Skip to content
Merged
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
93 changes: 81 additions & 12 deletions src/fsharp/fsc.fs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ open FSharp.Compiler.AbstractIL.ILBinaryReader
open FSharp.Compiler.AbstractIL.Internal
open FSharp.Compiler.AbstractIL.Internal.Library
open FSharp.Compiler.AbstractIL.Diagnostics
open FSharp.Compiler.IlxGen

open FSharp.Compiler.IlxGen
open FSharp.Compiler.AccessibilityLogic
open FSharp.Compiler.AttributeChecking
open FSharp.Compiler.Ast
Expand Down Expand Up @@ -1109,13 +1109,80 @@ module MainModuleBuilder =
//----------------------------------------------------------------------------

/// Optional static linking of all DLLs that depend on the F# Library, plus other specified DLLs
module StaticLinker =
module StaticLinker =

open FSharp.Compiler.AbstractIL

// Handles TypeForwarding for the generated IL model
type TypeForwarding (tcImports: TcImports) =

// Make a dictionary of ccus passed to the compiler will be looked up by qualified assembly name
let ccuThunksQualifiedName =
tcImports.GetCcusInDeclOrder()
|> List.filter(fun ccuThunk -> ccuThunk.QualifiedName |> Option.isSome)
|> List.map(fun ccuThunk -> ccuThunk.QualifiedName |> Option.defaultValue "Assembly Name Not Passed", ccuThunk)
|> dict

// If we can't type forward using exact assembly match, we need to rely on the loader (Policy, Configuration or the coreclr load heuristics), so use try simple name
let ccuThunksSimpleName =
tcImports.GetCcusInDeclOrder()
|> List.filter(fun ccuThunk -> not (String.IsNullOrEmpty(ccuThunk.AssemblyName)))
|> List.map(fun ccuThunk -> ccuThunk.AssemblyName, ccuThunk)
|> dict

let followTypeForwardForILTypeRef (tref:ILTypeRef) =
let typename =
let parts = tref.FullName.Split([|'.'|])
match parts.Length with
| 0 -> None
| 1 -> Some (Array.empty<string>, parts.[0])
| n -> Some (parts.[0..n-2], parts.[n-1])

let scoref = tref.Scope
match scoref with
| ILScopeRef.Assembly scope ->
match ccuThunksQualifiedName.TryGetValue(scope.QualifiedName) with
| true, ccu ->
match typename with
| Some (parts, name) ->
let forwarded = ccu.TryForward(parts, name)
let result =
match forwarded with
| Some fwd -> fwd.CompilationPath.ILScopeRef
| None -> scoref
result
| None -> scoref
| false, _ ->
// Couldn't find an assembly with the version so try using a simple name
match ccuThunksSimpleName.TryGetValue(scope.Name) with
| true, ccu ->
match typename with
| Some (parts, name) ->
let forwarded = ccu.TryForward(parts, name)
let result =
match forwarded with
| Some fwd -> fwd.CompilationPath.ILScopeRef
| None -> scoref
result
| None -> scoref
| false, _ -> scoref
| _ -> scoref

let typeForwardILTypeRef (tref: ILTypeRef) =
let scoref1 = tref.Scope
let scoref2 = followTypeForwardForILTypeRef tref
if scoref1 === scoref2 then tref
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

===

wat

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-)
I read that operator as "is the same as"
It is defined here: https://github.com/dotnet/fsharp/blob/master/src/absil/illib.fs#L44

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, so it's objEq (box x) (box y)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not =?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not instance equality, it's are the contents equal.

else ILTypeRef.Create (scoref2, tref.Enclosing, tref.Name)

member __.TypeForwardILTypeRef tref = typeForwardILTypeRef tref

let debugStaticLinking = condition "FSHARP_DEBUG_STATIC_LINKING"

let StaticLinkILModules (tcConfig, ilGlobals, ilxMainModule, dependentILModules: (CcuThunk option * ILModuleDef) list) =
let StaticLinkILModules (tcConfig:TcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules: (CcuThunk option * ILModuleDef) list) =
if isNil dependentILModules then
ilxMainModule, (fun x -> x)
else
let typeForwarding = new TypeForwarding(tcImports)

// Check no dependent assemblies use quotations
let dependentCcuUsingQuotations = dependentILModules |> List.tryPick (function (Some ccu, _) when ccu.UsesFSharp20PlusQuotations -> Some ccu | _ -> None)
Expand Down Expand Up @@ -1201,13 +1268,15 @@ module StaticLinker =
(mkILMethods (topTypeDefs |> List.collect (fun td -> td.Methods.AsList)),
mkILFields (topTypeDefs |> List.collect (fun td -> td.Fields.AsList)))

let ilxMainModule =
{ ilxMainModule with
Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (m.CustomAttrs.AsList @ savedManifestAttrs)) })
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsArray ])
TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs)
Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList)
NativeResources = savedNativeResources }
let ilxMainModule =
let main =
{ ilxMainModule with
Manifest = (let m = ilxMainModule.ManifestOfAssembly in Some {m with CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (m.CustomAttrs.AsList @ savedManifestAttrs)) })
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs [ for m in moduls do yield! m.CustomAttrs.AsArray ])
TypeDefs = mkILTypeDefs (topTypeDef :: List.concat normalTypeDefs)
Resources = mkILResources (savedResources @ ilxMainModule.Resources.AsList)
NativeResources = savedNativeResources }
Morphs.morphILTypeRefsInILModuleMemoized ilGlobals typeForwarding.TypeForwardILTypeRef main

ilxMainModule, rewriteExternalRefsToLocalRefs

Expand Down Expand Up @@ -1578,8 +1647,8 @@ module StaticLinker =

// Glue all this stuff into ilxMainModule
let ilxMainModule, rewriteExternalRefsToLocalRefs =
StaticLinkILModules (tcConfig, ilGlobals, ilxMainModule, dependentILModules @ providerGeneratedILModules)
StaticLinkILModules (tcConfig, ilGlobals, tcImports, ilxMainModule, dependentILModules @ providerGeneratedILModules)

// Rewrite type and assembly references
let ilxMainModule =
let isMscorlib = ilGlobals.primaryAssemblyName = PrimaryAssembly.Mscorlib.Name
Expand Down