未验证 提交 9d9c6c11 编写于 作者: D Don Syme 提交者: GitHub

Fix #13197 (#13870)

* Fix https://github.com/dotnet/fsharp/issues/13197

* format code
上级 38e7e575
......@@ -54,6 +54,14 @@ type PrimaryAssembly =
| System_Runtime -> "System.Runtime"
| NetStandard -> "netstandard"
static member IsPossiblePrimaryAssembly(fileName: string) =
let name = System.IO.Path.GetFileNameWithoutExtension(fileName)
String.Compare(name, "mscorlib", true) <> 0
|| String.Compare(name, "System.Runtime", true) <> 0
|| String.Compare(name, "netstandard", true) <> 0
|| String.Compare(name, "System.Private.CoreLib", true) <> 0
// --------------------------------------------------------------------
// Utilities: type names
// --------------------------------------------------------------------
......@@ -2803,12 +2811,16 @@ and [<Sealed>] ILTypeDefs(f: unit -> ILPreTypeDef[]) =
member x.GetEnumerator() =
(seq { for pre in array.Value -> pre.GetTypeDef() }).GetEnumerator()
member x.AsArrayOfPreTypeDefs() = array.Value
member _.AsArrayOfPreTypeDefs() = array.Value
member x.FindByName nm =
member _.FindByName nm =
let ns, n = splitILTypeName nm
dict.Value[ (ns, n) ].GetTypeDef()
member _.ExistsByName nm =
let ns, n = splitILTypeName nm
dict.Value.ContainsKey((ns, n))
and [<NoEquality; NoComparison>] ILPreTypeDef =
abstract Namespace: string list
abstract Name: string
......@@ -3331,15 +3343,9 @@ let tname_UIntPtr = "System.UIntPtr"
let tname_TypedReference = "System.TypedReference"
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
type ILGlobals
(
primaryScopeRef: ILScopeRef,
assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list,
fsharpCoreAssemblyScopeRef: ILScopeRef
) =
type ILGlobals(primaryScopeRef: ILScopeRef, equivPrimaryAssemblyRefs: ILAssemblyRef list, fsharpCoreAssemblyScopeRef: ILScopeRef) =
let assembliesThatForwardToPrimaryAssembly =
Array.ofList assembliesThatForwardToPrimaryAssembly
let equivPrimaryAssemblyRefs = Array.ofList equivPrimaryAssemblyRefs
let mkSysILTypeRef nm = mkILTyRef (primaryScopeRef, nm)
......@@ -3394,8 +3400,7 @@ type ILGlobals
member x.IsPossiblePrimaryAssemblyRef(aref: ILAssemblyRef) =
aref.EqualsIgnoringVersion x.primaryAssemblyRef
|| assembliesThatForwardToPrimaryAssembly
|> Array.exists aref.EqualsIgnoringVersion
|| equivPrimaryAssemblyRefs |> Array.exists aref.EqualsIgnoringVersion
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
......@@ -3403,8 +3408,8 @@ type ILGlobals
override x.ToString() = "<ILGlobals>"
let mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef) =
ILGlobals(primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef)
let mkILGlobals (primaryScopeRef, equivPrimaryAssemblyRefs, fsharpCoreAssemblyScopeRef) =
ILGlobals(primaryScopeRef, equivPrimaryAssemblyRefs, fsharpCoreAssemblyScopeRef)
let mkNormalCall mspec = I_call(Normalcall, mspec, None)
......
......@@ -8,6 +8,7 @@ open FSharp.Compiler.IO
open System.Collections.Generic
open System.Reflection
/// Represents the target primary assembly
[<RequireQualifiedAccess>]
type internal PrimaryAssembly =
| Mscorlib
......@@ -16,6 +17,11 @@ type internal PrimaryAssembly =
member Name: string
/// Checks if an assembly resolution may represent a primary assembly that actually contains the
/// definition of Sytem.Object. Note that the chosen target primary assembly may not actually be the one
/// that contains the definition of System.Object - it is just the one we are choosing to emit for.
static member IsPossiblePrimaryAssembly: fileName: string -> bool
/// Represents guids
type ILGuid = byte[]
......@@ -1407,12 +1413,12 @@ type ILTypeDefs =
/// Get some information about the type defs, but do not force the read of the type defs themselves.
member internal AsArrayOfPreTypeDefs: unit -> ILPreTypeDef[]
/// Calls to <c>FindByName</c> will result in any laziness in the overall
/// set of ILTypeDefs being read in in addition
/// to the details for the type found, but the remaining individual
/// type definitions will not be read.
/// Calls to <c>FindByName</c> will result in all the ILPreTypeDefs being read.
member internal FindByName: string -> ILTypeDef
/// Calls to <c>ExistsByName</c> will result in all the ILPreTypeDefs being read.
member internal ExistsByName: string -> bool
/// Represents IL Type Definitions.
[<NoComparison; NoEquality>]
type ILTypeDef =
......@@ -1841,10 +1847,11 @@ type internal ILGlobals =
member IsPossiblePrimaryAssemblyRef: ILAssemblyRef -> bool
/// Build the table of commonly used references given functions to find types in system assemblies
///
/// primaryScopeRef is the primary assembly we are emitting
/// equivPrimaryAssemblyRefs are ones regarded as equivalent
val internal mkILGlobals:
primaryScopeRef: ILScopeRef *
assembliesThatForwardToPrimaryAssembly: ILAssemblyRef list *
fsharpCoreAssemblyScopeRef: ILScopeRef ->
primaryScopeRef: ILScopeRef * equivPrimaryAssemblyRefs: ILAssemblyRef list * fsharpCoreAssemblyScopeRef: ILScopeRef ->
ILGlobals
val internal PrimaryAssemblyILGlobals: ILGlobals
......
......@@ -2321,13 +2321,13 @@ and [<Sealed>] TcImports
| _, [ ResolvedImportedAssembly ccu ] -> ccu.FSharpViewOfMetadata.ILScopeRef
| _ -> failwith "primaryScopeRef - unexpected"
let resolvedAssemblies = tcResolutions.GetAssemblyResolutions()
let primaryAssemblyResolvedPath =
match primaryAssemblyResolution with
| [ primaryAssemblyResolution ] -> primaryAssemblyResolution.resolvedPath
| _ -> failwith "primaryAssemblyResolvedPath - unexpected"
let resolvedAssemblies = tcResolutions.GetAssemblyResolutions()
let readerSettings: ILReaderOptions =
{
pdbDirPath = None
......@@ -2336,28 +2336,28 @@ and [<Sealed>] TcImports
tryGetMetadataSnapshot = tcConfig.tryGetMetadataSnapshot
}
let tryFindAssemblyByExportedType manifest (exportedType: ILExportedTypeOrForwarder) =
match exportedType.ScopeRef, primaryScopeRef with
| ILScopeRef.Assembly aref1, ILScopeRef.Assembly aref2 when aref1.EqualsIgnoringVersion aref2 ->
mkRefToILAssembly manifest |> Some
| _ -> None
let tryFindAssemblyThatForwardsToPrimaryAssembly manifest =
manifest.ExportedTypes.TryFindByName "System.Object"
|> Option.bind (tryFindAssemblyByExportedType manifest)
// Determine what other assemblies could have been the primary assembly
// by checking to see if "System.Object" is an exported type.
let assembliesThatForwardToPrimaryAssembly =
resolvedAssemblies
|> List.choose (fun resolvedAssembly ->
if primaryAssemblyResolvedPath <> resolvedAssembly.resolvedPath then
let reader = OpenILModuleReader resolvedAssembly.resolvedPath readerSettings
reader.ILModuleDef.Manifest
|> Option.bind tryFindAssemblyThatForwardsToPrimaryAssembly
else
None)
let tryFindEquivPrimaryAssembly (resolvedAssembly: AssemblyResolution) =
if primaryAssemblyResolvedPath = resolvedAssembly.resolvedPath then
None
else
let reader = OpenILModuleReader resolvedAssembly.resolvedPath readerSettings
let mdef = reader.ILModuleDef
// We check the exported types of all assemblies, since many may forward System.Object,
// but only check the actual type definitions for specific assemblies that we know
// might actually declare System.Object.
match mdef.Manifest with
| Some manifest when
manifest.ExportedTypes.TryFindByName "System.Object" |> Option.isSome
|| PrimaryAssembly.IsPossiblePrimaryAssembly resolvedAssembly.resolvedPath
&& mdef.TypeDefs.ExistsByName "System.Object"
->
mkRefToILAssembly manifest |> Some
| _ -> None
// Find assemblies which also declare System.Object
let equivPrimaryAssemblyRefs =
resolvedAssemblies |> List.choose tryFindEquivPrimaryAssembly
let! fslibCcu, fsharpCoreAssemblyScopeRef =
node {
......@@ -2406,7 +2406,7 @@ and [<Sealed>] TcImports
sysCcus |> Array.tryFind (fun ccu -> ccuHasType ccu path typeName)
let ilGlobals =
mkILGlobals (primaryScopeRef, assembliesThatForwardToPrimaryAssembly, fsharpCoreAssemblyScopeRef)
mkILGlobals (primaryScopeRef, equivPrimaryAssemblyRefs, fsharpCoreAssemblyScopeRef)
// OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals
let tcGlobals =
......
......@@ -6,6 +6,13 @@ open FluentAssertions
open FSharp.Compiler.Interactive.Shell
open FSharp.Test
open Xunit
open System.Threading
type Sentinel () =
let x = ()
module MyModule =
let test(x: int) = ()
[<Collection("SingleThreaded")>]
module FsiTests =
......@@ -636,3 +643,38 @@ module FsiTests =
let boundValue = fsiSession.GetBoundValues() |> List.exactlyOne
Assert.shouldBe typeof<CustomType2[,]> boundValue.Value.ReflectionType
boundValue.Value.ReflectionValue.Should().Be(mdArr, "") |> ignore
#if NETCOREAPP
[<Fact>]
let ``Evaluating simple reference and code succeeds under permutations``() =
for useSdkRefsFlag in ["/usesdkrefs"; "/usesdkrefs-"] do
for multiemitFlag in ["/multiemit"; "/multiemit-"] do
let config = FsiEvaluationSession.GetDefaultConfiguration()
let argv = [|
typeof<Sentinel>.Assembly.Location
"--noninteractive"
"--targetprofile:netcore"
"--langversion:preview"
multiemitFlag
useSdkRefsFlag
|]
let fsi = FsiEvaluationSession.Create(config, argv, TextReader.Null, TextWriter.Null, TextWriter.Null)
let assemblyPath = typeof<Sentinel>.Assembly.Location.Replace("\\", "/")
let code = $@"
#r ""{assemblyPath}""
FSharp.Compiler.UnitTests.MyModule.test(3)"
let ch, errors = fsi.EvalInteractionNonThrowing(code, CancellationToken.None)
errors
|> Array.iter (fun e -> printfn "error: %A" e)
match ch with
| Choice1Of2 v ->
let v =
match v with
| Some v -> sprintf "%A" v.ReflectionValue
| None -> "(none)"
printfn "value: %A" v
| Choice2Of2 e ->
printfn "exception: %A" e
raise e
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册