Skip to content

Commit 38b2bac

Browse files
authored
Fix 16009 - wrong order of static init in recursive module (#16054)
* Fix 16009 - wrong order of static init in recursive module
1 parent 10f956e commit 38b2bac

File tree

4 files changed

+87
-7
lines changed

4 files changed

+87
-7
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1840,7 +1840,10 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial mBinds scopem mutRecNSInfo (env
18401840
| SynMemberDefn.ImplicitCtor _ :: _ -> ()
18411841
| _ ->
18421842
if not tcref.IsFSharpEnumTycon && not tcref.IsFSharpDelegateTycon && not tcref.IsFSharpException && not tcref.IsTypeAbbrev then
1843-
TyconBindingDefn(containerInfo, newslotsOK, declKind, None, tcref.Range)
1843+
if members |> List.exists (function | SynMemberDefn.LetBindings(isStatic=true) -> true | _ -> false ) then
1844+
// 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
1845+
// Minimizing the impact by only yielding in case of actually emitting static let bindings.
1846+
TyconBindingDefn(containerInfo, newslotsOK, declKind, None, tcref.Range)
18441847

18451848
// Yield the other members
18461849
for memb in members do

src/Compiler/Checking/CheckIncrementalClasses.fs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,6 @@ let MakeCtorForIncrClassConstructionPhase2C(
756756
/// binding in the implicit class construction sequence
757757
let TransTrueDec isCtorArg (reps: IncrClassReprInfo) dec =
758758
match dec with
759-
// Pokud to neni staticke, a zaroven to nema construktor info, tak zkusit vyhnout se TransBind mozna?
760759
| IncrClassBindingGroup(binds, isStatic, isRec) ->
761760
let actions, reps, methodBinds =
762761
let reps = (reps, binds) ||> List.fold (fun rep bind -> rep.ChooseAndAddRepresentation(cenv, env, isStatic, isCtorArg, staticCtorInfo, ctorInfoOpt, staticForcedFieldVars, instanceForcedFieldVars, bind)) // extend

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/StaticLet/StaticLetInUnionsAndRecords.fs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,4 +561,86 @@ Console.Write(MyTypes.X.GetX)
561561
IL_0019: ret
562562
}
563563
564-
}"""]
564+
}"""]
565+
566+
[<Theory>]
567+
[<InlineData("preview")>]
568+
let ``Regression 16009 - module rec does not initialize let bindings`` langVersion =
569+
let moduleWithBinding = """
570+
module rec Module
571+
572+
open System
573+
574+
let binding =
575+
do Console.WriteLine("Asked for Module.binding")
576+
let b = Foo.StaticMember
577+
do Console.Write("isNull b in Module.binding after the call to Foo.StaticMember? ")
578+
do Console.WriteLine(isNull b)
579+
b
580+
581+
module NestedModule =
582+
let Binding =
583+
do Console.WriteLine("Asked for NestedModule.Binding, before creating obj()")
584+
let b = new obj()
585+
do Console.Write("isNull b in NestedModule.Binding after 'new obj()'? ")
586+
do Console.WriteLine(isNull b)
587+
b
588+
589+
type Foo =
590+
static member StaticMember =
591+
do Console.WriteLine("Asked for Foo.StaticMember")
592+
let b = NestedModule.Binding
593+
do Console.Write("isNull b in Foo.StaticMember after access to NestedModule.Binding? ")
594+
do Console.WriteLine(isNull b)
595+
b
596+
"""
597+
598+
let program = """
599+
open Module
600+
open System
601+
602+
do Console.WriteLine("Right before calling binding.ToString() in program.fs")
603+
let b = binding
604+
b.ToString() |> ignore
605+
"""
606+
607+
FSharp moduleWithBinding
608+
|> withAdditionalSourceFiles [SourceCodeFileKind.Create("program.fs", program)]
609+
|> withLangVersion langVersion
610+
|> asExe
611+
|> ignoreWarnings
612+
|> compileAndRun
613+
|> shouldSucceed
614+
615+
616+
[<Theory>]
617+
[<InlineData("preview")>]
618+
let ``Regression 16009 - as a single file program`` langVersion =
619+
let code = """
620+
namespace MyProgram
621+
622+
module rec Module =
623+
624+
open System
625+
626+
let binding = Foo.StaticMember
627+
628+
module NestedModule =
629+
let Binding = new obj()
630+
631+
type Foo =
632+
static member StaticMember = NestedModule.Binding
633+
634+
module ActualProgram =
635+
open Module
636+
open System
637+
638+
binding.ToString() |> Console.WriteLine
639+
"""
640+
641+
FSharp code
642+
|> withLangVersion langVersion
643+
|> asExe
644+
|> ignoreWarnings
645+
|> compileAndRun
646+
|> shouldSucceed

tests/fsharp/typecheck/sigs/neg04.bsl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,12 @@ neg04.fs(70,21,70,36): typecheck error FS0064: This construct causes code to be
4545

4646
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<string>'
4747

48-
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<string>'.
49-
5048
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
5149

5250
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'.
5351

5452
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'
5553

56-
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'.
57-
5854
neg04.fs(81,58,81,61): typecheck error FS0001: This expression was expected to have type
5955
'int'
6056
but here has type

0 commit comments

Comments
 (0)