From bbfa61df75c96053c3f023f14a48566a83d942ec Mon Sep 17 00:00:00 2001 From: Libo Zeng Date: Mon, 13 Feb 2017 16:58:12 -0500 Subject: [PATCH 1/5] initial --- src/fsharp/IlxGen.fs | 85 +++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index c1e507a576c..38c16103f4a 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -6062,6 +6062,46 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) = [],[],[] and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = + let genToString ilThisTy = + [ + match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, + eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with + | Some(Lazy(Method(_,_,sprintfMethSpec,_,_,_))), Some(Lazy(Method(_,_,newFormatMethSpec,_,_,_))) -> + // The type returned by the 'sprintf' call + let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String + // Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat + let newFormatMethSpec = mkILMethSpec(newFormatMethSpec.MethodRef,AsObject, + [// 'T -> string' + funcTy + // rest follow from 'StringFormat' + GenUnitTy cenv eenv m + cenv.g.ilg.typ_String + cenv.g.ilg.typ_String + ilThisTy],[]) + // Instantiate with our own type + let sprintfMethSpec = mkILMethSpec(sprintfMethSpec.MethodRef,AsObject,[],[funcTy]) + // Here's the body of the method. Call printf, then invoke the function it returns + let callInstrs = EraseClosures.mkCallFunc cenv.g.ilxPubCloEnv (fun _ -> 0us) eenv.tyenv.Count Normalcall (Apps_app(ilThisTy, Apps_done cenv.g.ilg.typ_String)) + let ilMethodDef = mkILNonGenericVirtualMethod ("ToString",ILMemberAccess.Public,[], + mkILReturn cenv.g.ilg.typ_String, + mkMethodBody (true,[],2,nonBranchingInstrsToCode + ([ // load the hardwired format string + yield I_ldstr "%+A" + // make the printf format object + yield mkNormalNewobj newFormatMethSpec + // call sprintf + yield mkNormalCall sprintfMethSpec + // call the function returned by sprintf + yield mkLdarg0 + if ilThisTy.Boxity = ILBoxity.AsValue then + yield mkNormalLdobj ilThisTy ] @ + callInstrs), + None)) + let mdef = { ilMethodDef with CustomAttrs = mkILCustomAttrs [ cenv.g.CompilerGeneratedAttribute ] } + yield mdef + | None,_ -> () + | _,None -> () + | _ -> ()] let tcref = mkLocalTyconRef tycon if tycon.IsTypeAbbrev then () else match tycon.TypeReprInfo with @@ -6418,7 +6458,9 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = // Records that are value types do not create a default constructor with CLIMutable or ComVisible if not isStructRecord && (isCLIMutable || (TryFindFSharpBoolAttribute cenv.g cenv.g.attrib_ComVisibleAttribute tycon.Attribs = Some true)) then yield mkILSimpleStorageCtor(None, Some cenv.g.ilg.typ_Object.TypeSpec, ilThisTy, [], reprAccess) - + + if (not <| tycon.HasMember cenv.g "ToString" []) then + yield! genToString ilThisTy | TFSharpObjectRepr r when tycon.IsFSharpDelegateTycon -> // Build all the methods that go with a delegate type @@ -6438,46 +6480,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = | _ -> () | TUnionRepr _ when (not <| tycon.HasMember cenv.g "ToString" []) -> - match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref, - eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with - | Some(Lazy(Method(_,_,sprintfMethSpec,_,_,_))), Some(Lazy(Method(_,_,newFormatMethSpec,_,_,_))) -> - // The type returned by the 'sprintf' call - let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String - // Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat - let newFormatMethSpec = mkILMethSpec(newFormatMethSpec.MethodRef,AsObject, - [// 'T -> string' - funcTy - // rest follow from 'StringFormat' - GenUnitTy cenv eenv m - cenv.g.ilg.typ_String - cenv.g.ilg.typ_String - ilThisTy],[]) - // Instantiate with our own type - let sprintfMethSpec = mkILMethSpec(sprintfMethSpec.MethodRef,AsObject,[],[funcTy]) - // Here's the body of the method. Call printf, then invoke the function it returns - let callInstrs = EraseClosures.mkCallFunc cenv.g.ilxPubCloEnv (fun _ -> 0us) eenv.tyenv.Count Normalcall (Apps_app(ilThisTy, Apps_done cenv.g.ilg.typ_String)) - let ilMethodDef = mkILNonGenericVirtualMethod ("ToString",ILMemberAccess.Public,[], - mkILReturn cenv.g.ilg.typ_String, - mkMethodBody - (true,[],2, - nonBranchingInstrsToCode - ([ // load the hardwired format string - yield I_ldstr "%+A" - // make the printf format object - yield mkNormalNewobj newFormatMethSpec - // call sprintf - yield mkNormalCall sprintfMethSpec - // call the function returned by sprintf - yield mkLdarg0 - if ilThisTy.Boxity = ILBoxity.AsValue then - yield mkNormalLdobj ilThisTy ] @ - callInstrs), - None)) - let mdef = { ilMethodDef with CustomAttrs = mkILCustomAttrs [ cenv.g.CompilerGeneratedAttribute ] } - yield mdef - | None,_ -> () - | _,None -> () - | _ -> () + yield! genToString ilThisTy | _ -> () ] let ilMethods = methodDefs @ augmentOverrideMethodDefs @ abstractMethodDefs From fa180c96b430fa39ec4d23658fa6ae6a3454d5d4 Mon Sep 17 00:00:00 2001 From: Libo Zeng Date: Mon, 13 Feb 2017 20:11:57 -0500 Subject: [PATCH 2/5] fix tests, add a simple test, and small style change --- src/fsharp/IlxGen.fs | 4 +- tests/fsharp/core/members/basics/test.fs | 38 +++++++++++++++++-- .../TestFunction17.il.netfx4.bsl | 15 +++++++- .../TestFunction24.il.netfx4.bsl | 15 +++++++- .../TestFunctions/Testfunction17.il.bsl | 15 +++++++- .../GenericComparison/Compare06.il.netfx4.bsl | 15 +++++++- .../GenericComparison/Equals05.il.netfx4.bsl | 16 +++++++- .../GenericComparison/Hash08.il.netfx4.bsl | 16 +++++++- 8 files changed, 122 insertions(+), 12 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 38c16103f4a..f6f14486ede 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -6459,7 +6459,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = if not isStructRecord && (isCLIMutable || (TryFindFSharpBoolAttribute cenv.g cenv.g.attrib_ComVisibleAttribute tycon.Attribs = Some true)) then yield mkILSimpleStorageCtor(None, Some cenv.g.ilg.typ_Object.TypeSpec, ilThisTy, [], reprAccess) - if (not <| tycon.HasMember cenv.g "ToString" []) then + if not (tycon.HasMember cenv.g "ToString" []) then yield! genToString ilThisTy | TFSharpObjectRepr r when tycon.IsFSharpDelegateTycon -> @@ -6479,7 +6479,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = yield { ilMethodDef with Access=reprAccess } | _ -> () - | TUnionRepr _ when (not <| tycon.HasMember cenv.g "ToString" []) -> + | TUnionRepr _ when not (tycon.HasMember cenv.g "ToString" []) -> yield! genToString ilThisTy | _ -> () ] diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index e550e7a5f57..b32f5294a32 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -1109,8 +1109,10 @@ module ToStringOnUnionTest = begin type MyUnion = A of string | B let a1 = A "FOO" - do test "union-tostring-def" (a1.ToString() = "A \"FOO\"") - do test "union-sprintfO-def" ((sprintf "%O" a1) = "A \"FOO\"") + let expected = "A \"FOO\"" + + do test "union-tostring-def" (a1.ToString() = expected) + do test "union-sprintfO-def" ((sprintf "%O" a1) = expected) end @@ -1121,8 +1123,36 @@ module ToStringOnUnionTestOverride = begin override x.ToString() = "MyUnion" let a1 = A "FOO" - do test "union-tostring-with-override" (a1.ToString() = "MyUnion") - do test "union-sprintfO-with-override" ((sprintf "%O" a1) = "MyUnion") + let expected = "MyUnion" + + do test "union-tostring-with-override" (a1.ToString() = expected) + do test "union-sprintfO-with-override" ((sprintf "%O" a1) = expected) + +end + +module ToStringOnRecordTest = begin + + type MyRecord = { A: string; B: int } + + let a1 = {A = "201"; B = 7} + let expected = "{A = \"201\";\n B = 7;}" + + do test "record-tostring-def" (a1.ToString() = expected) + do test "record-sprintfO-def" ((sprintf "%O" a1) = expected) + +end + +module ToStringOnRecordTestOverride = begin + + type MyRecord = { A: string; B: int } + with + override x.ToString() = "MyRecord" + + let a1 = {A = "201"; B = 7} + let expected = "MyRecord" + + do test "record-tostring-with-override" (a1.ToString() = expected) + do test "record-sprintfO-with-override" ((sprintf "%O" a1) = expected) end diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction17.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction17.il.netfx4.bsl index c64d34a92b0..4e1bf4a4e10 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction17.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction17.il.netfx4.bsl @@ -100,7 +100,20 @@ IL_000f: stfld int32 TestFunction17/R::y@ IL_0014: ret } // end of method R::.ctor - + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestFunction17/R>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } // end of method R::ToString + .method public hidebysig virtual final instance int32 CompareTo(class TestFunction17/R obj) cil managed { diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl index 514333240ed..00ee71a19d8 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl @@ -122,7 +122,20 @@ IL_000f: stfld int32 TestFunction24/Point::y@ IL_0014: ret } // end of method Point::.ctor - + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestFunction24/Point>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } // end of method Point::ToString + .method public hidebysig virtual final instance int32 CompareTo(class TestFunction24/Point obj) cil managed { diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction17.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction17.il.bsl index ad8540bab5f..bac87da136f 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction17.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction17.il.bsl @@ -100,7 +100,20 @@ IL_000f: stfld int32 TestFunction17/R::y@ IL_0014: ret } // end of method R::.ctor - + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class TestFunction17/R>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } // end of method R::ToString + .method public hidebysig virtual final instance int32 CompareTo(class TestFunction17/R obj) cil managed { diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.netfx4.bsl index 17550345691..7e926b33390 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.netfx4.bsl @@ -104,7 +104,20 @@ IL_000f: stfld int32 Compare06/CompareMicroPerfAndCodeGenerationTests/KeyR::key2@ IL_0014: ret } // end of method KeyR::.ctor - + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class Compare06/CompareMicroPerfAndCodeGenerationTests/KeyR>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } // end of method KeyR::ToString + .method public hidebysig virtual final instance int32 CompareTo(class Compare06/CompareMicroPerfAndCodeGenerationTests/KeyR obj) cil managed { diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.netfx4.bsl index 50d1acbd6aa..8a4f22d8256 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.netfx4.bsl @@ -104,7 +104,21 @@ IL_000f: stfld int32 Equals05/EqualsMicroPerfAndCodeGenerationTests/KeyR::key2@ IL_0014: ret } // end of method KeyR::.ctor - + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 22 (0x16) + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class Equals05/EqualsMicroPerfAndCodeGenerationTests/KeyR>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } // end of method KeyR::ToString + .method public hidebysig virtual final instance int32 CompareTo(class Equals05/EqualsMicroPerfAndCodeGenerationTests/KeyR obj) cil managed { diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.netfx4.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.netfx4.bsl index 8400b3e7606..13b35263e69 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.netfx4.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.netfx4.bsl @@ -104,7 +104,21 @@ IL_000f: stfld int32 Hash08/HashMicroPerfAndCodeGenerationTests/KeyR::key2@ IL_0014: ret } // end of method KeyR::.ctor - + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 22 (0x16) + .maxstack 8 + IL_0000: ldstr "%+A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,class Hash08/HashMicroPerfAndCodeGenerationTests/KeyR>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: ret + } // end of method KeyR::ToString + .method public hidebysig virtual final instance int32 CompareTo(class Hash08/HashMicroPerfAndCodeGenerationTests/KeyR obj) cil managed { From 7fe987a33239f49de2339f41707e42ad83642fa4 Mon Sep 17 00:00:00 2001 From: Libo Zeng Date: Tue, 14 Feb 2017 09:16:18 -0500 Subject: [PATCH 3/5] add test for struct records --- tests/fsharp/core/members/basics/test.fs | 32 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index b32f5294a32..06c0191f47f 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -1134,11 +1134,18 @@ module ToStringOnRecordTest = begin type MyRecord = { A: string; B: int } + [] + type MyStructRecord = { C: string; D: int } + let a1 = {A = "201"; B = 7} - let expected = "{A = \"201\";\n B = 7;}" + let c1 = {C = "20"; D = 17} + let expected1 = "{A = \"201\";\n B = 7;}" + let expected2 = "{C = \"20\";\n D = 17;}" - do test "record-tostring-def" (a1.ToString() = expected) - do test "record-sprintfO-def" ((sprintf "%O" a1) = expected) + do test "record-tostring-def" (a1.ToString() = expected1) + do test "record-sprintfO-def" ((sprintf "%O" a1) = expected1) + do test "struct-record-tostring-def" (c1.ToString() = expected2) + do test "struct-record-sprintfO-def" ((sprintf "%O" c1) = expected2) end @@ -1147,12 +1154,21 @@ module ToStringOnRecordTestOverride = begin type MyRecord = { A: string; B: int } with override x.ToString() = "MyRecord" - + + [] + type MyStructRecord = { C: string; D: int } + with + override x.ToString() = "MyStructRecord" + let a1 = {A = "201"; B = 7} - let expected = "MyRecord" - - do test "record-tostring-with-override" (a1.ToString() = expected) - do test "record-sprintfO-with-override" ((sprintf "%O" a1) = expected) + let c1 = {C = "20"; D = 17} + let expected1 = "MyRecord" + let expected2 = "MyStructRecord" + + do test "record-tostring-with-override" (a1.ToString() = expected1) + do test "record-sprintfO-with-override" ((sprintf "%O" a1) = expected1) + do test "struct-record-tostring-with-override" (c1.ToString() = expected2) + do test "struct-record-sprintfO-with-override" ((sprintf "%O" c1) = expected2) end From 8a516bad3c577160cd4f695b0eeb83feb4f19b8d Mon Sep 17 00:00:00 2001 From: Libo Zeng Date: Tue, 14 Feb 2017 14:44:18 -0500 Subject: [PATCH 4/5] also add a test for struct union --- tests/fsharp/core/members/basics/test.fs | 40 +++++++++++++++++------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index 06c0191f47f..63edfccbaf1 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -1108,25 +1108,41 @@ module ToStringOnUnionTest = begin type MyUnion = A of string | B + [] + type MyStructUnion = C of string | D + let a1 = A "FOO" - let expected = "A \"FOO\"" + let c1 = C "FOO" + + let expected1 = "A \"FOO\"" + let expected2 = "C \"FOO\"" - do test "union-tostring-def" (a1.ToString() = expected) - do test "union-sprintfO-def" ((sprintf "%O" a1) = expected) + do test "union-tostring-def" (a1.ToString() = expected1) + do test "union-sprintfO-def" ((sprintf "%O" a1) = expected1) + do test "struct-union-tostring-def" (c1.ToString() = expected2) + do test "struct-union-sprintfO-def" ((sprintf "%O" c1) = expected2) end module ToStringOnUnionTestOverride = begin + let expected1 = "MyUnion" type MyUnion = A of string | B with - override x.ToString() = "MyUnion" + override x.ToString() = expected1 + + let expected2 = "MyStructUnion" + + type MyStructUnion = C of string | D + with + override x.ToString() = expected2 let a1 = A "FOO" - let expected = "MyUnion" - do test "union-tostring-with-override" (a1.ToString() = expected) - do test "union-sprintfO-with-override" ((sprintf "%O" a1) = expected) + do test "union-tostring-with-override" (a1.ToString() = expected1) + do test "union-sprintfO-with-override" ((sprintf "%O" a1) = expected1) + do test "struct-union-tostring-with-override" (c1.ToString() = expected2) + do test "struct-union-sprintfO-with-override" ((sprintf "%O" c1) = expected2) end @@ -1151,19 +1167,21 @@ end module ToStringOnRecordTestOverride = begin + let expected1 = "MyRecord" + type MyRecord = { A: string; B: int } with - override x.ToString() = "MyRecord" + override x.ToString() = expected1 + let expected2 = "MyStructRecord" + [] type MyStructRecord = { C: string; D: int } with - override x.ToString() = "MyStructRecord" + override x.ToString() = expected2 let a1 = {A = "201"; B = 7} let c1 = {C = "20"; D = 17} - let expected1 = "MyRecord" - let expected2 = "MyStructRecord" do test "record-tostring-with-override" (a1.ToString() = expected1) do test "record-sprintfO-with-override" ((sprintf "%O" a1) = expected1) From f10a1121c1f2e6b0afbbb50b96e2f0934e52dfa7 Mon Sep 17 00:00:00 2001 From: Libo Zeng Date: Tue, 14 Feb 2017 16:58:38 -0500 Subject: [PATCH 5/5] fix test --- tests/fsharp/core/members/basics/test.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index 63edfccbaf1..76cda39b38e 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -1138,6 +1138,7 @@ module ToStringOnUnionTestOverride = begin override x.ToString() = expected2 let a1 = A "FOO" + let c1 = C "FOO" do test "union-tostring-with-override" (a1.ToString() = expected1) do test "union-sprintfO-with-override" ((sprintf "%O" a1) = expected1)