diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 8f41152c420..69e2c483ddf 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -1840,7 +1840,10 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial mBinds scopem mutRecNSInfo (env | SynMemberDefn.ImplicitCtor _ :: _ -> () | _ -> if not tcref.IsFSharpEnumTycon && not tcref.IsFSharpDelegateTycon && not tcref.IsFSharpException && not tcref.IsTypeAbbrev then - TyconBindingDefn(containerInfo, newslotsOK, declKind, None, tcref.Range) + if members |> List.exists (function | SynMemberDefn.LetBindings(isStatic=true) -> true | _ -> false ) then + // Introduction of this member has caused the regression #16009, due to a missed Lazy<>.Force access from a member to a value in recursive module + // Minimizing the impact by only yielding in case of actually emitting static let bindings. + TyconBindingDefn(containerInfo, newslotsOK, declKind, None, tcref.Range) // Yield the other members for memb in members do diff --git a/src/Compiler/Checking/CheckIncrementalClasses.fs b/src/Compiler/Checking/CheckIncrementalClasses.fs index 6452c7b224c..8ef4d3734f9 100644 --- a/src/Compiler/Checking/CheckIncrementalClasses.fs +++ b/src/Compiler/Checking/CheckIncrementalClasses.fs @@ -756,7 +756,6 @@ let MakeCtorForIncrClassConstructionPhase2C( /// binding in the implicit class construction sequence let TransTrueDec isCtorArg (reps: IncrClassReprInfo) dec = match dec with - // Pokud to neni staticke, a zaroven to nema construktor info, tak zkusit vyhnout se TransBind mozna? | IncrClassBindingGroup(binds, isStatic, isRec) -> let actions, reps, methodBinds = let reps = (reps, binds) ||> List.fold (fun rep bind -> rep.ChooseAndAddRepresentation(cenv, env, isStatic, isCtorArg, staticCtorInfo, ctorInfoOpt, staticForcedFieldVars, instanceForcedFieldVars, bind)) // extend diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/StaticLet/StaticLetInUnionsAndRecords.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/StaticLet/StaticLetInUnionsAndRecords.fs index ec7346244d2..efebe68fa76 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/StaticLet/StaticLetInUnionsAndRecords.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/StaticLet/StaticLetInUnionsAndRecords.fs @@ -561,4 +561,86 @@ Console.Write(MyTypes.X.GetX) IL_0019: ret } -}"""] \ No newline at end of file +}"""] + +[] +[] +let ``Regression 16009 - module rec does not initialize let bindings`` langVersion = + let moduleWithBinding = """ +module rec Module + +open System + +let binding = + do Console.WriteLine("Asked for Module.binding") + let b = Foo.StaticMember + do Console.Write("isNull b in Module.binding after the call to Foo.StaticMember? ") + do Console.WriteLine(isNull b) + b + +module NestedModule = + let Binding = + do Console.WriteLine("Asked for NestedModule.Binding, before creating obj()") + let b = new obj() + do Console.Write("isNull b in NestedModule.Binding after 'new obj()'? ") + do Console.WriteLine(isNull b) + b + +type Foo = + static member StaticMember = + do Console.WriteLine("Asked for Foo.StaticMember") + let b = NestedModule.Binding + do Console.Write("isNull b in Foo.StaticMember after access to NestedModule.Binding? ") + do Console.WriteLine(isNull b) + b +""" + + let program = """ +open Module +open System + +do Console.WriteLine("Right before calling binding.ToString() in program.fs") +let b = binding +b.ToString() |> ignore +""" + + FSharp moduleWithBinding + |> withAdditionalSourceFiles [SourceCodeFileKind.Create("program.fs", program)] + |> withLangVersion langVersion + |> asExe + |> ignoreWarnings + |> compileAndRun + |> shouldSucceed + + +[] +[] +let ``Regression 16009 - as a single file program`` langVersion = + let code = """ +namespace MyProgram + +module rec Module = + + open System + + let binding = Foo.StaticMember + + module NestedModule = + let Binding = new obj() + + type Foo = + static member StaticMember = NestedModule.Binding + +module ActualProgram = + open Module + open System + + binding.ToString() |> Console.WriteLine +""" + + FSharp code + |> withLangVersion langVersion + |> asExe + |> ignoreWarnings + |> compileAndRun + |> shouldSucceed \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg04.bsl b/tests/fsharp/typecheck/sigs/neg04.bsl index 88ae776c8ca..ab0c018eb80 100644 --- a/tests/fsharp/typecheck/sigs/neg04.bsl +++ b/tests/fsharp/typecheck/sigs/neg04.bsl @@ -45,16 +45,12 @@ neg04.fs(70,21,70,36): typecheck error FS0064: This construct causes code to be neg04.fs(70,12,70,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'c' -neg04.fs(70,12,70,14): typecheck error FS0660: This code is less generic than required by its annotations because the explicit type variable 'a' could not be generalized. It was constrained to be 'c'. - neg04.fs(76,19,76,26): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution neg04.fs(76,19,76,26): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'd'. neg04.fs(76,10,76,12): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'd' -neg04.fs(76,10,76,12): typecheck error FS0660: This code is less generic than required by its annotations because the explicit type variable 'a' could not be generalized. It was constrained to be 'd'. - neg04.fs(81,58,81,61): typecheck error FS0001: This expression was expected to have type 'int' but here has type