From f6d53e237ff7fa3e22f193735a37fc3c35be16c9 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 25 Feb 2025 16:55:05 +0100 Subject: [PATCH 1/3] ways of casting obj to T - tests --- .../Nullness/NullableReferenceTypesTests.fs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs index 4764554ce5f..5923fc9fff3 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs @@ -1381,6 +1381,20 @@ dict["ok"] <- 42 |> typeCheckWithStrictNullness |> shouldSucceed +[ 'T")>] +[] +[ unbox<'T>")>] +[ 'T")>] +[] +let ``Unsafe cast should not insist on not null constraint``(castOp:string) = + + FSharp $"""module MyLibrary +let test<'T> () = + let t = obj() + {castOp}""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed [] let ``Notnull constraint and inline annotated value`` () = From da38c2b336c8c32fbe1cc85585bdf02336ebaec5 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 27 Feb 2025 16:42:01 +0100 Subject: [PATCH 2/3] Make ' obj downcast to T' work without insisting on notnull constraint --- src/Compiler/Checking/Expressions/CheckExpressions.fs | 8 +++----- .../Language/Nullness/NullableReferenceTypesTests.fs | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index ee465013b6b..e873ba12f17 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -2976,11 +2976,9 @@ let TcRuntimeTypeTest isCast isOperator (cenv: cenv) denv m tgtTy srcTy = if isSealedTy g srcTy then error(RuntimeCoercionSourceSealed(denv, srcTy, m)) - if isSealedTy g tgtTy || isTyparTy g tgtTy || not (isInterfaceTy g srcTy) then - if isCast then - AddCxTypeMustSubsumeType (ContextInfo.RuntimeTypeTest isOperator) denv cenv.css m NoTrace srcTy tgtTy - else - AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css m NoTrace srcTy tgtTy + if (isSealedTy g tgtTy || isTyparTy g tgtTy || not (isInterfaceTy g srcTy)) && not (isObjTyAnyNullness g srcTy) then + let context = if isCast then ContextInfo.RuntimeTypeTest isOperator else ContextInfo.NoContext + AddCxTypeMustSubsumeType context denv cenv.css m NoTrace srcTy tgtTy if isErasedType g tgtTy then if isCast then diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs index b4266711718..ced7e02fdca 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs @@ -150,10 +150,8 @@ let doNotWarnOnDowncastRepeatedNestedNullable(o:objnull) = o :? list<((AB | null |> shouldFail |> withDiagnostics [ Error 3264, Line 4, Col 39, Line 4, Col 47, "Nullness warning: Downcasting from 'objnull' into 'AB' can introduce unexpected null values. Cast to 'AB|null' instead or handle the null before downcasting." - Error 3261, Line 5, Col 42, Line 5, Col 59, "Nullness warning: The types 'obj' and 'AB | null' do not have compatible nullability." Error 3060, Line 5, Col 42, Line 5, Col 59, "This type test or downcast will erase the provided type 'AB | null' to the type 'AB'" Error 3060, Line 6, Col 41, Line 6, Col 55, "This type test or downcast will erase the provided type 'AB | null' to the type 'AB'" - Error 3261, Line 7, Col 51, Line 7, Col 97, "Nullness warning: The types 'obj' and 'AB | null array | null list | null' do not have compatible nullability." Error 3060, Line 7, Col 51, Line 7, Col 97, "This type test or downcast will erase the provided type 'List | null' to the type 'List'"] From 057da8568ec478e3d16ab9b655779313f600d7c8 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 28 Feb 2025 18:38:24 +0100 Subject: [PATCH 3/3] notes --- docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index 1c78cff8fe9..491273fa561 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -12,6 +12,7 @@ * Cancellable: fix leaking cancellation token ([PR #18295](https://github.com/dotnet/fsharp/pull/18295)) * Fix NRE when accessing nullable fields of types within their equals/hash/compare methods ([PR #18296](https://github.com/dotnet/fsharp/pull/18296)) * Fix nullness warning for overrides of generic code with nullable type instance ([Issue #17988](https://github.com/dotnet/fsharp/issues/17988), [PR #18337](https://github.com/dotnet/fsharp/pull/18337)) +* Unsafe downcast from `obj` to generic `T` no longer requires `not null` constraint on `T`([Issue #18275](https://github.com/dotnet/fsharp/issues/18275), [PR #18343](https://github.com/dotnet/fsharp/pull/18343)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241))