未验证 提交 2c3ff6d1 编写于 作者: D Don Syme 提交者: GitHub

fix 12761 (#13865)

上级 2b391ff2
...@@ -6804,7 +6804,13 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenvouter takenN ...@@ -6804,7 +6804,13 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenvouter takenN
NestedTypeRefForCompLoc eenvouter.cloc cloName NestedTypeRefForCompLoc eenvouter.cloc cloName
// Collect the free variables of the closure // Collect the free variables of the closure
let cloFreeVarResults = freeInExpr (CollectTyparsAndLocalsWithStackGuard()) expr let cloFreeVarResults =
let opts = CollectTyparsAndLocalsWithStackGuard()
let opts =
match eenvouter.tyenv.TemplateReplacement with
| None -> opts
| Some (tcref, _, typars, _) -> opts.WithTemplateReplacement(tyconRefEq g tcref, typars)
freeInExpr opts expr
// Partition the free variables when some can be accessed from places besides the immediate environment // Partition the free variables when some can be accessed from places besides the immediate environment
// Also filter out the current value being bound, if any, as it is available from the "this" // Also filter out the current value being bound, if any, as it is available from the "this"
......
...@@ -2133,7 +2133,10 @@ type FreeVarOptions = ...@@ -2133,7 +2133,10 @@ type FreeVarOptions =
includeRecdFields: bool includeRecdFields: bool
includeUnionCases: bool includeUnionCases: bool
includeLocals: bool includeLocals: bool
templateReplacement: ((TyconRef -> bool) * Typars) option
stackGuard: StackGuard option } stackGuard: StackGuard option }
member this.WithTemplateReplacement(f, typars) = { this with templateReplacement = Some (f, typars) }
let CollectAllNoCaching = let CollectAllNoCaching =
{ canCache = false { canCache = false
...@@ -2144,6 +2147,7 @@ let CollectAllNoCaching = ...@@ -2144,6 +2147,7 @@ let CollectAllNoCaching =
includeUnionCases = true includeUnionCases = true
includeTypars = true includeTypars = true
includeLocals = true includeLocals = true
templateReplacement = None
stackGuard = None} stackGuard = None}
let CollectTyparsNoCaching = let CollectTyparsNoCaching =
...@@ -2155,6 +2159,7 @@ let CollectTyparsNoCaching = ...@@ -2155,6 +2159,7 @@ let CollectTyparsNoCaching =
includeRecdFields = false includeRecdFields = false
includeUnionCases = false includeUnionCases = false
includeLocals = false includeLocals = false
templateReplacement = None
stackGuard = None } stackGuard = None }
let CollectLocalsNoCaching = let CollectLocalsNoCaching =
...@@ -2166,6 +2171,7 @@ let CollectLocalsNoCaching = ...@@ -2166,6 +2171,7 @@ let CollectLocalsNoCaching =
includeRecdFields = false includeRecdFields = false
includeUnionCases = false includeUnionCases = false
includeLocals = true includeLocals = true
templateReplacement = None
stackGuard = None } stackGuard = None }
let CollectTyparsAndLocalsNoCaching = let CollectTyparsAndLocalsNoCaching =
...@@ -2177,6 +2183,7 @@ let CollectTyparsAndLocalsNoCaching = ...@@ -2177,6 +2183,7 @@ let CollectTyparsAndLocalsNoCaching =
includeUnionCases = false includeUnionCases = false
includeTypars = true includeTypars = true
includeLocals = true includeLocals = true
templateReplacement = None
stackGuard = None } stackGuard = None }
let CollectAll = let CollectAll =
...@@ -2188,6 +2195,7 @@ let CollectAll = ...@@ -2188,6 +2195,7 @@ let CollectAll =
includeUnionCases = true includeUnionCases = true
includeTypars = true includeTypars = true
includeLocals = true includeLocals = true
templateReplacement = None
stackGuard = None } stackGuard = None }
let CollectTyparsAndLocalsImpl stackGuardOpt = // CollectAll let CollectTyparsAndLocalsImpl stackGuardOpt = // CollectAll
...@@ -2199,6 +2207,7 @@ let CollectTyparsAndLocalsImpl stackGuardOpt = // CollectAll ...@@ -2199,6 +2207,7 @@ let CollectTyparsAndLocalsImpl stackGuardOpt = // CollectAll
includeLocalTyconReprs = false includeLocalTyconReprs = false
includeRecdFields = false includeRecdFields = false
includeUnionCases = false includeUnionCases = false
templateReplacement = None
stackGuard = stackGuardOpt } stackGuard = stackGuardOpt }
...@@ -2219,12 +2228,18 @@ let accFreeLocalTycon opts x acc = ...@@ -2219,12 +2228,18 @@ let accFreeLocalTycon opts x acc =
if Zset.contains x acc.FreeTycons then acc else if Zset.contains x acc.FreeTycons then acc else
{ acc with FreeTycons = Zset.add x acc.FreeTycons } { acc with FreeTycons = Zset.add x acc.FreeTycons }
let accFreeTycon opts (tcref: TyconRef) acc = let rec accFreeTycon opts (tcref: TyconRef) acc =
let acc =
match opts.templateReplacement with
| Some (isTemplateTyconRef, cloFreeTyvars) when isTemplateTyconRef tcref ->
let cloInst = List.map mkTyparTy cloFreeTyvars
accFreeInTypes opts cloInst acc
| _ -> acc
if not opts.includeLocalTycons then acc if not opts.includeLocalTycons then acc
elif tcref.IsLocalRef then accFreeLocalTycon opts tcref.ResolvedTarget acc elif tcref.IsLocalRef then accFreeLocalTycon opts tcref.ResolvedTarget acc
else acc else acc
let rec boundTypars opts tps acc = and boundTypars opts tps acc =
// Bound type vars form a recursively-referential set due to constraints, e.g. A: I<B>, B: I<A> // Bound type vars form a recursively-referential set due to constraints, e.g. A: I<B>, B: I<A>
// So collect up free vars in all constraints first, then bind all variables // So collect up free vars in all constraints first, then bind all variables
let acc = List.foldBack (fun (tp: Typar) acc -> accFreeInTyparConstraints opts tp.Constraints acc) tps acc let acc = List.foldBack (fun (tp: Typar) acc -> accFreeInTyparConstraints opts tp.Constraints acc) tps acc
......
...@@ -796,7 +796,12 @@ val emptyFreeLocals: FreeLocals ...@@ -796,7 +796,12 @@ val emptyFreeLocals: FreeLocals
val unionFreeLocals: FreeLocals -> FreeLocals -> FreeLocals val unionFreeLocals: FreeLocals -> FreeLocals -> FreeLocals
type FreeVarOptions /// Represents the options to activate when collecting free variables
[<Sealed>]
type FreeVarOptions =
/// During backend code generation of state machines, register a template replacement for struct types.
/// This may introduce new free variables related to the instantiation of the struct type.
member WithTemplateReplacement: (TyconRef -> bool) * Typars -> FreeVarOptions
val CollectLocalsNoCaching: FreeVarOptions val CollectLocalsNoCaching: FreeVarOptions
......
...@@ -1259,6 +1259,75 @@ type BasicsNotInParallel() = ...@@ -1259,6 +1259,75 @@ type BasicsNotInParallel() =
require ran "never ran") require ran "never ran")
taskOuter.Wait() taskOuter.Wait()
[<Fact; >]
member _.testGenericBackgroundTasks() =
printfn "Running testBackgroundTask..."
for i in 1 .. 5 do
let mutable ran = false
let mutable posted = false
let oldSyncContext = SynchronizationContext.Current
let syncContext = { new SynchronizationContext() with member _.Post(d,state) = posted <- true; d.Invoke(state) }
try
SynchronizationContext.SetSynchronizationContext syncContext
let f (result: 'T ref) (x: 'T) =
backgroundTask {
require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expect to be on background thread"
ran <- true
result.Value <- x
}
let t = f (ref "") "hello"
t.Wait()
let t2 = f (ref 1) 1
t2.Wait()
require ran "never ran"
require (not posted) "did not expect post to sync context"
finally
SynchronizationContext.SetSynchronizationContext oldSyncContext
/// https://github.com/dotnet/fsharp/issues/12761
module Test12761A =
type Dto = {
DtoValue : string
Key : string
}
type MyGenericType<'Key,'Value> = {
Value : 'Value
Key : 'Key
}
type ProblematicType<'Key, 'Value, 'Dto, 'E>( fromDto : 'Dto -> Result<MyGenericType<'Key,'Value>,'E> ) =
let myTask =
backgroundTask {
let dto = """{"DtoValue":"1","Key":"key1"}""" |> box |> unbox<'Dto>
return fromDto dto |> printfn "%A"
}
member __.ContainsKey = fun (key: 'Key) -> true
type MyType = MyGenericType<string,int>
module MyType =
let fromDto (dto: Dto) =
try
{
Value = int dto.DtoValue
Key = dto.Key
}
|> Ok
with | e -> Error e
/// https://github.com/dotnet/fsharp/issues/12761
module Test12761B =
let TestFunction<'Dto>() =
backgroundTask {
let dto = Unchecked.defaultof<'Dto>
System.Console.WriteLine(dto)
}
type Issue12184() = type Issue12184() =
member this.TaskMethod() = member this.TaskMethod() =
task { task {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册