anchor.diff:                          else i <- i + 1
                       res
   
  +            type EqualityComparerInfo =
  +            | PER = 0
  +            | ER = 1
  +
  +            type IEqualityComparerInfo =
  +                abstract Info : EqualityComparerInfo
   
               /// One of the two unique instances of System.Collections.IEqualityComparer. Implements PER semantics
               /// where equality on NaN returns "false".
               let fsEqualityComparerNoHashingPER = 
                   { new System.Collections.IEqualityComparer with
                       override iec.Equals(x:obj,y:obj) = GenericEqualityObj false iec (x,y)  // PER Semantics
  -                    override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing))) }
  -                    
  +                    override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing)))
  +                  interface IEqualityComparerInfo with
  +                    member __.Info = EqualityComparerInfo.PER }
  +
               /// One of the two unique instances of System.Collections.IEqualityComparer. Implements ER semantics
               /// where equality on NaN returns "true".
               let fsEqualityComparerNoHashingER = 
                   { new System.Collections.IEqualityComparer with
                       override iec.Equals(x:obj,y:obj) = GenericEqualityObj true iec (x,y)  // ER Semantics
  -                    override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing))) }
  +                    override iec.GetHashCode(x:obj) = raise (InvalidOperationException (SR.GetString(SR.notUsedForHashing)))
  +                  interface IEqualityComparerInfo with
  +                    member __.Info = EqualityComparerInfo.ER }
   
               type private EquivalenceRelation = class end
               type private PartialEquivalenceRelation = class end
   
  -            type GenericSpecializeEquals_StandardTypes<'a>() =
  -                static let generalize (func:Func<IEqualityComparer,'aa,'aa,bool>) =
  -                    match box func with
  -                    | :? Func<IEqualityComparer,'a, 'a, bool> as f -> f
  -                    | _ -> raise (Exception "invalid logic")
  -
  -                static let _func =
  -                    match typeof<'a> with
  -                    | t when t.Equals typeof<bool>       -> generalize (Func<_,_,_,_>(fun _ (x:bool)      y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<sbyte>      -> generalize (Func<_,_,_,_>(fun _ (x:sbyte)     y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<int16>      -> generalize (Func<_,_,_,_>(fun _ (x:int16)     y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<int32>      -> generalize (Func<_,_,_,_>(fun _ (x:int32)     y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<int64>      -> generalize (Func<_,_,_,_>(fun _ (x:int64)     y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<byte>       -> generalize (Func<_,_,_,_>(fun _ (x:byte)      y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<uint16>     -> generalize (Func<_,_,_,_>(fun _ (x:uint16)    y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<uint32>     -> generalize (Func<_,_,_,_>(fun _ (x:uint32)    y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<uint64>     -> generalize (Func<_,_,_,_>(fun _ (x:uint64)    y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<nativeint>  -> generalize (Func<_,_,_,_>(fun _ (x:nativeint) y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<unativeint> -> generalize (Func<_,_,_,_>(fun _ (x:unativeint)y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<char>       -> generalize (Func<_,_,_,_>(fun _ (x:char)      y -> (# "ceq" x y : bool #)))
  -                    | t when t.Equals typeof<string>     -> generalize (Func<_,_,_,_>(fun _ (x:string)    y -> System.String.Equals((# "" x : string #),(# "" y : string #))))
  -                    | t when t.Equals typeof<decimal>    -> generalize (Func<_,_,_,_>(fun _ (x:decimal)   y -> System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #))))
  +            type GenericSpecializeEqualsOther =
  +            | ReferenceTypeStructuralEquality   = 0
  +            | ReferenceTypeSealed               = 1
  +            | GenericEqualityObj_ER             = 2 
  +            | GenericEqualityObj_PER            = 3
  +
  +            module GenericSpecializeEquals =
  +                let standardTypes (ty:Type) : obj =
  +                    match ty with
  +                    | t when t.Equals typeof<bool>       -> upcast Func<IEqualityComparer,bool      ,bool      ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<sbyte>      -> upcast Func<IEqualityComparer,sbyte     ,sbyte     ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<int16>      -> upcast Func<IEqualityComparer,int16     ,int16     ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<int32>      -> upcast Func<IEqualityComparer,int32     ,int32     ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<int64>      -> upcast Func<IEqualityComparer,int64     ,int64     ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<byte>       -> upcast Func<IEqualityComparer,byte      ,byte      ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<uint16>     -> upcast Func<IEqualityComparer,uint16    ,uint16    ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<uint32>     -> upcast Func<IEqualityComparer,uint32    ,uint32    ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<uint64>     -> upcast Func<IEqualityComparer,uint64    ,uint64    ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<nativeint>  -> upcast Func<IEqualityComparer,nativeint ,nativeint ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<unativeint> -> upcast Func<IEqualityComparer,unativeint,unativeint,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<char>       -> upcast Func<IEqualityComparer,char      ,char      ,bool>(fun _ x y -> (# "ceq" x y : bool #))
  +                    | t when t.Equals typeof<string>     -> upcast Func<IEqualityComparer,string    ,string    ,bool>(fun _ x y -> System.String.Equals((# "" x : string #),(# "" y : string #)))
  +                    | t when t.Equals typeof<decimal>    -> upcast Func<IEqualityComparer,decimal   ,decimal   ,bool>(fun _ x y -> System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #)))
                       | _ -> null
  -                            
  -                static member Func = _func
  -
  -            type GenericSpecializeEquals_EqualityInterfaces<'a>() =
  -                static let _func =
  -                    match typeof<'a> with
  +
  +                let makeEquatableType ty =
  +                    let equatableTypedef = typedefof<IEquatable<_>>
  +                    equatableTypedef.MakeGenericType [|ty|]
  +
  +                let makeReturnType ty =
  +                    let func4Typedef = typedefof<Func<_,_,_,_>>
  +                    func4Typedef.MakeGenericType [| typeof<IEqualityComparer>; ty; ty; typeof<bool> |]
  +
  +                let equalityInterfaces (ty:Type) : obj =
  +                    match ty with
                       | t when t.IsArray || typeof<System.Array>.IsAssignableFrom t ->
                           // I could do something here, but I doubt it would have any real performance impact
                           null
  
positive.code:             // The compiler optimizer is aware of this function (see use of generic_equality_er_inner_vref in opt.fs)
              // and devirtualizes calls to it based on "T".
              let GenericEqualityERIntrinsic (x : 'T) (y : 'T) : bool =
                  eliminate_tail_call_bool (GenericSpecializeEqualsWithRelation<EquivalenceRelation,_>.Func.Invoke (fsEqualityComparerNoHashingER, x, y))
                  
              /// Implements generic equality between two values using "comp" for recursive calls.
              //
  
negative.code:             // this is doucmented here- https://github.com/Microsoft/visualfsharp/pull/513#issuecomment-117995410
              let GenericEqualityWithComparerIntrinsic (comp : System.Collections.IEqualityComparer) (x : 'T) (y : 'T) : bool =
                  match comp with
                  | :? IEqualityComparerInfo as info ->
                      match info.Info with
                      | EqualityComparerInfo.ER  -> eliminate_tail_call_bool (GenericEqualityERIntrinsic x y)
                      | EqualityComparerInfo.PER -> eliminate_tail_call_bool (GenericEqualityIntrinsic x y)
                      | _ -> raise (Exception "invalid logic")
                  | c when obj.ReferenceEquals (c, EqualityComparer<'T>.Default)   ->
                      eliminate_tail_call_bool (EqualityComparer<'T>.Default.Equals (x, y))
                  | _ ->
                      eliminate_tail_call_bool (comp.Equals (box x, box y))
  
              /// Implements generic equality between two values, with ER semantics for NaN (so equality on two NaN values returns true)
              //
  