@@ -9275,13 +9275,13 @@ namespace ProviderImplementation.ProvidedTypes
92759275 let typeTableFwd = Dictionary<Type, Type>()
92769276 let typeTableBwd = Dictionary<Type, Type>()
92779277
9278- // Guards the type translation tables above. The F# compiler may translate types on several
9279- // threads at once (e.g. ParallelCompilation, on by default in recent .NET SDKs). The
9280- // check-then-create in convProvidedTypeDefToTgt must be atomic: without this lock, two
9281- // concurrent conversions of the same source ProvidedTypeDefinition each mint a distinct
9282- // target type, and the compiler then fails intermittently with FS0193/FS0001
9283- // "type X is not compatible with type X" on erased provided types . Monitor is re-entrant,
9284- // so the recursive conversion of declaring/base/argument types on the same thread is fine.
9278+ // Guards the translation tables above (type, var, and assembly) . The F# compiler may
9279+ // translate types on several threads at once (e.g. ParallelCompilation, on by default in
9280+ // recent .NET SDKs). The check-then-create in convProvidedTypeDefToTgt, convVarToTgt/Src,
9281+ // and convProvidedAssembly must be atomic: without this lock, two concurrent conversions
9282+ // of the same source object each mint a distinct target copy, leading to FS0193/FS0001
9283+ // or ArgumentException on duplicate Dictionary keys . Monitor is re-entrant, so recursive
9284+ // conversion of declaring/base/argument types on the same thread is fine.
92859285 let typeTablesLock = obj()
92869286
92879287 let fixName (fullName:string) =
@@ -9475,14 +9475,15 @@ namespace ProviderImplementation.ProvidedTypes
94759475 | Choice2Of2 res -> res
94769476
94779477 and convVarToSrc (v: Var) =
9478+ lock typeTablesLock (fun () ->
94789479 match varTableBwd.TryGetValue v with
94799480 | true, v -> v
94809481 | false, _ ->
94819482 let newVar = Var (v.Name, convTypeToSrc v.Type, v.IsMutable)
94829483 // store the original var as we'll have to revert to it later
94839484 varTableBwd.Add(v, newVar)
94849485 varTableFwd.Add(newVar, v)
9485- newVar
9486+ newVar)
94869487
94879488 and convVarExprToSrc quotation =
94889489 match quotation with
@@ -9491,6 +9492,7 @@ namespace ProviderImplementation.ProvidedTypes
94919492 | _ -> failwithf "Unexpected non-variable argument: %A" quotation
94929493
94939494 and convVarToTgt (v: Var) =
9495+ lock typeTablesLock (fun () ->
94949496 match varTableFwd.TryGetValue v with
94959497 | true, v -> v
94969498 | false, _ ->
@@ -9499,7 +9501,7 @@ namespace ProviderImplementation.ProvidedTypes
94999501 // store it so we reuse it from now on
95009502 varTableFwd.Add(v, newVar)
95019503 varTableBwd.Add(newVar, v)
9502- newVar
9504+ newVar)
95039505
95049506
95059507 and convExprToTgt quotation =
@@ -9806,19 +9808,20 @@ namespace ProviderImplementation.ProvidedTypes
98069808 convMemberDefToTgt declTyT x :?> ProvidedMethod
98079809
98089810 and convProvidedAssembly (assembly: ProvidedAssembly) =
9809- match assemblyTableFwd.TryGetValue(assembly) with
9810- | true, newT -> newT
9811- | false, _ ->
9812- let tgtAssembly = ProvidedAssembly(true, assembly.GetName(), assembly.Location, K(convCustomAttributesDataToTgt(assembly.GetCustomAttributesData())))
9811+ lock typeTablesLock (fun () ->
9812+ match assemblyTableFwd.TryGetValue(assembly) with
9813+ | true, newT -> newT
9814+ | false, _ ->
9815+ let tgtAssembly = ProvidedAssembly(true, assembly.GetName(), assembly.Location, K(convCustomAttributesDataToTgt(assembly.GetCustomAttributesData())))
98139816
9814- for (types, enclosingGeneratedTypeNames) in assembly.GetTheTypes() do
9815- let typesT = Array.map convProvidedTypeDefToTgt types
9816- tgtAssembly.AddTheTypes (typesT, enclosingGeneratedTypeNames)
9817+ for (types, enclosingGeneratedTypeNames) in assembly.GetTheTypes() do
9818+ let typesT = Array.map convProvidedTypeDefToTgt types
9819+ tgtAssembly.AddTheTypes (typesT, enclosingGeneratedTypeNames)
98179820
9818- assemblyTableFwd.Add(assembly, tgtAssembly)
9819- this.AddSourceAssembly(assembly)
9820- this.AddTargetAssembly(assembly.GetName(), tgtAssembly)
9821- (tgtAssembly :> Assembly)
9821+ assemblyTableFwd.Add(assembly, tgtAssembly)
9822+ this.AddSourceAssembly(assembly)
9823+ this.AddTargetAssembly(assembly.GetName(), tgtAssembly)
9824+ (tgtAssembly :> Assembly) )
98229825
98239826 let rec convNamespaceToTgt (x: IProvidedNamespace) =
98249827 { new IProvidedNamespace with
0 commit comments