@@ -1586,8 +1586,10 @@ and [<Sealed>] TcImports
15861586
15871587#if ! NO_ TYPEPROVIDERS
15881588 member private tcImports.AttachDisposeTypeProviderAction action =
1589- CheckDisposed()
1590- disposeTypeProviderActions.Add action
1589+ tciLock.AcquireLock( fun tcitok ->
1590+ CheckDisposed()
1591+ RequireTcImportsLock( tcitok, disposeTypeProviderActions)
1592+ disposeTypeProviderActions.Add action)
15911593#endif
15921594
15931595 // Note: the returned binary reader is associated with the tcImports, i.e. when the tcImports are closed
@@ -2247,110 +2249,106 @@ and [<Sealed>] TcImports
22472249 phase2
22482250
22492251 // NOTE: When used in the Language Service this can cause the transitive checking of projects. Hence it must be cancellable.
2250- member tcImports.TryRegisterAndPrepareToImportReferencedDll
2251- ( ctok , r : AssemblyResolution )
2252- : Async <( _ * ( unit -> AvailableImportedAssembly list )) option > =
2253- async {
2254- CheckDisposed()
2255- let m = r.originalReference.Range
2256- let fileName = r.resolvedPath
2252+ member tcImports.RegisterAndImportReferencedAssemblies ( ctok , nms : AssemblyResolution list ) =
2253+ let tryGetAssemblyData ( r : AssemblyResolution ) =
2254+ async {
2255+ CheckDisposed()
2256+ let m = r.originalReference.Range
2257+ let fileName = r.resolvedPath
22572258
2258- let! contentsOpt =
2259- async {
2260- match r.ProjectReference with
2261- | Some ilb -> return ! ilb.EvaluateRawContents()
2262- | None -> return ProjectAssemblyDataResult.Unavailable true
2263- }
2259+ try
22642260
2265- // If we have a project reference but did not get any valid contents,
2266- // just return None and do not attempt to read elsewhere.
2267- match contentsOpt with
2268- | ProjectAssemblyDataResult.Unavailable false -> return None
2269- | _ ->
2261+ let! contentsOpt =
2262+ async {
2263+ match r.ProjectReference with
2264+ | Some ilb -> return ! ilb.EvaluateRawContents()
2265+ | None -> return ProjectAssemblyDataResult.Unavailable true
2266+ }
22702267
2271- let assemblyData =
2268+ // If we have a project reference but did not get any valid contents,
2269+ // just return None and do not attempt to read elsewhere.
22722270 match contentsOpt with
2273- | ProjectAssemblyDataResult.Available ilb -> ilb
2274- | ProjectAssemblyDataResult.Unavailable _ ->
2275- let ilModule , ilAssemblyRefs = tcImports.OpenILBinaryModule( ctok, fileName, m)
2276- RawFSharpAssemblyDataBackedByFileOnDisk( ilModule, ilAssemblyRefs) :> IRawFSharpAssemblyData
2271+ | ProjectAssemblyDataResult.Unavailable false -> return None
2272+ | _ ->
2273+
2274+ match contentsOpt with
2275+ | ProjectAssemblyDataResult.Available ilb -> return Some( r, ilb)
2276+ | ProjectAssemblyDataResult.Unavailable _ ->
2277+ let ilModule , ilAssemblyRefs = tcImports.OpenILBinaryModule( ctok, fileName, m)
2278+ return Some( r, RawFSharpAssemblyDataBackedByFileOnDisk( ilModule, ilAssemblyRefs))
2279+
2280+ with e ->
2281+ errorR ( Error( FSComp.SR.buildProblemReadingAssembly ( fileName, e.Message), m))
2282+ return None
2283+ }
22772284
2278- let ilShortAssemName = assemblyData.ShortAssemblyName
2279- let ilScopeRef = assemblyData.ILScopeRef
2285+ let registerDll ( r : AssemblyResolution , assemblyData : IRawFSharpAssemblyData ) =
2286+ let m = r.originalReference.Range
2287+ let fileName = r.resolvedPath
2288+ let ilShortAssemName = assemblyData.ShortAssemblyName
2289+ let ilScopeRef = assemblyData.ILScopeRef
22802290
2281- if tcImports.IsAlreadyRegistered ilShortAssemName then
2282- let dllinfo = tcImports.FindDllInfo( ctok, m, ilShortAssemName)
2291+ if tcImports.IsAlreadyRegistered ilShortAssemName then
22832292
2284- let phase2 () =
2285- [ tcImports.FindCcuInfo( ctok, m, ilShortAssemName, lookupOnly = true ) ]
2293+ let phase2 () =
2294+ [ tcImports.FindCcuInfo( ctok, m, ilShortAssemName, lookupOnly = true ) ]
22862295
2287- return Some ( dllinfo , phase2)
2288- else
2289- let dllinfo =
2290- {
2291- RawMetadata = assemblyData
2292- FileName = fileName
2296+ async { return phase2 () }
2297+ else
2298+ let dllinfo =
2299+ {
2300+ RawMetadata = assemblyData
2301+ FileName = fileName
22932302#if ! NO_ TYPEPROVIDERS
2294- ProviderGeneratedAssembly = None
2295- IsProviderGenerated = false
2296- ProviderGeneratedStaticLinkMap = None
2303+ ProviderGeneratedAssembly = None
2304+ IsProviderGenerated = false
2305+ ProviderGeneratedStaticLinkMap = None
22972306#endif
2298- ILScopeRef = ilScopeRef
2299- ILAssemblyRefs = assemblyData.ILAssemblyRefs
2300- }
2307+ ILScopeRef = ilScopeRef
2308+ ILAssemblyRefs = assemblyData.ILAssemblyRefs
2309+ }
23012310
2302- tcImports.RegisterDll dllinfo
2311+ tcImports.RegisterDll dllinfo
23032312
2304- let phase2 =
2305- if assemblyData.HasAnyFSharpSignatureDataAttribute then
2306- if not assemblyData.HasMatchingFSharpSignatureDataAttribute then
2307- errorR ( Error( FSComp.SR.buildDifferentVersionMustRecompile fileName, m))
2308- tcImports.PrepareToImportReferencedILAssembly( ctok, m, fileName, dllinfo)
2309- else
2310- try
2311- tcImports.PrepareToImportReferencedFSharpAssembly( ctok, m, fileName, dllinfo)
2312- with e ->
2313- error ( Error( FSComp.SR.buildErrorOpeningBinaryFile ( fileName, e.Message), m))
2314- else
2313+ let phase2 =
2314+ if assemblyData.HasAnyFSharpSignatureDataAttribute then
2315+ if not assemblyData.HasMatchingFSharpSignatureDataAttribute then
2316+ errorR ( Error( FSComp.SR.buildDifferentVersionMustRecompile fileName, m))
23152317 tcImports.PrepareToImportReferencedILAssembly( ctok, m, fileName, dllinfo)
2318+ else
2319+ try
2320+ tcImports.PrepareToImportReferencedFSharpAssembly( ctok, m, fileName, dllinfo)
2321+ with e ->
2322+ error ( Error( FSComp.SR.buildErrorOpeningBinaryFile ( fileName, e.Message), m))
2323+ else
2324+ tcImports.PrepareToImportReferencedILAssembly( ctok, m, fileName, dllinfo)
23162325
2317- return Some( dllinfo, phase2)
2318- }
2326+ async { return phase2 () }
23192327
2320- // NOTE: When used in the Language Service this can cause the transitive checking of projects. Hence it must be cancellable.
2321- member tcImports.RegisterAndImportReferencedAssemblies ( ctok , nms : AssemblyResolution list ) =
23222328 async {
23232329 CheckDisposed()
23242330
23252331 let tcConfig = tcConfigP.Get ctok
23262332
2327- let runMethod =
2333+ let runMethod computations =
23282334 match tcConfig.parallelReferenceResolution with
2329- | ParallelReferenceResolution.On -> MultipleDiagnosticsLoggers.Parallel
2330- | ParallelReferenceResolution.Off -> MultipleDiagnosticsLoggers.Sequential
2335+ | ParallelReferenceResolution.On -> MultipleDiagnosticsLoggers.Parallel computations
2336+ | ParallelReferenceResolution.Off -> MultipleDiagnosticsLoggers.Sequential computations
2337+
2338+ let! assemblyData = nms |> List.map tryGetAssemblyData |> runMethod
2339+
2340+ // Preserve determinicstic order of references, because types from later assemblies may shadow earlier ones.
2341+ let phase2s = assemblyData |> Seq.choose id |> Seq.map registerDll |> List.ofSeq
23312342
2332- let! results =
2333- nms
2334- |> List.map ( fun nm ->
2335- async {
2336- try
2337- use _ = new CompilationGlobalsScope()
2338- return ! tcImports.TryRegisterAndPrepareToImportReferencedDll( ctok, nm)
2339- with e ->
2340- errorR ( Error( FSComp.SR.buildProblemReadingAssembly ( nm.resolvedPath, e.Message), nm.originalReference.Range))
2341- return None
2342- })
2343- |> runMethod
2344-
2345- let _dllinfos , phase2s = results |> Array.choose id |> List.ofArray |> List.unzip
23462343 fixupOrphanCcus ()
2347- let ccuinfos = List.collect ( fun phase2 -> phase2 ()) phase2s
2344+
2345+ let! ccuinfos = phase2s |> runMethod
23482346
23492347 if importsBase.IsSome then
23502348 importsBase.Value.CcuTable.Values |> Seq.iter addConstraintSources
23512349 ccuTable.Values |> Seq.iter addConstraintSources
23522350
2353- return ccuinfos
2351+ return ccuinfos |> List.concat
23542352 }
23552353
23562354 /// Note that implicit loading is not used for compilations from MSBuild, which passes ``--noframework``
@@ -2376,7 +2374,7 @@ and [<Sealed>] TcImports
23762374 ReportWarnings warns
23772375
23782376 tcImports.RegisterAndImportReferencedAssemblies( ctok, res)
2379- |> Async.RunImmediate
2377+ |> Async.RunSynchronously
23802378 |> ignore
23812379
23822380 true
@@ -2684,7 +2682,7 @@ let RequireReferences (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, reso
26842682
26852683 let ccuinfos =
26862684 tcImports.RegisterAndImportReferencedAssemblies( ctok, resolutions)
2687- |> Async.RunImmediate
2685+ |> Async.RunSynchronously
26882686
26892687 let asms =
26902688 ccuinfos
0 commit comments