From ff657e65844dffbe67ff1c0c8429035eb7bb2a0e Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 7 Oct 2024 12:09:03 +0200 Subject: [PATCH 1/4] failing test --- .../Nullness/NullableReferenceTypesTests.fs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs index de6d1c888ca..0feb9aee96e 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs @@ -41,6 +41,22 @@ let nonStrictFunc(x:string | null) = strictFunc(x) |> shouldFail |> withDiagnostics [ Error 3261, Line 4, Col 49, Line 4, Col 50, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."] + +[] +let ``Can have nullable prop of same type T within a custom type T``() = + FSharp """ +module MyLib +type T () = + //let mutable v : T | null = null + member val P : T | null = null with get, set + member this.M() = + //v <- null + this.P <- null + """ + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldFail + |> withDiagnostics [] [] [] From 9a50e937841437862866a5c790745b83cb5d2f13 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 7 Oct 2024 18:02:23 +0200 Subject: [PATCH 2/4] Fix bug with longer nullness inference chains --- src/Compiler/TypedTree/TypedTree.fs | 6 ++++++ src/Compiler/TypedTree/TypedTree.fsi | 1 + src/Compiler/TypedTree/TypedTreeBasics.fs | 2 +- .../Language/Nullness/NullableReferenceTypesTests.fs | 3 +-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index b948e91fb65..b5e620c6bd6 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -4358,6 +4358,12 @@ type NullnessVar() = member nv.IsSolved = solution.IsSome + member nv.IsFullySolved = + match solution with + | None -> false + | Some (Nullness.Known _) -> true + | Some (Nullness.Variable v) -> v.IsFullySolved + member nv.Set(nullness) = assert (not nv.IsSolved) solution <- Some nullness diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index d357895728d..5f96fba2266 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -3100,6 +3100,7 @@ type NullnessVar = member Evaluate: unit -> NullnessInfo member TryEvaluate: unit -> NullnessInfo voption member IsSolved: bool + member IsFullySolved: bool member Set: Nullness -> unit member Unset: unit -> unit member Solution: Nullness diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fs b/src/Compiler/TypedTree/TypedTreeBasics.fs index c8268ffcf8a..0ad62482b6a 100644 --- a/src/Compiler/TypedTree/TypedTreeBasics.fs +++ b/src/Compiler/TypedTree/TypedTreeBasics.fs @@ -284,7 +284,7 @@ let tryAddNullnessToTy nullnessNew (ty:TType) = let addNullnessToTy (nullness: Nullness) (ty:TType) = match nullness with | Nullness.Known NullnessInfo.WithoutNull -> ty - | Nullness.Variable nv when nv.IsSolved && nv.Evaluate() = NullnessInfo.WithoutNull -> ty + | Nullness.Variable nv when nv.IsFullySolved && nv.TryEvaluate() = ValueSome NullnessInfo.WithoutNull -> ty | _ -> match ty with | TType_var (tp, nullnessOrig) -> TType_var (tp, combineNullness nullnessOrig nullness) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs index 3759ff426e7..bd55e370def 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs @@ -158,8 +158,7 @@ type T () = """ |> asLibrary |> typeCheckWithStrictNullness - |> shouldFail - |> withDiagnostics [] + |> shouldSucceed [] [] From da9779f9e695e5e4ab09074662769085f1b8b823 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 15 Oct 2024 11:13:09 +0200 Subject: [PATCH 3/4] Apply suggestions from code review --- .../Language/Nullness/NullableReferenceTypesTests.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs index bd55e370def..0da1169b9a8 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs @@ -150,10 +150,10 @@ let ``Can have nullable prop of same type T within a custom type T``() = FSharp """ module MyLib type T () = - //let mutable v : T | null = null + let mutable v : T | null = null member val P : T | null = null with get, set member this.M() = - //v <- null + v <- null this.P <- null """ |> asLibrary From 864e3cf041b3aeff1995161dd637f0c2718d047f Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 15 Oct 2024 11:15:55 +0200 Subject: [PATCH 4/4] release notes --- docs/release-notes/.FSharp.Compiler.Service/9.0.200.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md index e58c882938b..8964c6b6698 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md @@ -5,6 +5,7 @@ * Fix extension methods support for non-reference system assemblies ([PR #17799](https://github.com/dotnet/fsharp/pull/17799)) * Ensure `frameworkTcImportsCache` mutations are thread-safe. ([PR #17795](https://github.com/dotnet/fsharp/pull/17795)) * Fix concurrency issue in `ILPreTypeDefImpl` ([PR #17812](https://github.com/dotnet/fsharp/pull/17812)) +* Fix nullness inference for member val and other OO scenarios ([PR #17845](https://github.com/dotnet/fsharp/pull/17845)) ### Added