@@ -34,8 +34,8 @@ open FSharp.Compiler.AbstractIL.ILBinaryReader
3434open FSharp.Compiler .AbstractIL .Internal
3535open FSharp.Compiler .AbstractIL .Internal .Library
3636open FSharp.Compiler .AbstractIL .Diagnostics
37- open FSharp.Compiler .IlxGen
3837
38+ open FSharp.Compiler .IlxGen
3939open FSharp.Compiler .AccessibilityLogic
4040open FSharp.Compiler .AttributeChecking
4141open FSharp.Compiler .Ast
@@ -1109,13 +1109,80 @@ module MainModuleBuilder =
11091109//----------------------------------------------------------------------------
11101110
11111111/// Optional static linking of all DLLs that depend on the F# Library, plus other specified DLLs
1112- module StaticLinker =
1112+ module StaticLinker =
1113+
1114+ open FSharp.Compiler .AbstractIL
1115+
1116+ // Handles TypeForwarding for the generated IL model
1117+ type TypeForwarding ( tcImports : TcImports ) =
1118+
1119+ // Make a dictionary of ccus passed to the compiler will be looked up by qualified assembly name
1120+ let ccuThunksQualifiedName =
1121+ tcImports.GetCcusInDeclOrder()
1122+ |> List.filter( fun ccuThunk -> ccuThunk.QualifiedName |> Option.isSome)
1123+ |> List.map( fun ccuThunk -> ccuThunk.QualifiedName |> Option.defaultValue " Assembly Name Not Passed" , ccuThunk)
1124+ |> dict
1125+
1126+ // 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
1127+ let ccuThunksSimpleName =
1128+ tcImports.GetCcusInDeclOrder()
1129+ |> List.filter( fun ccuThunk -> not ( String.IsNullOrEmpty( ccuThunk.AssemblyName)))
1130+ |> List.map( fun ccuThunk -> ccuThunk.AssemblyName, ccuThunk)
1131+ |> dict
1132+
1133+ let followTypeForwardForILTypeRef ( tref : ILTypeRef ) =
1134+ let typename =
1135+ let parts = tref.FullName.Split([| '.' |])
1136+ match parts.Length with
1137+ | 0 -> None
1138+ | 1 -> Some ( Array.empty< string>, parts.[ 0 ])
1139+ | n -> Some ( parts.[ 0 .. n-2 ], parts.[ n-1 ])
1140+
1141+ let scoref = tref.Scope
1142+ match scoref with
1143+ | ILScopeRef.Assembly scope ->
1144+ match ccuThunksQualifiedName.TryGetValue( scope.QualifiedName) with
1145+ | true , ccu ->
1146+ match typename with
1147+ | Some ( parts, name) ->
1148+ let forwarded = ccu.TryForward( parts, name)
1149+ let result =
1150+ match forwarded with
1151+ | Some fwd -> fwd.CompilationPath.ILScopeRef
1152+ | None -> scoref
1153+ result
1154+ | None -> scoref
1155+ | false , _ ->
1156+ // Couldn't find an assembly with the version so try using a simple name
1157+ match ccuThunksSimpleName.TryGetValue( scope.Name) with
1158+ | true , ccu ->
1159+ match typename with
1160+ | Some ( parts, name) ->
1161+ let forwarded = ccu.TryForward( parts, name)
1162+ let result =
1163+ match forwarded with
1164+ | Some fwd -> fwd.CompilationPath.ILScopeRef
1165+ | None -> scoref
1166+ result
1167+ | None -> scoref
1168+ | false , _ -> scoref
1169+ | _ -> scoref
1170+
1171+ let typeForwardILTypeRef ( tref : ILTypeRef ) =
1172+ let scoref1 = tref.Scope
1173+ let scoref2 = followTypeForwardForILTypeRef tref
1174+ if scoref1 === scoref2 then tref
1175+ else ILTypeRef.Create ( scoref2, tref.Enclosing, tref.Name)
1176+
1177+ member __.TypeForwardILTypeRef tref = typeForwardILTypeRef tref
1178+
11131179 let debugStaticLinking = condition " FSHARP_DEBUG_STATIC_LINKING"
11141180
1115- let StaticLinkILModules ( tcConfig , ilGlobals , ilxMainModule , dependentILModules : ( CcuThunk option * ILModuleDef ) list ) =
1181+ let StaticLinkILModules ( tcConfig : TcConfig , ilGlobals , tcImports , ilxMainModule , dependentILModules : ( CcuThunk option * ILModuleDef ) list ) =
11161182 if isNil dependentILModules then
11171183 ilxMainModule, ( fun x -> x)
11181184 else
1185+ let typeForwarding = new TypeForwarding( tcImports)
11191186
11201187 // Check no dependent assemblies use quotations
11211188 let dependentCcuUsingQuotations = dependentILModules |> List.tryPick ( function ( Some ccu, _) when ccu.UsesFSharp20PlusQuotations -> Some ccu | _ -> None)
@@ -1201,13 +1268,15 @@ module StaticLinker =
12011268 ( mkILMethods ( topTypeDefs |> List.collect ( fun td -> td.Methods.AsList)),
12021269 mkILFields ( topTypeDefs |> List.collect ( fun td -> td.Fields.AsList)))
12031270
1204- let ilxMainModule =
1205- { ilxMainModule with
1206- Manifest = ( let m = ilxMainModule.ManifestOfAssembly in Some { m with CustomAttrsStored = storeILCustomAttrs ( mkILCustomAttrs ( m.CustomAttrs.AsList @ savedManifestAttrs)) })
1207- CustomAttrsStored = storeILCustomAttrs ( mkILCustomAttrs [ for m in moduls do yield ! m.CustomAttrs.AsArray ])
1208- TypeDefs = mkILTypeDefs ( topTypeDef :: List.concat normalTypeDefs)
1209- Resources = mkILResources ( savedResources @ ilxMainModule.Resources.AsList)
1210- NativeResources = savedNativeResources }
1271+ let ilxMainModule =
1272+ let main =
1273+ { ilxMainModule with
1274+ Manifest = ( let m = ilxMainModule.ManifestOfAssembly in Some { m with CustomAttrsStored = storeILCustomAttrs ( mkILCustomAttrs ( m.CustomAttrs.AsList @ savedManifestAttrs)) })
1275+ CustomAttrsStored = storeILCustomAttrs ( mkILCustomAttrs [ for m in moduls do yield ! m.CustomAttrs.AsArray ])
1276+ TypeDefs = mkILTypeDefs ( topTypeDef :: List.concat normalTypeDefs)
1277+ Resources = mkILResources ( savedResources @ ilxMainModule.Resources.AsList)
1278+ NativeResources = savedNativeResources }
1279+ Morphs.morphILTypeRefsInILModuleMemoized ilGlobals typeForwarding.TypeForwardILTypeRef main
12111280
12121281 ilxMainModule, rewriteExternalRefsToLocalRefs
12131282
@@ -1578,8 +1647,8 @@ module StaticLinker =
15781647
15791648 // Glue all this stuff into ilxMainModule
15801649 let ilxMainModule , rewriteExternalRefsToLocalRefs =
1581- StaticLinkILModules ( tcConfig, ilGlobals, ilxMainModule, dependentILModules @ providerGeneratedILModules)
1582-
1650+ StaticLinkILModules ( tcConfig, ilGlobals, tcImports , ilxMainModule, dependentILModules @ providerGeneratedILModules)
1651+
15831652 // Rewrite type and assembly references
15841653 let ilxMainModule =
15851654 let isMscorlib = ilGlobals.primaryAssemblyName = PrimaryAssembly.Mscorlib.Name
0 commit comments