From 79179ad3837d1db617eafed6c6ed510fa0795229 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 9 Feb 2024 12:28:11 +0100 Subject: [PATCH] Improve type inference w.r.t. nullness in printing --- src/Compiler/Checking/CheckFormatStrings.fs | 2 +- src/Compiler/TypedTree/TcGlobals.fs | 4 ++-- .../Language/NullableReferenceTypesTests.fs | 15 ++++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Checking/CheckFormatStrings.fs b/src/Compiler/Checking/CheckFormatStrings.fs index b37f21506a6..1264cbbcb86 100644 --- a/src/Compiler/Checking/CheckFormatStrings.fs +++ b/src/Compiler/Checking/CheckFormatStrings.fs @@ -449,7 +449,7 @@ let parseFormatStringInternal checkOtherFlags ch collectSpecifierLocation fragLine fragCol 1 let i = skipPossibleInterpolationHole (i+1) - let stringTy = if g.checkNullness && g.langFeatureNullness then g.string_ty_withNull else g.string_ty + let stringTy = if g.checkNullness && g.langFeatureNullness then g.string_ty_ambivalent else g.string_ty parseLoop ((posi, stringTy) :: acc) (i, fragLine, fragCol+1) fragments | 'O' -> diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index 946a9f5b2f1..1d35038d953 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -447,7 +447,7 @@ type TcGlobals( let v_FormattableStringFactory_tcref = findSysTyconRef sysCompilerServices "FormattableStringFactory" let v_FormattableStringFactory_ty = mkNonGenericTy v_FormattableStringFactory_tcref let v_string_ty = mkNonGenericTy v_string_tcr - let v_string_ty_withNull = mkNonGenericTyWithNullness v_string_tcr KnownWithNull + let v_string_ty_ambivalent = mkNonGenericTyWithNullness v_string_tcr KnownAmbivalentToNull let v_decimal_ty = mkSysNonGenericTy sys "Decimal" let v_unit_ty = mkNonGenericTy v_unit_tcr_nice let v_system_Type_ty = mkSysNonGenericTy sys "Type" @@ -1337,7 +1337,7 @@ type TcGlobals( member _.bool_ty = v_bool_ty member _.int_ty = v_int_ty member _.string_ty = v_string_ty - member _.string_ty_withNull = v_string_ty_withNull + member _.string_ty_ambivalent = v_string_ty_ambivalent member _.system_IFormattable_tcref = v_IFormattable_tcref member _.system_FormattableString_tcref = v_FormattableString_tcref member _.system_FormattableStringFactory_tcref = v_FormattableStringFactory_tcref diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs index ff50d481185..e6842ffffe7 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableReferenceTypesTests.fs @@ -18,7 +18,7 @@ let maybeNull : string | null = null let nonNullString = "abc" let printedValueNotNull = sprintf "This is not null: %s" nonNullString let printedValueNull = sprintf "This is null: %s" maybeNull -let interpolated = $"This is fine {maybeNull}" +let interpolated = $"This is fine %s{maybeNull}" let interpolatedAnnotatedNotNull = $"This is fine %s{nonNullString}" let interpolatedAnnotatedNullable = $"This is not null %s{maybeNull}" let interpolateNullLiteral = $"This is not null %s{null}" @@ -53,6 +53,19 @@ let printViaA = sprintf "This is null: %A and this has null inside %A" maybeArra |> typeCheckWithStrictNullness |> shouldSucceed +[] +let ``Type inference with sprintfn`` () = + FSharp """module MyLibrary +let needsString(x:string) = () + +let myTopFunction inferedVal = + printfn "This is it %s" inferedVal // There was a regression infering this to be (string | null) + needsString inferedVal +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + [] let ``WhatIf the format itself is null`` () = FSharp """module MyLibrary