From 0c84eb00c709a8571c3dbadc105415e5df779773 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 6 Feb 2024 11:12:05 +0100 Subject: [PATCH 1/4] Fsharp.Core Unchecked.nonNull --- src/FSharp.Core/prim-types.fs | 21 +++++++++++++++++++++ src/FSharp.Core/prim-types.fsi | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index e1f64380f4a..0144d25dae0 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -4434,6 +4434,9 @@ namespace Microsoft.FSharp.Core when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "add" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "add" x y : uint32 #) : byte #) when ^T : string and ^U : string = (# "" (String.Concat((# "" x : string #),(# "" y : string #))) : ^T #) +#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT + when ^T : (string|null) and ^U : (string|null) = (# "" (String.Concat((# "" x : string #),(# "" y : string #))) : string #) +#endif when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Addition((# "" x : decimal #),(# "" y : decimal #))) : ^V #) // According to the somewhat subtle rules of static optimizations, // this condition is used whenever ^T is resolved to a nominal type or witnesses are available @@ -5346,6 +5349,24 @@ namespace Microsoft.FSharp.Core [] let inline hash x = GenericHash x + #if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT + + [] + let inline nonNull (x: 'T | null) : 'T = (# "" x : 'T #) + + [] + let inline (|NonNullQuick|) (value : 'T | null when 'T : not null and 'T : not struct) = nonNull value + + #else + + [] + let inline nonNull (x: 'T ) : 'T = x + + [] + let inline (|NonNullQuick|) (value) = nonNull value + + #endif + module Checked = let inline (+) (x: ^T) (y: ^U) : ^V = diff --git a/src/FSharp.Core/prim-types.fsi b/src/FSharp.Core/prim-types.fsi index e3c2bb245b6..feb535ba643 100644 --- a/src/FSharp.Core/prim-types.fsi +++ b/src/FSharp.Core/prim-types.fsi @@ -5740,6 +5740,28 @@ namespace Microsoft.FSharp.Core [] val inline hash: 'T -> int + /// Unsafely retypes the value from ('T | null) to 'T without doing any null check at runtime. This is an unsafe operation. + /// The possibly nullable value. + /// The same value as in the input. + [] + [] + #if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT + val inline nonNull : value: 'T | null -> 'T when 'T : not null and 'T : not struct + #else + val inline nonNull : value: 'T -> 'T + #endif + + /// When used in a pattern forgets 'nullness' of the value without any runtime check. This is an unsafe operation, as null check is being skipped and null value can be returned. + /// The value to retype from ('T | null) to 'T . + /// The non-null value. + [] + [] + #if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT + val inline (|NonNullQuick|) : value: 'T | null -> 'T when 'T : not null and 'T : not struct + #else + val inline (|NonNullQuick|) : value: 'T -> 'T + #endif + /// A module of comparison and equality operators that are statically resolved, but which are not fully generic and do not make structural comparison. Opening this /// module may make code that relies on structural or generic comparison no longer compile. module NonStructuralComparison = From d31de714e3391482892792bd1e40669f07130944 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 6 Feb 2024 11:24:49 +0100 Subject: [PATCH 2/4] Update src/FSharp.Core/prim-types.fs --- src/FSharp.Core/prim-types.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index 0144d25dae0..3ec0b8d19d7 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -5352,7 +5352,7 @@ namespace Microsoft.FSharp.Core #if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT [] - let inline nonNull (x: 'T | null) : 'T = (# "" x : 'T #) + let inline nonNull (x: 'T | null when 'T : not null and 'T : not struct) : 'T = (# "" x : 'T #) [] let inline (|NonNullQuick|) (value : 'T | null when 'T : not null and 'T : not struct) = nonNull value From 5ad24c3987da8371b26c97164633b12160fc4d01 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 6 Feb 2024 14:03:03 +0100 Subject: [PATCH 3/4] surface area + tests --- .../FSharp.Compiler.ComponentTests.fsproj | 3 +- .../NullableLibraryConstructsTests.fs | 42 +++++++++++++++++++ ...p.Core.SurfaceArea.netstandard20.debug.bsl | 28 +++++++------ ...Core.SurfaceArea.netstandard20.release.bsl | 30 ++++++------- ...p.Core.SurfaceArea.netstandard21.debug.bsl | 28 +++++++------ ...Core.SurfaceArea.netstandard21.release.bsl | 28 +++++++------ 6 files changed, 105 insertions(+), 54 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 6fe69ad285a..24823485abf 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -225,8 +225,9 @@ + - + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs new file mode 100644 index 00000000000..c68412e7859 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs @@ -0,0 +1,42 @@ +module Language.NullableLibraryConstructs + +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +let typeCheckWithStrictNullness cu = + cu + |> withLangVersionPreview + |> withCheckNulls + |> withWarnOn 3261 + |> withOptions ["--warnaserror+"] + |> typecheck + +[] +let ``Can unsafely forgive null using Unchecked nonNull function`` () = + FSharp """module MyLibrary + +let readAllLines (reader:System.IO.StreamReader) : seq = + seq { + while not reader.EndOfStream do + reader.ReadLine() |> Unchecked.nonNull + } +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Can unsafely forgive null using Unchecked NonNullQuick active pattern`` () = + FSharp """module MyLibrary + +let readAllLines (reader:System.IO.StreamReader) : seq = + seq { + while not reader.EndOfStream do + match reader.ReadLine() with + | Unchecked.NonNullQuick line -> yield line + } +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed \ No newline at end of file diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl index eeea1540744..7d20a88524a 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl @@ -1732,7 +1732,10 @@ Microsoft.FSharp.Core.Operators+Unchecked: Boolean Equals[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Compare[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Hash[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T DefaultOf[T]() +Microsoft.FSharp.Core.Operators+Unchecked: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators+Unchecked: T NonNull[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Boolean IsNull[T](T) Microsoft.FSharp.Core.Operators: Boolean Not(Boolean) Microsoft.FSharp.Core.Operators: Boolean op_Equality[T](T, T) @@ -1768,6 +1771,8 @@ Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Collections.FSharpList`1[T] op_Append[T](Microsoft.FSharp.Collections.FSharpList`1[T], Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeLeft[T2,T3,T1](Microsoft.FSharp.Core.FSharpFunc`2[T2,T3], Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeRight[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,T2], Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[System.String] FailurePattern(System.Exception) @@ -1797,6 +1802,8 @@ Microsoft.FSharp.Core.Operators: System.Exception Failure(System.String) Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleError[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleOut[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) Microsoft.FSharp.Core.Operators: System.Object Box[T](T) Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]) Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) @@ -1820,6 +1827,8 @@ Microsoft.FSharp.Core.Operators: T Cos[T](T) Microsoft.FSharp.Core.Operators: T Cosh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Cosh[T](T) Microsoft.FSharp.Core.Operators: T DefaultArg[T](Microsoft.FSharp.Core.FSharpOption`1[T], T) +Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) Microsoft.FSharp.Core.Operators: T DefaultValueArg[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], T) Microsoft.FSharp.Core.Operators: T Exit[T](Int32) Microsoft.FSharp.Core.Operators: T Exp$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) @@ -1837,6 +1846,11 @@ Microsoft.FSharp.Core.Operators: T Log10[T](T) Microsoft.FSharp.Core.Operators: T Log[T](T) Microsoft.FSharp.Core.Operators: T Max[T](T, T) Microsoft.FSharp.Core.Operators: T Min[T](T, T) +Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNull[T](T) +Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) Microsoft.FSharp.Core.Operators: T NullArg[T](System.String) Microsoft.FSharp.Core.Operators: T PowInteger$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, Int32) Microsoft.FSharp.Core.Operators: T PowInteger[T](T, Int32) @@ -1856,6 +1870,7 @@ Microsoft.FSharp.Core.Operators: T Tanh[T](T) Microsoft.FSharp.Core.Operators: T Truncate$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Truncate[T](T) Microsoft.FSharp.Core.Operators: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd[T](T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) @@ -1913,19 +1928,6 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef` Microsoft.FSharp.Core.Operators: Void Ignore[T](T) Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32]) Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T) -Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) -Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) -Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) -Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNull[T](T) -Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) -Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]]) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl index 5b8c8858e96..e923211a3a2 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl @@ -1732,7 +1732,10 @@ Microsoft.FSharp.Core.Operators+Unchecked: Boolean Equals[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Compare[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Hash[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T DefaultOf[T]() +Microsoft.FSharp.Core.Operators+Unchecked: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators+Unchecked: T NonNull[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Boolean IsNull[T](T) Microsoft.FSharp.Core.Operators: Boolean Not(Boolean) Microsoft.FSharp.Core.Operators: Boolean op_Equality[T](T, T) @@ -1768,6 +1771,8 @@ Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Collections.FSharpList`1[T] op_Append[T](Microsoft.FSharp.Collections.FSharpList`1[T], Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeLeft[T2,T3,T1](Microsoft.FSharp.Core.FSharpFunc`2[T2,T3], Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeRight[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,T2], Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[System.String] FailurePattern(System.Exception) @@ -1797,6 +1802,8 @@ Microsoft.FSharp.Core.Operators: System.Exception Failure(System.String) Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleError[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleOut[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) Microsoft.FSharp.Core.Operators: System.Object Box[T](T) Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString[T](T) @@ -1819,6 +1826,8 @@ Microsoft.FSharp.Core.Operators: T Cos[T](T) Microsoft.FSharp.Core.Operators: T Cosh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Cosh[T](T) Microsoft.FSharp.Core.Operators: T DefaultArg[T](Microsoft.FSharp.Core.FSharpOption`1[T], T) +Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) Microsoft.FSharp.Core.Operators: T DefaultValueArg[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], T) Microsoft.FSharp.Core.Operators: T Exit[T](Int32) Microsoft.FSharp.Core.Operators: T Exp$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) @@ -1836,6 +1845,11 @@ Microsoft.FSharp.Core.Operators: T Log10[T](T) Microsoft.FSharp.Core.Operators: T Log[T](T) Microsoft.FSharp.Core.Operators: T Max[T](T, T) Microsoft.FSharp.Core.Operators: T Min[T](T, T) +Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNull[T](T) +Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) Microsoft.FSharp.Core.Operators: T NullArg[T](System.String) Microsoft.FSharp.Core.Operators: T PowInteger$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, Int32) Microsoft.FSharp.Core.Operators: T PowInteger[T](T, Int32) @@ -1855,6 +1869,7 @@ Microsoft.FSharp.Core.Operators: T Tanh[T](T) Microsoft.FSharp.Core.Operators: T Truncate$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Truncate[T](T) Microsoft.FSharp.Core.Operators: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd[T](T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) @@ -1912,19 +1927,6 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef` Microsoft.FSharp.Core.Operators: Void Ignore[T](T) Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32]) Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T) -Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) -Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) -Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) -Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNull[T](T) -Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) -Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]]) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2) @@ -2555,4 +2557,4 @@ Microsoft.FSharp.Reflection.UnionCaseInfo: System.String Name Microsoft.FSharp.Reflection.UnionCaseInfo: System.String ToString() Microsoft.FSharp.Reflection.UnionCaseInfo: System.String get_Name() Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type DeclaringType -Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType() +Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType() \ No newline at end of file diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl index 5a5008e7218..7abc18b3057 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl @@ -1733,7 +1733,10 @@ Microsoft.FSharp.Core.Operators+Unchecked: Boolean Equals[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Compare[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Hash[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T DefaultOf[T]() +Microsoft.FSharp.Core.Operators+Unchecked: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators+Unchecked: T NonNull[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Boolean IsNull[T](T) Microsoft.FSharp.Core.Operators: Boolean Not(Boolean) Microsoft.FSharp.Core.Operators: Boolean op_Equality[T](T, T) @@ -1769,6 +1772,8 @@ Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Collections.FSharpList`1[T] op_Append[T](Microsoft.FSharp.Collections.FSharpList`1[T], Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeLeft[T2,T3,T1](Microsoft.FSharp.Core.FSharpFunc`2[T2,T3], Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeRight[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,T2], Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[System.String] FailurePattern(System.Exception) @@ -1798,6 +1803,8 @@ Microsoft.FSharp.Core.Operators: System.Exception Failure(System.String) Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleError[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleOut[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) Microsoft.FSharp.Core.Operators: System.Object Box[T](T) Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]) Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) @@ -1821,6 +1828,8 @@ Microsoft.FSharp.Core.Operators: T Cos[T](T) Microsoft.FSharp.Core.Operators: T Cosh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Cosh[T](T) Microsoft.FSharp.Core.Operators: T DefaultArg[T](Microsoft.FSharp.Core.FSharpOption`1[T], T) +Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) Microsoft.FSharp.Core.Operators: T DefaultValueArg[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], T) Microsoft.FSharp.Core.Operators: T Exit[T](Int32) Microsoft.FSharp.Core.Operators: T Exp$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) @@ -1838,6 +1847,11 @@ Microsoft.FSharp.Core.Operators: T Log10[T](T) Microsoft.FSharp.Core.Operators: T Log[T](T) Microsoft.FSharp.Core.Operators: T Max[T](T, T) Microsoft.FSharp.Core.Operators: T Min[T](T, T) +Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNull[T](T) +Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) Microsoft.FSharp.Core.Operators: T NullArg[T](System.String) Microsoft.FSharp.Core.Operators: T PowInteger$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, Int32) Microsoft.FSharp.Core.Operators: T PowInteger[T](T, Int32) @@ -1857,6 +1871,7 @@ Microsoft.FSharp.Core.Operators: T Tanh[T](T) Microsoft.FSharp.Core.Operators: T Truncate$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Truncate[T](T) Microsoft.FSharp.Core.Operators: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd[T](T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) @@ -1914,19 +1929,6 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef` Microsoft.FSharp.Core.Operators: Void Ignore[T](T) Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32]) Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T) -Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) -Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) -Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) -Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNull[T](T) -Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) -Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]]) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl index 12f8380fbfb..a633fb0dc1b 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl @@ -1733,7 +1733,10 @@ Microsoft.FSharp.Core.Operators+Unchecked: Boolean Equals[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Compare[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Hash[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T DefaultOf[T]() +Microsoft.FSharp.Core.Operators+Unchecked: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators+Unchecked: T NonNull[T](T) Microsoft.FSharp.Core.Operators+Unchecked: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Boolean IsNull[T](T) Microsoft.FSharp.Core.Operators: Boolean Not(Boolean) Microsoft.FSharp.Core.Operators: Boolean op_Equality[T](T, T) @@ -1769,6 +1772,8 @@ Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Collections.FSharpList`1[T] op_Append[T](Microsoft.FSharp.Collections.FSharpList`1[T], Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) +Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeLeft[T2,T3,T1](Microsoft.FSharp.Core.FSharpFunc`2[T2,T3], Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeRight[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,T2], Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[System.String] FailurePattern(System.Exception) @@ -1798,6 +1803,8 @@ Microsoft.FSharp.Core.Operators: System.Exception Failure(System.String) Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleError[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleOut[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() +Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) Microsoft.FSharp.Core.Operators: System.Object Box[T](T) Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString[T](T) @@ -1820,6 +1827,8 @@ Microsoft.FSharp.Core.Operators: T Cos[T](T) Microsoft.FSharp.Core.Operators: T Cosh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Cosh[T](T) Microsoft.FSharp.Core.Operators: T DefaultArg[T](Microsoft.FSharp.Core.FSharpOption`1[T], T) +Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) Microsoft.FSharp.Core.Operators: T DefaultValueArg[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], T) Microsoft.FSharp.Core.Operators: T Exit[T](Int32) Microsoft.FSharp.Core.Operators: T Exp$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) @@ -1837,6 +1846,11 @@ Microsoft.FSharp.Core.Operators: T Log10[T](T) Microsoft.FSharp.Core.Operators: T Log[T](T) Microsoft.FSharp.Core.Operators: T Max[T](T, T) Microsoft.FSharp.Core.Operators: T Min[T](T, T) +Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) +Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) +Microsoft.FSharp.Core.Operators: T NonNull[T](T) +Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) Microsoft.FSharp.Core.Operators: T NullArg[T](System.String) Microsoft.FSharp.Core.Operators: T PowInteger$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, Int32) Microsoft.FSharp.Core.Operators: T PowInteger[T](T, Int32) @@ -1856,6 +1870,7 @@ Microsoft.FSharp.Core.Operators: T Tanh[T](T) Microsoft.FSharp.Core.Operators: T Truncate$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Truncate[T](T) Microsoft.FSharp.Core.Operators: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd[T](T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) @@ -1913,19 +1928,6 @@ Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef` Microsoft.FSharp.Core.Operators: Void Ignore[T](T) Microsoft.FSharp.Core.Operators: Void Increment(Microsoft.FSharp.Core.FSharpRef`1[System.Int32]) Microsoft.FSharp.Core.Operators: Void op_ColonEquals[T](Microsoft.FSharp.Core.FSharpRef`1[T], T) -Microsoft.FSharp.Core.Operators: Boolean IsNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullMatchPattern[T](T) -Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpChoice`2[Microsoft.FSharp.Core.Unit,T] NullValueMatchPattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] NullV[T]() -Microsoft.FSharp.Core.Operators: System.Nullable`1[T] WithNullV[T](T) -Microsoft.FSharp.Core.Operators: T DefaultIfNullV[T](T, System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T DefaultIfNull[T](T, T) -Microsoft.FSharp.Core.Operators: T NonNullQuickPattern[T](T) -Microsoft.FSharp.Core.Operators: T NonNullQuickValuePattern[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNullV[T](System.Nullable`1[T]) -Microsoft.FSharp.Core.Operators: T NonNull[T](T) -Microsoft.FSharp.Core.Operators: T NullArgCheck[T](System.String, T) -Microsoft.FSharp.Core.Operators: T WithNull[T](T) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: FSharpFunc`3 Adapt(Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]]) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult] Invoke(T1) Microsoft.FSharp.Core.OptimizedClosures+FSharpFunc`3[T1,T2,TResult]: TResult Invoke(T1, T2) From a82e880d692692718f503a594fc4209b1f9b41b4 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 6 Feb 2024 16:33:58 +0100 Subject: [PATCH 4/4] Lets not touch (+) --- src/FSharp.Core/prim-types.fs | 3 --- .../Language/NullableLibraryConstructsTests.fs | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/FSharp.Core/prim-types.fs b/src/FSharp.Core/prim-types.fs index 3ec0b8d19d7..b4e3271b60d 100644 --- a/src/FSharp.Core/prim-types.fs +++ b/src/FSharp.Core/prim-types.fs @@ -4434,9 +4434,6 @@ namespace Microsoft.FSharp.Core when ^T : sbyte and ^U : sbyte = (# "conv.i1" (# "add" x y : int32 #) : sbyte #) when ^T : byte and ^U : byte = (# "conv.u1" (# "add" x y : uint32 #) : byte #) when ^T : string and ^U : string = (# "" (String.Concat((# "" x : string #),(# "" y : string #))) : ^T #) -#if !BUILDING_WITH_LKG && !NO_NULLCHECKING_LIB_SUPPORT - when ^T : (string|null) and ^U : (string|null) = (# "" (String.Concat((# "" x : string #),(# "" y : string #))) : string #) -#endif when ^T : decimal and ^U : decimal = (# "" (Decimal.op_Addition((# "" x : decimal #),(# "" y : decimal #))) : ^V #) // According to the somewhat subtle rules of static optimizations, // this condition is used whenever ^T is resolved to a nominal type or witnesses are available diff --git a/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs index c68412e7859..790c4cfd395 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/NullableLibraryConstructsTests.fs @@ -36,6 +36,23 @@ let readAllLines (reader:System.IO.StreamReader) : seq = match reader.ReadLine() with | Unchecked.NonNullQuick line -> yield line } +""" + |> asLibrary + |> typeCheckWithStrictNullness + |> shouldSucceed + +[] +let ``Can concat two maybe null strings`` () = + FSharp """module MyLibrary + +let addStrings (x:string | null) (y:string) : string = + + let s2 = x + x + let s3 = y + y + let s4 = y + x + let s4string : string = s4 + + s4 """ |> asLibrary |> typeCheckWithStrictNullness