From 1947a4a12c408abe6fbfbb5f6442d3cef562f5d9 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 11 May 2021 17:50:35 -0700 Subject: [PATCH 1/9] Added a failing test --- src/fsharp/IlxGen.fs | 6 + src/fsharp/TcGlobals.fs | 2 + tests/FSharp.Test.Utilities/Compiler.fs | 4 +- tests/FSharp.Test.Utilities/CompilerAssert.fs | 109 +------------- tests/FSharp.Test.Utilities/Utilities.fs | 142 ++++++++++++++++++ .../InitOnlyPropertyConsumptionTests.fs | 53 +++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + 7 files changed, 209 insertions(+), 108 deletions(-) create mode 100644 tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index ab3f72dfb15..eb6166b602c 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -473,6 +473,12 @@ let GenReadOnlyModReqIfNecessary (g: TcGlobals) ty ilTy = else ilTy +let GenIsExternalInitModReq (g: TcGlobals) ilTy = + if g.tcref_System_Runtime_CompilerServices_IsExternalInit.CanDeref && g.tcref_System_Runtime_CompilerServices_IsExternalInit.IsILTycon then + ILType.Modified(true, g.tcref_System_Runtime_CompilerServices_IsExternalInit.CompiledRepresentationForNamedType, ilTy) + else + ilTy + let rec GenTypeArgAux amap m tyenv tyarg = GenTypeAux amap m tyenv VoidNotOK PtrTypesNotOK tyarg diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index dd4bf222c0d..704ad2caa36 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -1139,6 +1139,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member _.tcref_System_Attribute = v_System_Attribute_tcr + member val tcref_System_Runtime_CompilerServices_IsExternalInit = findSysTyconRef sysCompilerServices "System.Runtime.CompilerServices.IsExternalInit" + // Review: Does this need to be an option type? member val System_Runtime_CompilerServices_RuntimeFeature_ty = tryFindSysTyconRef sysCompilerServices "RuntimeFeature" |> Option.map mkNonGenericTy diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index c80b05bbdb9..0233c3f3954 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -122,8 +122,8 @@ module rec Compiler = | null -> failwith "Source cannot be null" | _ -> { Source = Text source - LangVersion = CSharpLanguageVersion.CSharp8 - TargetFramework = TargetFramework.NetCoreApp31 + LangVersion = CSharpLanguageVersion.CSharp9 + TargetFramework = TargetFramework.Current Name = None References = [] } diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index 240275139d4..c2f4e33607e 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -76,109 +76,6 @@ type CompilerAssert private () = static let checker = FSharpChecker.Create(suggestNamesForErrors=true) - static let config = TestFramework.initializeSuite () - - static let _ = config |> ignore - -// Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler - static let projectFile = """ - - - - Exe - $TARGETFRAMEWORK - true - true - - - - - - - - - - - - - - - - - - - - - - - -""" - - static let directoryBuildProps = """ - - -""" - - static let directoryBuildTargets = """ - - -""" - - static let programFs = """ -open System - -[] -let main argv = 0""" - - static let getNetCoreAppReferences = - let mutable output = "" - let mutable errors = "" - let mutable cleanUp = true - let pathToArtifacts = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "../../../..")) - if Path.GetFileName(pathToArtifacts) <> "artifacts" then failwith "CompilerAssert did not find artifacts directory --- has the location changed????" - let pathToTemp = Path.Combine(pathToArtifacts, "Temp") - let projectDirectory = Path.Combine(pathToTemp, "CompilerAssert", Path.GetRandomFileName()) - let pathToFSharpCore = typeof.Assembly.Location - try - try - Directory.CreateDirectory(projectDirectory) |> ignore - let projectFileName = Path.Combine(projectDirectory, "ProjectFile.fsproj") - let programFsFileName = Path.Combine(projectDirectory, "Program.fs") - let directoryBuildPropsFileName = Path.Combine(projectDirectory, "Directory.Build.props") - let directoryBuildTargetsFileName = Path.Combine(projectDirectory, "Directory.Build.targets") - let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt") -#if NETCOREAPP - File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net5.0").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) -#else - File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) -#endif - File.WriteAllText(programFsFileName, programFs) - File.WriteAllText(directoryBuildPropsFileName, directoryBuildProps) - File.WriteAllText(directoryBuildTargetsFileName, directoryBuildTargets) - - let timeout = 30000 - let exitCode, output, errors = Commands.executeProcess (Some config.DotNetExe) "build" projectDirectory timeout - - if exitCode <> 0 || errors.Length > 0 then - printfn "Output:\n=======\n" - output |> Seq.iter(fun line -> printfn "STDOUT:%s\n" line) - printfn "Errors:\n=======\n" - errors |> Seq.iter(fun line -> printfn "STDERR:%s\n" line) - Assert.True(false, "Errors produced generating References") - - File.ReadLines(frameworkReferencesFileName) |> Seq.toArray - with | e -> - cleanUp <- false - printfn "Project directory: %s" projectDirectory - printfn "STDOUT: %s" output - File.WriteAllText(Path.Combine(projectDirectory, "project.stdout"), output) - printfn "STDERR: %s" errors - File.WriteAllText(Path.Combine(projectDirectory, "project.stderror"), errors) - raise (new Exception (sprintf "An error occurred getting netcoreapp references: %A" e)) - finally - if cleanUp then - try Directory.Delete(projectDirectory, recursive=true) with | _ -> () - #if FX_NO_APP_DOMAINS static let executeBuiltApp assembly deps = let ctxt = AssemblyLoadContext("ContextName", true) @@ -214,7 +111,7 @@ let main argv = 0""" ProjectId = None SourceFiles = [|"test.fs"|] OtherOptions = - let assemblies = getNetCoreAppReferences |> Array.map (fun x -> sprintf "-r:%s" x) + let assemblies = TargetFrameworkUtil.currentReferences |> Array.map (fun x -> sprintf "-r:%s" x) #if NETCOREAPP Array.append [|"--preferreduilang:en-US"; "--targetprofile:netcore"; "--noframework"; "--simpleresolution"; "--warn:5"|] assemblies #else @@ -510,7 +407,7 @@ let main argv = 0""" let dependencies = #if NETCOREAPP - Array.toList getNetCoreAppReferences + Array.toList TargetFrameworkUtil.currentReferences #else [] #endif @@ -534,7 +431,7 @@ let main argv = 0""" let dependencies = #if NETCOREAPP - Array.toList getNetCoreAppReferences + Array.toList TargetFrameworkUtil.currentReferences #else [] #endif diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs index 762849037cf..69698120e64 100644 --- a/tests/FSharp.Test.Utilities/Utilities.fs +++ b/tests/FSharp.Test.Utilities/Utilities.fs @@ -10,6 +10,8 @@ open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.CSharp open System.Diagnostics open FSharp.Test.Utilities +open TestFramework +open NUnit.Framework // This file mimics how Roslyn handles their compilation references for compilation testing @@ -19,6 +21,7 @@ module Utilities = type TargetFramework = | NetStandard20 | NetCoreApp31 + | Current let private getResourceStream name = let assembly = typeof.GetTypeInfo().Assembly @@ -74,20 +77,157 @@ module Utilities = let systemDynamicRuntimeRef = lazy AssemblyMetadata.CreateFromImage(NetCoreApp31Refs.System_Dynamic_Runtime ()).GetReference(display = "System.Dynamic.Runtime.dll (netcoreapp 3.1 ref)") let systemConsoleRef = lazy AssemblyMetadata.CreateFromImage(NetCoreApp31Refs.System_Console ()).GetReference(display = "System.Console.dll (netcoreapp 3.1 ref)") + module private Net5Refs = + let mutable (_mscorlib: byte[]) = Unchecked.defaultof + let mutable (_netstandard: byte[]) = Unchecked.defaultof + let mutable (_System_Console: byte[]) = Unchecked.defaultof + let mutable (_System_Core: byte[]) = Unchecked.defaultof + let mutable (_System_Dynamic_Runtime: byte[]) = Unchecked.defaultof + let mutable (_System_Runtime: byte[]) = Unchecked.defaultof + let mscorlib () = getOrCreateResource &_mscorlib "mscorlib.dll" + let netstandard () = getOrCreateResource &_netstandard "netstandard.dll" + let System_Core () = getOrCreateResource &_System_Core "System.Core.dll" + let System_Console () = getOrCreateResource &_System_Console "System.Console.dll" + let System_Runtime () = getOrCreateResource &_System_Runtime "System.Runtime.dll" + let System_Dynamic_Runtime () = getOrCreateResource &_System_Dynamic_Runtime "System.Dynamic.Runtime.dll" + + [] + module Net5 = + let netStandard = lazy AssemblyMetadata.CreateFromImage(Net5Refs.netstandard ()).GetReference(display = "netstandard.dll (net5 ref)") + let mscorlibRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.mscorlib ()).GetReference(display = "mscorlib.dll (net5 ref)") + let systemRuntimeRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Runtime ()).GetReference(display = "System.Runtime.dll (net5 ref)") + let systemCoreRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Core ()).GetReference(display = "System.Core.dll (net5 ref)") + let systemDynamicRuntimeRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Dynamic_Runtime ()).GetReference(display = "System.Dynamic.Runtime.dll (net5 ref)") + let systemConsoleRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Console ()).GetReference(display = "System.Console.dll (net5 ref)") + [] module TargetFrameworkUtil = + let private config = TestFramework.initializeSuite () + + // Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler + let private projectFile = """ + + + + Exe + $TARGETFRAMEWORK + true + true + + + + + + + + + + + + + + + + + + + + + + + +""" + + let private directoryBuildProps = """ + + +""" + + let private directoryBuildTargets = """ + + +""" + + let private programFs = """ +open System + +[] +let main argv = 0""" + + let private getNetCoreAppReferences = + let mutable output = "" + let mutable errors = "" + let mutable cleanUp = true + let pathToArtifacts = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "../../../..")) + if Path.GetFileName(pathToArtifacts) <> "artifacts" then failwith "CompilerAssert did not find artifacts directory --- has the location changed????" + let pathToTemp = Path.Combine(pathToArtifacts, "Temp") + let projectDirectory = Path.Combine(pathToTemp, "CompilerAssert", Path.GetRandomFileName()) + let pathToFSharpCore = typeof.Assembly.Location + try + try + Directory.CreateDirectory(projectDirectory) |> ignore + let projectFileName = Path.Combine(projectDirectory, "ProjectFile.fsproj") + let programFsFileName = Path.Combine(projectDirectory, "Program.fs") + let directoryBuildPropsFileName = Path.Combine(projectDirectory, "Directory.Build.props") + let directoryBuildTargetsFileName = Path.Combine(projectDirectory, "Directory.Build.targets") + let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt") +#if NETCOREAPP + File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net5.0").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) +#else + File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) +#endif + File.WriteAllText(programFsFileName, programFs) + File.WriteAllText(directoryBuildPropsFileName, directoryBuildProps) + File.WriteAllText(directoryBuildTargetsFileName, directoryBuildTargets) + + let timeout = 30000 + let exitCode, output, errors = Commands.executeProcess (Some config.DotNetExe) "build" projectDirectory timeout + + if exitCode <> 0 || errors.Length > 0 then + printfn "Output:\n=======\n" + output |> Seq.iter(fun line -> printfn "STDOUT:%s\n" line) + printfn "Errors:\n=======\n" + errors |> Seq.iter(fun line -> printfn "STDERR:%s\n" line) + Assert.True(false, "Errors produced generating References") + + File.ReadLines(frameworkReferencesFileName) |> Seq.toArray + with | e -> + cleanUp <- false + printfn "Project directory: %s" projectDirectory + printfn "STDOUT: %s" output + File.WriteAllText(Path.Combine(projectDirectory, "project.stdout"), output) + printfn "STDERR: %s" errors + File.WriteAllText(Path.Combine(projectDirectory, "project.stderror"), errors) + raise (new Exception (sprintf "An error occurred getting netcoreapp references: %A" e)) + finally + if cleanUp then + try Directory.Delete(projectDirectory, recursive=true) with | _ -> () + open TestReferences let private netStandard20References = lazy ImmutableArray.Create(NetStandard20.netStandard.Value, NetStandard20.mscorlibRef.Value, NetStandard20.systemRuntimeRef.Value, NetStandard20.systemCoreRef.Value, NetStandard20.systemDynamicRuntimeRef.Value) let private netCoreApp31References = lazy ImmutableArray.Create(NetCoreApp31.netStandard.Value, NetCoreApp31.mscorlibRef.Value, NetCoreApp31.systemRuntimeRef.Value, NetCoreApp31.systemCoreRef.Value, NetCoreApp31.systemDynamicRuntimeRef.Value, NetCoreApp31.systemConsoleRef.Value) + let private net5References = + lazy ImmutableArray.Create(Net5.netStandard.Value, Net5.mscorlibRef.Value, Net5.systemRuntimeRef.Value, Net5.systemCoreRef.Value, Net5.systemDynamicRuntimeRef.Value, Net5.systemConsoleRef.Value) + + let currentReferences = + getNetCoreAppReferences + + let currentReferencesAsPEs = + getNetCoreAppReferences + |> Seq.map (fun x -> + PortableExecutableReference.CreateFromFile(x) + ) + |> ImmutableArray.CreateRange let getReferences tf = match tf with | TargetFramework.NetStandard20 -> netStandard20References.Value | TargetFramework.NetCoreApp31 -> netCoreApp31References.Value + | TargetFramework.Current -> currentReferencesAsPEs type RoslynLanguageVersion = LanguageVersion @@ -128,6 +268,7 @@ module Utilities = type CSharpLanguageVersion = | CSharp8 = 0 + | CSharp9 = 1 [] type CompilationUtil private () = @@ -136,6 +277,7 @@ module Utilities = let lv = match lv with | CSharpLanguageVersion.CSharp8 -> LanguageVersion.CSharp8 + | CSharpLanguageVersion.CSharp9 -> LanguageVersion.CSharp9 | _ -> LanguageVersion.Default let tf = defaultArg tf TargetFramework.NetStandard20 diff --git a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs new file mode 100644 index 00000000000..d000f6106c5 --- /dev/null +++ b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Test.Utilities.Compiler +open FSharp.Test.Utilities +open FSharp.Test.Utilities.Utilities +open FSharp.Tests + +#if NETCOREAPP + +[] +module InitOnlyPropertyConsumptionTests = + + [] + let ``Should be able to set an init-only property from a C# record`` () = + let csharpSource = + """ +using System; + +namespace CSharpTest +{ + public record Test + { + public int X { get; init; } + } +} + """ + + let fsharpSource = + """ +open System +open CSharpTest + +[] +let main _ = + let test = Test(X = 123) + Console.Write(test.X) + 0 + """ + + let csCmpl = + CompilationUtil.CreateCSharpCompilation(csharpSource, CSharpLanguageVersion.CSharp9, TargetFramework.Current) + |> CompilationReference.Create + + let fsCmpl = + Compilation.Create(fsharpSource, Fs, Exe, options = [|"--langversion:5.0"|], cmplRefs = [csCmpl]) + + CompilerAssert.ExecutionHasOutput(fsCmpl, "123") + +#endif + diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 6ba0c4a6a5d..ce4becaea00 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -40,6 +40,7 @@ + From cd2d6aa2f10febd1fd2834c793592de5ea067a48 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 11 May 2021 19:12:00 -0700 Subject: [PATCH 2/9] Adding an erased bridge for values for codegen --- src/fsharp/CheckExpressions.fs | 2 +- src/fsharp/IlxGen.fs | 34 ++++++++++++------- .../InitOnlyPropertyConsumptionTests.fs | 3 +- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index b06a6d2bcc6..8340a79ea53 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -8871,7 +8871,7 @@ and TcMethodApplication [], expr else // This holds the result of the call - let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct + let objv, objExpr = mkMutableCompGenLocal mMethExpr "$__bridge" exprty // mutable in case it's a struct // Build the expression that mutates the properties on the result of the call let setterExprPrebinders, propSetExpr = diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index eb6166b602c..411f065e2bb 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5777,7 +5777,11 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star | _ -> GenBindingRhs cenv cgbuf eenv SPSuppress vspec rhsExpr CommitStartScope cgbuf startScopeMarkOpt - GenStoreVal cenv cgbuf eenv vspec.Range vspec + if vspec.IsCompilerGenerated && vspec.LogicalName = "$__bridge" then + let ilTy = GenType cenv.amap m eenv.tyenv vspec.Type + CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) AI_dup + else + GenStoreVal cenv cgbuf eenv vspec.Range vspec //------------------------------------------------------------------------- // Generate method bindings @@ -6467,24 +6471,28 @@ and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) b // Generate locals and other storage of values //------------------------------------------------------------------------- -and GenSetVal cenv cgbuf eenv (vref, e, m) sequel = - let storage = StorageForValRef cenv.g m vref eenv - match storage with - | Env (ilCloTy, _, _) -> - CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 - | _ -> - () - GenExpr cenv cgbuf eenv SPSuppress e Continue - GenSetStorage vref.Range cgbuf storage - GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel +and GenSetVal cenv cgbuf eenv (vref: ValRef, e, m) sequel = + if vref.IsCompilerGenerated && vref.LogicalName = "$__bridge" then () + else + let storage = StorageForValRef cenv.g m vref eenv + match storage with + | Env (ilCloTy, _, _) -> + CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 + | _ -> + () + GenExpr cenv cgbuf eenv SPSuppress e Continue + GenSetStorage vref.Range cgbuf storage + GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel and GenGetValRefAndSequel cenv cgbuf eenv m (v: ValRef) storeSequel = let ty = v.Type GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) (StorageForValRef cenv.g m v eenv) storeSequel and GenGetVal cenv cgbuf eenv (v: ValRef, m) sequel = - GenGetValRefAndSequel cenv cgbuf eenv m v None - GenSequel cenv eenv.cloc cgbuf sequel + if v.IsCompilerGenerated && v.LogicalName = "$__bridge" then () + else + GenGetValRefAndSequel cenv cgbuf eenv m v None + GenSequel cenv eenv.cloc cgbuf sequel and GenBindingRhs cenv cgbuf eenv sp (vspec: Val) e = let g = cenv.g diff --git a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs index d000f6106c5..b7c7155fe91 100644 --- a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs +++ b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs @@ -35,8 +35,7 @@ open CSharpTest [] let main _ = - let test = Test(X = 123) - Console.Write(test.X) + Test(X = 123) |> ignore 0 """ From cb83ee2420d917b0ba09872903be85019b15fc37 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 11 May 2021 19:59:26 -0700 Subject: [PATCH 3/9] Not really working --- src/fsharp/IlxGen.fs | 4 ++-- .../Compiler/Language/InitOnlyPropertyConsumptionTests.fs | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 411f065e2bb..62c6e2d7a33 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5778,8 +5778,8 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star GenBindingRhs cenv cgbuf eenv SPSuppress vspec rhsExpr CommitStartScope cgbuf startScopeMarkOpt if vspec.IsCompilerGenerated && vspec.LogicalName = "$__bridge" then - let ilTy = GenType cenv.amap m eenv.tyenv vspec.Type - CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) AI_dup + //let ilTy = GenType cenv.amap m eenv.tyenv vspec.Type + CG.EmitInstr cgbuf (pop 0) Push0 AI_dup else GenStoreVal cenv cgbuf eenv vspec.Range vspec diff --git a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs index b7c7155fe91..7664d7a9026 100644 --- a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs +++ b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs @@ -31,11 +31,17 @@ namespace CSharpTest let fsharpSource = """ open System +open System.Runtime.CompilerServices open CSharpTest +[] +let test() = + Test(X = 1) + [] let main _ = - Test(X = 123) |> ignore + let _x = test() + Console.Write("123") 0 """ From c01ee8ae55b3155ed06c33b02106b310fc6302fb Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 12 May 2021 07:27:05 -0700 Subject: [PATCH 4/9] revert changes --- src/fsharp/CheckExpressions.fs | 2 +- src/fsharp/IlxGen.fs | 32 ++++++++++++-------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 8340a79ea53..b06a6d2bcc6 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -8871,7 +8871,7 @@ and TcMethodApplication [], expr else // This holds the result of the call - let objv, objExpr = mkMutableCompGenLocal mMethExpr "$__bridge" exprty // mutable in case it's a struct + let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct // Build the expression that mutates the properties on the result of the call let setterExprPrebinders, propSetExpr = diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 62c6e2d7a33..4a6dfbe0055 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5777,11 +5777,7 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star | _ -> GenBindingRhs cenv cgbuf eenv SPSuppress vspec rhsExpr CommitStartScope cgbuf startScopeMarkOpt - if vspec.IsCompilerGenerated && vspec.LogicalName = "$__bridge" then - //let ilTy = GenType cenv.amap m eenv.tyenv vspec.Type - CG.EmitInstr cgbuf (pop 0) Push0 AI_dup - else - GenStoreVal cenv cgbuf eenv vspec.Range vspec + GenStoreVal cenv cgbuf eenv vspec.Range vspec //------------------------------------------------------------------------- // Generate method bindings @@ -6472,27 +6468,23 @@ and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) b //------------------------------------------------------------------------- and GenSetVal cenv cgbuf eenv (vref: ValRef, e, m) sequel = - if vref.IsCompilerGenerated && vref.LogicalName = "$__bridge" then () - else - let storage = StorageForValRef cenv.g m vref eenv - match storage with - | Env (ilCloTy, _, _) -> - CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 - | _ -> - () - GenExpr cenv cgbuf eenv SPSuppress e Continue - GenSetStorage vref.Range cgbuf storage - GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel + let storage = StorageForValRef cenv.g m vref eenv + match storage with + | Env (ilCloTy, _, _) -> + CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 + | _ -> + () + GenExpr cenv cgbuf eenv SPSuppress e Continue + GenSetStorage vref.Range cgbuf storage + GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel and GenGetValRefAndSequel cenv cgbuf eenv m (v: ValRef) storeSequel = let ty = v.Type GenGetStorageAndSequel cenv cgbuf eenv m (ty, GenType cenv.amap m eenv.tyenv ty) (StorageForValRef cenv.g m v eenv) storeSequel and GenGetVal cenv cgbuf eenv (v: ValRef, m) sequel = - if v.IsCompilerGenerated && v.LogicalName = "$__bridge" then () - else - GenGetValRefAndSequel cenv cgbuf eenv m v None - GenSequel cenv eenv.cloc cgbuf sequel + GenGetValRefAndSequel cenv cgbuf eenv m v None + GenSequel cenv eenv.cloc cgbuf sequel and GenBindingRhs cenv cgbuf eenv sp (vspec: Val) e = let g = cenv.g From 2b65519ac3baaaad8b0e56d83b35ac91664c1bc5 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 12 May 2021 08:07:25 -0700 Subject: [PATCH 5/9] Added stripILModifiedFromTy. Fixed setter from emitting an extra pop --- src/fsharp/MethodCalls.fs | 2 +- src/fsharp/absil/il.fs | 6 ++++++ src/fsharp/absil/il.fsi | 3 +++ .../Compiler/Language/InitOnlyPropertyConsumptionTests.fs | 7 +++---- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 94fbd7ff60f..0cd10e2fc4e 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -767,7 +767,7 @@ let BuildILMethInfoCall g amap m isProp (minfo: ILMethInfo) valUseFlags minst di let ilMethRef = minfo.ILMethodRef let newobj = ctor && (match valUseFlags with NormalValUse -> true | _ -> false) let exprTy = if ctor then minfo.ApparentEnclosingType else minfo.GetFSharpReturnTy(amap, m, minst) - let retTy = if not ctor && ilMethRef.ReturnType = ILType.Void then [] else [exprTy] + let retTy = if not ctor && (stripILModifiedFromTy ilMethRef.ReturnType) = ILType.Void then [] else [exprTy] let isDllImport = minfo.IsDllImport g Expr.Op (TOp.ILCall (useCallvirt, isProtected, valu, newobj, valUseFlags, isProp, isDllImport, ilMethRef, minfo.DeclaringTypeInst, minst, retTy), [], args, m), exprTy diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index a93aac6893b..609bcb0511c 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -2722,6 +2722,12 @@ let isILBoxedTy = function ILType.Boxed _ -> true | _ -> false let isILValueTy = function ILType.Value _ -> true | _ -> false +/// Strips ILType.Modified from the ILType. +let rec stripILModifiedFromTy (ty: ILType) = + match ty with + | ILType.Modified(_, _, ty) -> stripILModifiedFromTy ty + | _ -> ty + let isBuiltInTySpec (ilg: ILGlobals) (tspec: ILTypeSpec) n = let tref = tspec.TypeRef let scoref = tref.Scope diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index 2f8b44a627b..14ce112b1d6 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -2002,6 +2002,9 @@ val internal instILType: ILGenericArgs -> ILType -> ILType /// This is a 'vendor neutral' way of referencing mscorlib. val internal ecmaPublicKey: PublicKey +/// Strips ILType.Modified from the ILType. +val internal stripILModifiedFromTy: ILType -> ILType + /// Discriminating different important built-in types. val internal isILObjectTy: ILGlobals -> ILType -> bool val internal isILStringTy: ILGlobals -> ILType -> bool diff --git a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs index 7664d7a9026..fb210986b49 100644 --- a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs +++ b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs @@ -34,14 +34,13 @@ open System open System.Runtime.CompilerServices open CSharpTest -[] let test() = - Test(X = 1) + Test(X = 123) [] let main _ = - let _x = test() - Console.Write("123") + let x = test() + Console.Write(x) 0 """ From a0b804289db9bca27767fe7c618b176a35789658 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 12 May 2021 08:08:12 -0700 Subject: [PATCH 6/9] Fixing test --- .../Compiler/Language/InitOnlyPropertyConsumptionTests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs index fb210986b49..eca26290cec 100644 --- a/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs +++ b/tests/fsharp/Compiler/Language/InitOnlyPropertyConsumptionTests.fs @@ -40,7 +40,7 @@ let test() = [] let main _ = let x = test() - Console.Write(x) + Console.Write(x.X) 0 """ From a74cd79f1996359132c5597fd41980e42d373495 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 12 May 2021 08:10:25 -0700 Subject: [PATCH 7/9] Reverting a few changes --- src/fsharp/IlxGen.fs | 10 ++-------- src/fsharp/TcGlobals.fs | 2 -- tests/FSharp.Test.Utilities/Utilities.fs | 25 ------------------------ 3 files changed, 2 insertions(+), 35 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 4a6dfbe0055..b7a8ba38bad 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -471,13 +471,7 @@ let GenReadOnlyModReqIfNecessary (g: TcGlobals) ty ilTy = if add then ILType.Modified(true, g.attrib_InAttribute.TypeRef, ilTy) else - ilTy - -let GenIsExternalInitModReq (g: TcGlobals) ilTy = - if g.tcref_System_Runtime_CompilerServices_IsExternalInit.CanDeref && g.tcref_System_Runtime_CompilerServices_IsExternalInit.IsILTycon then - ILType.Modified(true, g.tcref_System_Runtime_CompilerServices_IsExternalInit.CompiledRepresentationForNamedType, ilTy) - else - ilTy + ilTy let rec GenTypeArgAux amap m tyenv tyarg = GenTypeAux amap m tyenv VoidNotOK PtrTypesNotOK tyarg @@ -6467,7 +6461,7 @@ and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) b // Generate locals and other storage of values //------------------------------------------------------------------------- -and GenSetVal cenv cgbuf eenv (vref: ValRef, e, m) sequel = +and GenSetVal cenv cgbuf eenv (vref, e, m) sequel = let storage = StorageForValRef cenv.g m vref eenv match storage with | Env (ilCloTy, _, _) -> diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 704ad2caa36..dd4bf222c0d 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -1139,8 +1139,6 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member _.tcref_System_Attribute = v_System_Attribute_tcr - member val tcref_System_Runtime_CompilerServices_IsExternalInit = findSysTyconRef sysCompilerServices "System.Runtime.CompilerServices.IsExternalInit" - // Review: Does this need to be an option type? member val System_Runtime_CompilerServices_RuntimeFeature_ty = tryFindSysTyconRef sysCompilerServices "RuntimeFeature" |> Option.map mkNonGenericTy diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs index 69698120e64..fa02e829b7b 100644 --- a/tests/FSharp.Test.Utilities/Utilities.fs +++ b/tests/FSharp.Test.Utilities/Utilities.fs @@ -77,29 +77,6 @@ module Utilities = let systemDynamicRuntimeRef = lazy AssemblyMetadata.CreateFromImage(NetCoreApp31Refs.System_Dynamic_Runtime ()).GetReference(display = "System.Dynamic.Runtime.dll (netcoreapp 3.1 ref)") let systemConsoleRef = lazy AssemblyMetadata.CreateFromImage(NetCoreApp31Refs.System_Console ()).GetReference(display = "System.Console.dll (netcoreapp 3.1 ref)") - module private Net5Refs = - let mutable (_mscorlib: byte[]) = Unchecked.defaultof - let mutable (_netstandard: byte[]) = Unchecked.defaultof - let mutable (_System_Console: byte[]) = Unchecked.defaultof - let mutable (_System_Core: byte[]) = Unchecked.defaultof - let mutable (_System_Dynamic_Runtime: byte[]) = Unchecked.defaultof - let mutable (_System_Runtime: byte[]) = Unchecked.defaultof - let mscorlib () = getOrCreateResource &_mscorlib "mscorlib.dll" - let netstandard () = getOrCreateResource &_netstandard "netstandard.dll" - let System_Core () = getOrCreateResource &_System_Core "System.Core.dll" - let System_Console () = getOrCreateResource &_System_Console "System.Console.dll" - let System_Runtime () = getOrCreateResource &_System_Runtime "System.Runtime.dll" - let System_Dynamic_Runtime () = getOrCreateResource &_System_Dynamic_Runtime "System.Dynamic.Runtime.dll" - - [] - module Net5 = - let netStandard = lazy AssemblyMetadata.CreateFromImage(Net5Refs.netstandard ()).GetReference(display = "netstandard.dll (net5 ref)") - let mscorlibRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.mscorlib ()).GetReference(display = "mscorlib.dll (net5 ref)") - let systemRuntimeRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Runtime ()).GetReference(display = "System.Runtime.dll (net5 ref)") - let systemCoreRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Core ()).GetReference(display = "System.Core.dll (net5 ref)") - let systemDynamicRuntimeRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Dynamic_Runtime ()).GetReference(display = "System.Dynamic.Runtime.dll (net5 ref)") - let systemConsoleRef = lazy AssemblyMetadata.CreateFromImage(Net5Refs.System_Console ()).GetReference(display = "System.Console.dll (net5 ref)") - [] module TargetFrameworkUtil = @@ -210,8 +187,6 @@ let main argv = 0""" lazy ImmutableArray.Create(NetStandard20.netStandard.Value, NetStandard20.mscorlibRef.Value, NetStandard20.systemRuntimeRef.Value, NetStandard20.systemCoreRef.Value, NetStandard20.systemDynamicRuntimeRef.Value) let private netCoreApp31References = lazy ImmutableArray.Create(NetCoreApp31.netStandard.Value, NetCoreApp31.mscorlibRef.Value, NetCoreApp31.systemRuntimeRef.Value, NetCoreApp31.systemCoreRef.Value, NetCoreApp31.systemDynamicRuntimeRef.Value, NetCoreApp31.systemConsoleRef.Value) - let private net5References = - lazy ImmutableArray.Create(Net5.netStandard.Value, Net5.mscorlibRef.Value, Net5.systemRuntimeRef.Value, Net5.systemCoreRef.Value, Net5.systemDynamicRuntimeRef.Value, Net5.systemConsoleRef.Value) let currentReferences = getNetCoreAppReferences From 089f494357230052e79ebc91ab0b194e9ad4b025 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 12 May 2021 08:15:05 -0700 Subject: [PATCH 8/9] remove extra spaces --- src/fsharp/IlxGen.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index b7a8ba38bad..ab3f72dfb15 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -471,7 +471,7 @@ let GenReadOnlyModReqIfNecessary (g: TcGlobals) ty ilTy = if add then ILType.Modified(true, g.attrib_InAttribute.TypeRef, ilTy) else - ilTy + ilTy let rec GenTypeArgAux amap m tyenv tyarg = GenTypeAux amap m tyenv VoidNotOK PtrTypesNotOK tyarg From 3d8c5404ab8e9c72d916b904be539c2d72bf489d Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 12 May 2021 08:25:34 -0700 Subject: [PATCH 9/9] Remove redundant comment --- src/fsharp/absil/il.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index 609bcb0511c..a2e1f0ee3ec 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -2722,7 +2722,6 @@ let isILBoxedTy = function ILType.Boxed _ -> true | _ -> false let isILValueTy = function ILType.Value _ -> true | _ -> false -/// Strips ILType.Modified from the ILType. let rec stripILModifiedFromTy (ty: ILType) = match ty with | ILType.Modified(_, _, ty) -> stripILModifiedFromTy ty