diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 6f619b045b3..0aba6593b02 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -4509,7 +4509,10 @@ namespace Microsoft.FSharp.Core [] let inline string (value: 'T) = anyToString "" value - when 'T : string = (# "" value : string #) // force no-op + + when 'T : string = + if value = unsafeDefault<'T> then "" + else (# "" value : string #) // force no-op // Using 'let x = (# ... #) in x.ToString()' leads to better IL, without it, an extra stloc and ldloca.s (get address-of) // gets emitted, which are unnecessary. With it, the extra address-of-variable is not created diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/OperatorsModule2.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/OperatorsModule2.fs index e821b4b8835..3a7cc87778d 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/OperatorsModule2.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/OperatorsModule2.fs @@ -740,6 +740,20 @@ type OperatorsModule2() = [] member _.string() = + + let result = Operators.string null + Assert.AreEqual("", result) + + let nullStr:string = null + let result = Operators.string nullStr + Assert.AreEqual("", result) + + let result = Operators.string null + Assert.AreEqual("", result) + + let result = Operators.string (null:string) + Assert.AreEqual("", result) + // value type let result = Operators.string 100 Assert.AreEqual("100", result) diff --git a/tests/service/ExprTests.fs b/tests/service/ExprTests.fs index 05164371137..5077986015a 100644 --- a/tests/service/ExprTests.fs +++ b/tests/service/ExprTests.fs @@ -2792,7 +2792,7 @@ let ``Test Operator Declarations for String`` () = [], "let testStringToDoubleOperator(e1) = Double.Parse ((if Operators.op_Equality (e1,dflt) then dflt else e1.Replace(\"_\",\"\")),167,CultureInfo.get_InvariantCulture () :> System.IFormatProvider) @ (53,47--53,55)" [], "let testStringToDecimalOperator(e1) = Decimal.Parse (e1,167,CultureInfo.get_InvariantCulture () :> System.IFormatProvider) @ (54,47--54,57)" [], "let testStringToCharOperator(e1) = Char.Parse (e1) @ (55,47--55,54)" - [FC47; FC50], "let testStringToStringOperator(e1) = e1 @ (56,54--56,56)" + [FC47; FC50], """let testStringToStringOperator(e1) = (if String.Equals (e1,dflt) then "" else e1) @ (56,47--56,56)""" ] testOperators "String" "string" excludedTests expectedUnoptimized expectedOptimized