Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 69 additions & 80 deletions src/Compiler/Driver/CompilerImports.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2247,110 +2247,99 @@ and [<Sealed>] TcImports
phase2

// NOTE: When used in the Language Service this can cause the transitive checking of projects. Hence it must be cancellable.
member tcImports.TryRegisterAndPrepareToImportReferencedDll
(ctok, r: AssemblyResolution)
: Async<(_ * (unit -> AvailableImportedAssembly list)) option> =
async {
CheckDisposed()
let m = r.originalReference.Range
let fileName = r.resolvedPath
member tcImports.RegisterAndImportReferencedAssemblies(ctok, nms: AssemblyResolution list) =
let tryGetAssemblyData (r: AssemblyResolution) =
async {
CheckDisposed()
let m = r.originalReference.Range
let fileName = r.resolvedPath

let! contentsOpt =
async {
match r.ProjectReference with
| Some ilb -> return! ilb.EvaluateRawContents()
| None -> return ProjectAssemblyDataResult.Unavailable true
}
try

// If we have a project reference but did not get any valid contents,
// just return None and do not attempt to read elsewhere.
match contentsOpt with
| ProjectAssemblyDataResult.Unavailable false -> return None
| _ ->
let! contentsOpt =
async {
match r.ProjectReference with
| Some ilb -> return! ilb.EvaluateRawContents()
| None -> return ProjectAssemblyDataResult.Unavailable true
}

let assemblyData =
// If we have a project reference but did not get any valid contents,
// just return None and do not attempt to read elsewhere.
match contentsOpt with
| ProjectAssemblyDataResult.Available ilb -> ilb
| ProjectAssemblyDataResult.Unavailable _ ->
let ilModule, ilAssemblyRefs = tcImports.OpenILBinaryModule(ctok, fileName, m)
RawFSharpAssemblyDataBackedByFileOnDisk(ilModule, ilAssemblyRefs) :> IRawFSharpAssemblyData
| ProjectAssemblyDataResult.Unavailable false -> return None
| _ ->

match contentsOpt with
| ProjectAssemblyDataResult.Available ilb -> return Some(r, ilb)
| ProjectAssemblyDataResult.Unavailable _ ->
let ilModule, ilAssemblyRefs = tcImports.OpenILBinaryModule(ctok, fileName, m)
return Some(r, RawFSharpAssemblyDataBackedByFileOnDisk(ilModule, ilAssemblyRefs))

with e ->
errorR (Error(FSComp.SR.buildProblemReadingAssembly (fileName, e.Message), m))
return None
}

let ilShortAssemName = assemblyData.ShortAssemblyName
let ilScopeRef = assemblyData.ILScopeRef
let registerDll (r: AssemblyResolution, assemblyData: IRawFSharpAssemblyData) =
let m = r.originalReference.Range
let fileName = r.resolvedPath
let ilShortAssemName = assemblyData.ShortAssemblyName
let ilScopeRef = assemblyData.ILScopeRef

if tcImports.IsAlreadyRegistered ilShortAssemName then
let dllinfo = tcImports.FindDllInfo(ctok, m, ilShortAssemName)
if tcImports.IsAlreadyRegistered ilShortAssemName then

let phase2 () =
[ tcImports.FindCcuInfo(ctok, m, ilShortAssemName, lookupOnly = true) ]
let phase2 () =
[ tcImports.FindCcuInfo(ctok, m, ilShortAssemName, lookupOnly = true) ]

return Some(dllinfo, phase2)
else
let dllinfo =
{
RawMetadata = assemblyData
FileName = fileName
async { return phase2 () }
else
let dllinfo =
{
RawMetadata = assemblyData
FileName = fileName
#if !NO_TYPEPROVIDERS
ProviderGeneratedAssembly = None
IsProviderGenerated = false
ProviderGeneratedStaticLinkMap = None
ProviderGeneratedAssembly = None
IsProviderGenerated = false
ProviderGeneratedStaticLinkMap = None
#endif
ILScopeRef = ilScopeRef
ILAssemblyRefs = assemblyData.ILAssemblyRefs
}
ILScopeRef = ilScopeRef
ILAssemblyRefs = assemblyData.ILAssemblyRefs
}

tcImports.RegisterDll dllinfo
tcImports.RegisterDll dllinfo

let phase2 =
if assemblyData.HasAnyFSharpSignatureDataAttribute then
if not assemblyData.HasMatchingFSharpSignatureDataAttribute then
errorR (Error(FSComp.SR.buildDifferentVersionMustRecompile fileName, m))
tcImports.PrepareToImportReferencedILAssembly(ctok, m, fileName, dllinfo)
else
try
tcImports.PrepareToImportReferencedFSharpAssembly(ctok, m, fileName, dllinfo)
with e ->
error (Error(FSComp.SR.buildErrorOpeningBinaryFile (fileName, e.Message), m))
else
let phase2 =
if assemblyData.HasAnyFSharpSignatureDataAttribute then
if not assemblyData.HasMatchingFSharpSignatureDataAttribute then
errorR (Error(FSComp.SR.buildDifferentVersionMustRecompile fileName, m))
tcImports.PrepareToImportReferencedILAssembly(ctok, m, fileName, dllinfo)
else
try
tcImports.PrepareToImportReferencedFSharpAssembly(ctok, m, fileName, dllinfo)
with e ->
error (Error(FSComp.SR.buildErrorOpeningBinaryFile (fileName, e.Message), m))
else
tcImports.PrepareToImportReferencedILAssembly(ctok, m, fileName, dllinfo)

return Some(dllinfo, phase2)
}
async { return phase2 () }

// NOTE: When used in the Language Service this can cause the transitive checking of projects. Hence it must be cancellable.
member tcImports.RegisterAndImportReferencedAssemblies(ctok, nms: AssemblyResolution list) =
async {
CheckDisposed()

let tcConfig = tcConfigP.Get ctok
let! assemblyData = nms |> List.map tryGetAssemblyData |> MultipleDiagnosticsLoggers.Parallel

let runMethod =
match tcConfig.parallelReferenceResolution with
| ParallelReferenceResolution.On -> MultipleDiagnosticsLoggers.Parallel
| ParallelReferenceResolution.Off -> MultipleDiagnosticsLoggers.Sequential
// Preserve determinicstic order of references, because types from later assemblies may shadow earlier ones.
let phase2s = assemblyData |> Seq.choose id |> Seq.map registerDll |> List.ofSeq

let! results =
nms
|> List.map (fun nm ->
async {
try
use _ = new CompilationGlobalsScope()
return! tcImports.TryRegisterAndPrepareToImportReferencedDll(ctok, nm)
with e ->
errorR (Error(FSComp.SR.buildProblemReadingAssembly (nm.resolvedPath, e.Message), nm.originalReference.Range))
return None
})
|> runMethod

let _dllinfos, phase2s = results |> Array.choose id |> List.ofArray |> List.unzip
fixupOrphanCcus ()
let ccuinfos = List.collect (fun phase2 -> phase2 ()) phase2s

let! ccuinfos = phase2s |> MultipleDiagnosticsLoggers.Parallel

if importsBase.IsSome then
importsBase.Value.CcuTable.Values |> Seq.iter addConstraintSources
ccuTable.Values |> Seq.iter addConstraintSources

return ccuinfos
return ccuinfos |> List.concat
}

/// Note that implicit loading is not used for compilations from MSBuild, which passes ``--noframework``
Expand All @@ -2376,7 +2365,7 @@ and [<Sealed>] TcImports
ReportWarnings warns

tcImports.RegisterAndImportReferencedAssemblies(ctok, res)
|> Async.RunImmediate
|> Async.RunSynchronously
|> ignore

true
Expand Down Expand Up @@ -2684,7 +2673,7 @@ let RequireReferences (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, reso

let ccuinfos =
tcImports.RegisterAndImportReferencedAssemblies(ctok, resolutions)
|> Async.RunImmediate
|> Async.RunSynchronously

let asms =
ccuinfos
Expand Down
Loading