From bcc31e6a3285567bd7064a21c573f1c51bd3a93b Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 3 Feb 2016 19:21:28 +1100
Subject: [PATCH 1/3] Removing boxing on equality of System.Enum objects
Use magical System.Collections.Generic.EqualityComparer.Default for
typeof<_>.IsEnum
---
src/fsharp/FSharp.Core/prim-types.fs | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs
index bf1168b597d..6ff1b7e7145 100644
--- a/src/fsharp/FSharp.Core/prim-types.fs
+++ b/src/fsharp/FSharp.Core/prim-types.fs
@@ -1793,6 +1793,16 @@ namespace Microsoft.FSharp.Core
if x.HasValue then x.Value.GetHashCode ()
else 0
+ module EqualityComparerDefault =
+ []
+ type Impl<'a> =
+ interface IEssenceOfEquals<'a> with
+ member __.Ensorcel (_:IEqualityComparer, x:'a, y:'a) =
+ System.Collections.Generic.EqualityComparer.Default.Equals (x, y)
+ interface IEssenceOfGetHashCode<'a> with
+ member __.Ensorcel (_:IEqualityComparer, x:'a) =
+ System.Collections.Generic.EqualityComparer.Default.GetHashCode x
+
module ValueType =
[]
type StructuralEquatable<'a when 'a : struct and 'a :> IStructuralEquatable> =
@@ -2628,6 +2638,11 @@ namespace Microsoft.FSharp.Core
elif t.Equals typeof then typeof
else null
+ let enumTypes (t:Type) : Type =
+ if t.IsEnum
+ then mos.makeType t typedefof>
+ else null
+
let compilerGenerated tyRelation ty =
// if we are using the ER comparer, and we are a standard f# record or value type with compiler generated
// equality operators, then we can avoid the boxing of IStructuralEquatable and just call the
@@ -2699,6 +2714,7 @@ namespace Microsoft.FSharp.Core
fun () -> tuples tyRelation ty
fun () -> floatingPointTypes tyRelation ty
fun () -> standardTypes ty
+ fun () -> enumTypes ty
fun () -> compilerGenerated tyRelation ty
fun () -> arrays tyRelation ty
fun () -> nullableType ty
@@ -3052,6 +3068,11 @@ namespace Microsoft.FSharp.Core
elif t.Equals typeof then typeof
else null
+ let enumTypes (t:Type) : Type =
+ if t.IsEnum
+ then mos.makeType t typedefof>
+ else null
+
[]
type GenericHashParamObject<'a> =
interface IEssenceOfGetHashCode<'a> with
@@ -3093,6 +3114,7 @@ namespace Microsoft.FSharp.Core
mos.takeFirstNonNull [|
fun () -> tuples t
fun () -> standardTypes t
+ fun () -> enumTypes t
fun () -> arrays t
fun () -> nullableType t
fun () -> structualEquatable t
From b37f855280419b61ce0999f365585da8cbd34690 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 3 Feb 2016 19:48:37 +1100
Subject: [PATCH 2/3] Tests for equality of System.Enum derived objects
Tests try to ensure that the compiler doesn't inline the functionality
---
.../FSharp.Core/PrimTypes.fs | 52 +++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/PrimTypes.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/PrimTypes.fs
index 8f23db3a41e..a1dde2fbde8 100644
--- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/PrimTypes.fs
+++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/PrimTypes.fs
@@ -683,3 +683,55 @@ type UnboxAndOptionStuff() =
Assert.IsTrue( not (isNull [| |]))
Assert.IsTrue( not (isNull ""))
Assert.IsTrue( not (isNull "1"))
+
+
+type EnumA =
+| A0 = 0
+| A1 = 1
+| A2 = 2
+
+module EnumEqualityTestHelper =
+ let equals<'a when 'a : equality> (lhs:'a) (rhs:'a) =
+ // we are needlessly complex here to avoid the compiler from inlining this function
+ let r = System.Random ()
+ let n = r.Next ()
+ let mutable result = Unchecked.defaultof<_>
+ for i = n to n do
+ result <- lhs = rhs
+ result
+
+ let equals2<'a when 'a : equality> (lhs:'a) (rhs:'a) =
+ LanguagePrimitives.FastGenericEqualityComparer.Equals (lhs, rhs)
+
+[]
+type EnumEqualityTest() =
+ []
+ member this.EqualityCheck () =
+ Assert.IsTrue (EnumEqualityTestHelper.equals EnumA.A0 EnumA.A0)
+ Assert.IsFalse (EnumEqualityTestHelper.equals EnumA.A0 EnumA.A1)
+ Assert.IsFalse (EnumEqualityTestHelper.equals EnumA.A0 EnumA.A2)
+
+ Assert.IsFalse (EnumEqualityTestHelper.equals EnumA.A1 EnumA.A0)
+ Assert.IsTrue (EnumEqualityTestHelper.equals EnumA.A1 EnumA.A1)
+ Assert.IsFalse (EnumEqualityTestHelper.equals EnumA.A1 EnumA.A2)
+
+ Assert.IsFalse (EnumEqualityTestHelper.equals EnumA.A2 EnumA.A0)
+ Assert.IsFalse (EnumEqualityTestHelper.equals EnumA.A2 EnumA.A1)
+ Assert.IsTrue (EnumEqualityTestHelper.equals EnumA.A2 EnumA.A2)
+
+ []
+ member this.EqualityCheck2 () =
+ Assert.IsTrue (EnumEqualityTestHelper.equals2 EnumA.A0 EnumA.A0)
+ Assert.IsFalse (EnumEqualityTestHelper.equals2 EnumA.A0 EnumA.A1)
+ Assert.IsFalse (EnumEqualityTestHelper.equals2 EnumA.A0 EnumA.A2)
+
+ Assert.IsFalse (EnumEqualityTestHelper.equals2 EnumA.A1 EnumA.A0)
+ Assert.IsTrue (EnumEqualityTestHelper.equals2 EnumA.A1 EnumA.A1)
+ Assert.IsFalse (EnumEqualityTestHelper.equals2 EnumA.A1 EnumA.A2)
+
+ Assert.IsFalse (EnumEqualityTestHelper.equals2 EnumA.A2 EnumA.A0)
+ Assert.IsFalse (EnumEqualityTestHelper.equals2 EnumA.A2 EnumA.A1)
+ Assert.IsTrue (EnumEqualityTestHelper.equals2 EnumA.A2 EnumA.A2)
+
+
+
From 13a1129bf67c6846bb2d346bcf8b1ef6d4203ad0 Mon Sep 17 00:00:00 2001
From: Paul Westcott
Date: Wed, 3 Feb 2016 20:36:25 +1100
Subject: [PATCH 3/3] Add IsEnum for reshaped reflection
To support alternative profiles
---
src/fsharp/FSharp.Core/prim-types.fs | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs
index 6ff1b7e7145..7086c4dadd7 100644
--- a/src/fsharp/FSharp.Core/prim-types.fs
+++ b/src/fsharp/FSharp.Core/prim-types.fs
@@ -402,6 +402,7 @@ namespace Microsoft.FSharp.Core
type System.Type with
member inline this.IsGenericType = this.GetTypeInfo().IsGenericType
member inline this.IsValueType = this.GetTypeInfo().IsValueType
+ member inline this.IsEnum = this.GetTypeInfo().IsEnum
member inline this.IsSealed = this.GetTypeInfo().IsSealed
member inline this.IsAssignableFrom(otherTy : Type) = this.GetTypeInfo().IsAssignableFrom(otherTy.GetTypeInfo())
member inline this.GetGenericArguments() = this.GetTypeInfo().GenericTypeArguments