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) + + + diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index bf1168b597d..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 @@ -1793,6 +1794,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 +2639,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 +2715,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 +3069,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 +3115,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