Code is not sufficiently generic
NinoFloris opened this issue · comments
Was porting an old project (netcoreapp2.2) to 3.1 today, noticed something that did compile back then that doesn't anymore.
This code is not sufficiently generic. The type variable ^TEntity when ^TEntity : not struct could not be generalized because it would escape its scope
Note the compiler inferred an SRTP type var ^TEntity
here even though no SRTP constraints are used.
open FSharp.Control.Tasks.V2.ContextInsensitive
open Microsoft.EntityFrameworkCore
type DbSet<'TEntity when 'TEntity: not struct> with
member this.TryFindAsync(keyValues) = task {
let! r = this.FindAsync(keyValues)
if obj.ReferenceEquals(r, null) then return ValueNone
else return ValueSome r
}
What seems to have happened here is EF moving from returning Task<'T>
in 2.x to ValueTask<'T>
in 3.x that caused this error to surface.
I've produced a minimal repro
open FSharp.Control.Tasks.V2.ContextInsensitive
type Foo<'T> =
member this.FindAsync() = ValueTask<_>(Unchecked.defaultof<'T>)
member this.TryFindAsync() = task {
let! r = this.FindAsync()
if obj.ReferenceEquals(r, null) then return ValueNone
else return ValueSome r
}
My hunch is something is iffy around the SRTP based 'tasklike' Bind
as ValueTask isn't directly supported.
Also, adding inline
to the new member TryFindAsync
to potentially flow the SRTP var doesn't work either and returns a different error:
The signature and implementation are not compatible because the type parameter in the class/signature has a different compile-time requirement to the one in the member/implementation
Finally to confirm my hunch I tried this code in Ply under netstandard2.0
, where Ply has no explicit ValueTask
overloads, only similar tasklike support, and under netcoreapp2.2
(which does have the overloads) both compile without errors. Something is going wrong with the SRTP constrained overloads in Taskbuilder.
/cc: @gusty