diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs
index 445f93aa2fc..96ff2ea9b2c 100644
--- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs
+++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs
@@ -205,6 +205,7 @@ Microsoft.FSharp.Collections.ArrayModule: Void SortInPlace[T](T[])
Microsoft.FSharp.Collections.ComparisonIdentity: Boolean Equals(System.Object)
Microsoft.FSharp.Collections.ComparisonIdentity: Int32 GetHashCode()
Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] FromFunction[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]])
+Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] NonStructural[T]()
Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]()
Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString()
Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType()
@@ -289,6 +290,7 @@ Microsoft.FSharp.Collections.HashIdentity: Boolean Equals(System.Object)
Microsoft.FSharp.Collections.HashIdentity: Int32 GetHashCode()
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] FromFunctions[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]])
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] LimitedStructural[T](Int32)
+Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] NonStructural[T]()
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Reference[T]()
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Structural[T]()
Microsoft.FSharp.Collections.HashIdentity: System.String ToString()
@@ -2443,6 +2445,20 @@ Microsoft.FSharp.Core.Operators+Checked: UInt16 ToUInt16[T](T)
Microsoft.FSharp.Core.Operators+Checked: UInt32 ToUInt32[T](T)
Microsoft.FSharp.Core.Operators+Checked: UInt64 ToUInt64[T](T)
Microsoft.FSharp.Core.Operators+Checked: UIntPtr ToUIntPtr[T](T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean Equals(System.Object)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Equality[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThanOrEqual[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThan[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Inequality[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThanOrEqual[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThan[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Compare[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 GetHashCode()
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Hash[T](T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: System.String ToString()
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: System.Type GetType()
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Max[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Min[T](T, T)
Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Boolean Equals(System.Object)
Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Byte PowByte(Byte, Int32)
Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Double PowDouble(Double, Int32)
@@ -2553,6 +2569,7 @@ Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[System.Str
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[T] TryUnbox[T](System.Object)
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpRef`1[T] Ref[T](T)
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+Checked
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+NonStructuralComparison
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+OperatorIntrinsics
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+Unchecked
Microsoft.FSharp.Core.Operators: SByte ToSByte[T](T)
diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs
index c357eaac653..37cb72619dd 100644
--- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs
+++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Portable.fs
@@ -199,6 +199,7 @@ Microsoft.FSharp.Collections.ArrayModule: Void SortInPlace[T](T[])
Microsoft.FSharp.Collections.ComparisonIdentity: Boolean Equals(System.Object)
Microsoft.FSharp.Collections.ComparisonIdentity: Int32 GetHashCode()
Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] FromFunction[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]])
+Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] NonStructural[T]()
Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]()
Microsoft.FSharp.Collections.ComparisonIdentity: System.String ToString()
Microsoft.FSharp.Collections.ComparisonIdentity: System.Type GetType()
@@ -283,6 +284,7 @@ Microsoft.FSharp.Collections.HashIdentity: Boolean Equals(System.Object)
Microsoft.FSharp.Collections.HashIdentity: Int32 GetHashCode()
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] FromFunctions[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]])
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] LimitedStructural[T](Int32)
+Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] NonStructural[T]()
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Reference[T]()
Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Structural[T]()
Microsoft.FSharp.Collections.HashIdentity: System.String ToString()
@@ -2430,6 +2432,20 @@ Microsoft.FSharp.Core.Operators+Checked: UInt16 ToUInt16[T](T)
Microsoft.FSharp.Core.Operators+Checked: UInt32 ToUInt32[T](T)
Microsoft.FSharp.Core.Operators+Checked: UInt64 ToUInt64[T](T)
Microsoft.FSharp.Core.Operators+Checked: UIntPtr ToUIntPtr[T](T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean Equals(System.Object)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Equality[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThanOrEqual[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThan[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Inequality[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThanOrEqual[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThan[T,TResult](T, TResult)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Compare[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 GetHashCode()
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Hash[T](T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: System.String ToString()
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: System.Type GetType()
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Max[T](T, T)
+Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Min[T](T, T)
Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Boolean Equals(System.Object)
Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Byte PowByte(Byte, Int32)
Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Double PowDouble(Double, Int32)
@@ -2540,6 +2556,7 @@ Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[System.Str
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpOption`1[T] TryUnbox[T](System.Object)
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpRef`1[T] Ref[T](T)
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+Checked
+Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+NonStructuralComparison
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+OperatorIntrinsics
Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+Unchecked
Microsoft.FSharp.Core.Operators: SByte ToSByte[T](T)
diff --git a/src/fsharp/FSharp.Core/Linq.fs b/src/fsharp/FSharp.Core/Linq.fs
index 64b0217c7e3..1156b25527b 100644
--- a/src/fsharp/FSharp.Core/Linq.fs
+++ b/src/fsharp/FSharp.Core/Linq.fs
@@ -233,6 +233,13 @@ module LeafExpressionConverter =
let (|LessEqQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x,y) -> x <= y))
let (|NotEqQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x,y) -> x <> y))
+ let (|StaticEqualsQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x:int,y:int) -> NonStructuralComparison.(=) x y))
+ let (|StaticGreaterQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x:int,y:int) -> NonStructuralComparison.(>) x y))
+ let (|StaticGreaterEqQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x:int,y:int) -> NonStructuralComparison.(>=) x y))
+ let (|StaticLessQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x:int,y:int) -> NonStructuralComparison.(<) x y))
+ let (|StaticLessEqQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x:int,y:int) -> NonStructuralComparison.(<=) x y))
+ let (|StaticNotEqQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x:int,y:int) -> NonStructuralComparison.(<>) x y))
+
let (|NullableEqualsQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x,y) -> NullableOperators.( ?= ) x y))
let (|NullableNotEqQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x,y) -> NullableOperators.( ?<> ) x y))
let (|NullableGreaterQ|_|) = (|SpecificCallToMethod|_|) (methodhandleof (fun (x,y) -> NullableOperators.( ?> ) x y))
@@ -487,6 +494,13 @@ module LeafExpressionConverter =
| LessEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThanOrEqual
| NotQ (_, _, [x1]) -> Expression.Not(ConvExprToLinqInContext env x1) |> asExpr
+ | StaticEqualsQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.Equal
+ | StaticNotEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.NotEqual
+ | StaticGreaterQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThan
+ | StaticGreaterEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.GreaterThanOrEqual
+ | StaticLessQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThan
+ | StaticLessEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 false Expression.LessThanOrEqual
+
| NullableEqualsQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.Equal
| NullableNotEqQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.NotEqual
| NullableGreaterQ (_, _,[x1;x2]) -> transBinOp env false x1 x2 true Expression.GreaterThan
diff --git a/src/fsharp/FSharp.Core/collections.fs b/src/fsharp/FSharp.Core/collections.fs
index 3c7f41e3058..6c4e2b23fa8 100644
--- a/src/fsharp/FSharp.Core/collections.fs
+++ b/src/fsharp/FSharp.Core/collections.fs
@@ -28,6 +28,11 @@ namespace Microsoft.FSharp.Collections
member self.GetHashCode(x) = LanguagePrimitives.PhysicalHash(x)
member self.Equals(x,y) = LanguagePrimitives.PhysicalEquality x y }
+ let inline NonStructural< 'T when 'T : equality and 'T : (static member ( = ) : 'T * 'T -> bool) > =
+ { new IEqualityComparer< 'T > with
+ member self.GetHashCode(x) = NonStructuralComparison.hash x
+ member self.Equals(x, y) = NonStructuralComparison.(=) x y }
+
let inline FromFunctions hash eq : IEqualityComparer<'T> =
let eq = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(eq)
{ new IEqualityComparer<'T> with
@@ -37,10 +42,16 @@ namespace Microsoft.FSharp.Collections
module ComparisonIdentity =
-
let inline Structural<'T when 'T : comparison > : IComparer<'T> =
LanguagePrimitives.FastGenericComparer<'T>
-
+
+#if BUILDING_WITH_LKG
+#else
+ let inline NonStructural< 'T when 'T : (static member ( < ) : 'T * 'T -> bool) and 'T : (static member ( > ) : 'T * 'T -> bool) > : IComparer< 'T > =
+ { new IComparer<'T> with
+ member self.Compare(x,y) = NonStructuralComparison.compare x y }
+#endif
+
let FromFunction comparer =
let comparer = OptimizedClosures.FSharpFunc<'T,'T,int>.Adapt(comparer)
{ new IComparer<'T> with
diff --git a/src/fsharp/FSharp.Core/collections.fsi b/src/fsharp/FSharp.Core/collections.fsi
index 4ae00f4e644..10e71fceb96 100644
--- a/src/fsharp/FSharp.Core/collections.fsi
+++ b/src/fsharp/FSharp.Core/collections.fsi
@@ -14,7 +14,13 @@ namespace Microsoft.FSharp.Collections
/// Structural comparison. Compare using Operators.compare.
val inline Structural<'T> : IComparer<'T> when 'T : comparison
-
+
+#if BUILDING_WITH_LKG
+#else
+ /// Non-structural comparison. Compare using NonStructuralComparison.compare.
+ val inline NonStructural< ^T > : IComparer< ^T > when ^T : (static member ( < ) : ^T * ^T -> bool) and ^T : (static member ( > ) : ^T * ^T -> bool)
+#endif
+
/// Compare using the given comparer function.
/// A function to compare two values.
/// An object implementing IComparer using the supplied comparer.
@@ -24,10 +30,11 @@ namespace Microsoft.FSharp.Collections
module HashIdentity =
/// Structural hashing. Hash using Operators.(=) and Operators.hash.
-
- // inline justification: allows specialization of structural hash functions based on type
val inline Structural<'T> : IEqualityComparer<'T> when 'T : equality
+ /// Non-structural hashing. Equality using NonStructuralComparison.(=) and NonStructuralComparison.hash.
+ val inline NonStructural<'T> : IEqualityComparer< ^T > when ^T : equality and ^T : (static member ( = ) : ^T * ^T -> bool)
+
val inline LimitedStructural<'T> : limit: int -> IEqualityComparer<'T> when 'T : equality
/// Physical hashing (hash on reference identity of objects, and the contents of value types).
diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs
index 15eaae8ad34..2fc6ada8824 100644
--- a/src/fsharp/FSharp.Core/prim-types.fs
+++ b/src/fsharp/FSharp.Core/prim-types.fs
@@ -956,13 +956,8 @@ namespace Microsoft.FSharp.Core
| null,null -> 0
| null,_ -> -1
| _,null -> 1
-#if INVARIANT_CULTURE_STRING_COMPARISON
- // Use invariant culture comparison for strings
- | (:? string as x),(:? string as y) -> System.String.Compare(x, y, false, CultureInfo.InvariantCulture)
-#else
// Use Ordinal comparison for strings
| (:? string as x),(:? string as y) -> System.String.CompareOrdinal(x, y)
-#endif
// Permit structural comparison on arrays
| (:? System.Array as arr1),_ ->
match arr1,yobj with
@@ -1216,15 +1211,9 @@ namespace Microsoft.FSharp.Core
when 'T : float32 = if (# "clt" x y : bool #) then (-1) else if (# "cgt" x y : bool #) then 1 else if (# "ceq" x y : bool #) then 0 else GenericComparisonWithComparerIntrinsic comp x y
when 'T : char = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
when 'T : string =
-#if INVARIANT_CULTURE_STRING_COMPARISON
- // NOTE: we don't have to null check here because System.String.Compare
- // gives reliable results on null values.
- System.String.Compare((# "" x : string #) ,(# "" y : string #), false, CultureInfo.InvariantCulture)
-#else
// NOTE: we don't have to null check here because System.String.CompareOrdinal
// gives reliable results on null values.
System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))
-#endif
when 'T : decimal = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #))
@@ -1292,15 +1281,9 @@ namespace Microsoft.FSharp.Core
when 'T : float32 = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
when 'T : char = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
when 'T : string =
-#if INVARIANT_CULTURE_STRING_COMPARISON
- // NOTE: we don't have to null check here because System.String.Compare
- // gives reliable results on null values.
- System.String.Compare((# "" x : string #) ,(# "" y : string #), false, CultureInfo.InvariantCulture)
-#else
// NOTE: we don't have to null check here because System.String.CompareOrdinal
// gives reliable results on null values.
System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))
-#endif
when 'T : decimal = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #))
/// Generic less-than with static optimizations for some well-known cases.
@@ -4499,6 +4482,180 @@ namespace Microsoft.FSharp.Core
when ^T : byte = (# "conv.u2" x : char #)
+ module NonStructuralComparison =
+ /// Static less-than with static optimizations for some well-known cases.
+ let inline (<) (x:^T) (y:^U) =
+ ((^T or ^U): (static member (<) : ^T * ^U -> bool) (x,y))
+ when ^T : bool = (# "clt" x y : bool #)
+ when ^T : sbyte = (# "clt" x y : bool #)
+ when ^T : int16 = (# "clt" x y : bool #)
+ when ^T : int32 = (# "clt" x y : bool #)
+ when ^T : int64 = (# "clt" x y : bool #)
+ when ^T : byte = (# "clt.un" x y : bool #)
+ when ^T : uint16 = (# "clt.un" x y : bool #)
+ when ^T : uint32 = (# "clt.un" x y : bool #)
+ when ^T : uint64 = (# "clt.un" x y : bool #)
+ when ^T : unativeint = (# "clt.un" x y : bool #)
+ when ^T : nativeint = (# "clt" x y : bool #)
+ when ^T : float = (# "clt" x y : bool #)
+ when ^T : float32= (# "clt" x y : bool #)
+ when ^T : char = (# "clt" x y : bool #)
+ when ^T : decimal = System.Decimal.op_LessThan ((# "" x:decimal #), (# "" y:decimal #))
+ when ^T : string = (# "clt" (System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))) 0 : bool #)
+
+ /// Static greater-than with static optimizations for some well-known cases.
+ let inline (>) (x:^T) (y:^U) =
+ ((^T or ^U): (static member (>) : ^T * ^U -> bool) (x,y))
+ when 'T : bool = (# "cgt" x y : bool #)
+ when 'T : sbyte = (# "cgt" x y : bool #)
+ when 'T : int16 = (# "cgt" x y : bool #)
+ when 'T : int32 = (# "cgt" x y : bool #)
+ when 'T : int64 = (# "cgt" x y : bool #)
+ when 'T : nativeint = (# "cgt" x y : bool #)
+ when 'T : byte = (# "cgt.un" x y : bool #)
+ when 'T : uint16 = (# "cgt.un" x y : bool #)
+ when 'T : uint32 = (# "cgt.un" x y : bool #)
+ when 'T : uint64 = (# "cgt.un" x y : bool #)
+ when 'T : unativeint = (# "cgt.un" x y : bool #)
+ when 'T : float = (# "cgt" x y : bool #)
+ when 'T : float32 = (# "cgt" x y : bool #)
+ when 'T : char = (# "cgt" x y : bool #)
+ when 'T : decimal = System.Decimal.op_GreaterThan ((# "" x:decimal #), (# "" y:decimal #))
+ when ^T : string = (# "cgt" (System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))) 0 : bool #)
+
+ /// Static less-than-or-equal with static optimizations for some well-known cases.
+ let inline (<=) (x:^T) (y:^U) =
+ ((^T or ^U): (static member (<=) : ^T * ^U -> bool) (x,y))
+ when 'T : bool = not (# "cgt" x y : bool #)
+ when 'T : sbyte = not (# "cgt" x y : bool #)
+ when 'T : int16 = not (# "cgt" x y : bool #)
+ when 'T : int32 = not (# "cgt" x y : bool #)
+ when 'T : int64 = not (# "cgt" x y : bool #)
+ when 'T : nativeint = not (# "cgt" x y : bool #)
+ when 'T : byte = not (# "cgt.un" x y : bool #)
+ when 'T : uint16 = not (# "cgt.un" x y : bool #)
+ when 'T : uint32 = not (# "cgt.un" x y : bool #)
+ when 'T : uint64 = not (# "cgt.un" x y : bool #)
+ when 'T : unativeint = not (# "cgt.un" x y : bool #)
+ when 'T : float = not (# "cgt.un" x y : bool #)
+ when 'T : float32 = not (# "cgt.un" x y : bool #)
+ when 'T : char = not (# "cgt" x y : bool #)
+ when 'T : decimal = System.Decimal.op_LessThanOrEqual ((# "" x:decimal #), (# "" y:decimal #))
+ when ^T : string = not (# "cgt" (System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))) 0 : bool #)
+
+ /// Static greater-than-or-equal with static optimizations for some well-known cases.
+ let inline (>=) (x:^T) (y:^U) =
+ ((^T or ^U): (static member (>=) : ^T * ^U -> bool) (x,y))
+ when 'T : bool = not (# "clt" x y : bool #)
+ when 'T : sbyte = not (# "clt" x y : bool #)
+ when 'T : int16 = not (# "clt" x y : bool #)
+ when 'T : int32 = not (# "clt" x y : bool #)
+ when 'T : int64 = not (# "clt" x y : bool #)
+ when 'T : nativeint = not (# "clt" x y : bool #)
+ when 'T : byte = not (# "clt.un" x y : bool #)
+ when 'T : uint16 = not (# "clt.un" x y : bool #)
+ when 'T : uint32 = not (# "clt.un" x y : bool #)
+ when 'T : uint64 = not (# "clt.un" x y : bool #)
+ when 'T : unativeint = not (# "clt.un" x y : bool #)
+ when 'T : float = not (# "clt.un" x y : bool #)
+ when 'T : float32 = not (# "clt.un" x y : bool #)
+ when 'T : char = not (# "clt" x y : bool #)
+ when 'T : decimal = System.Decimal.op_GreaterThanOrEqual ((# "" x:decimal #), (# "" y:decimal #))
+ when ^T : string = not (# "clt" (System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))) 0 : bool #)
+
+
+ /// Static greater-than-or-equal with static optimizations for some well-known cases.
+ let inline (=) (x:^T) (y:^T) =
+ (^T : (static member (=) : ^T * ^T -> bool) (x,y))
+ when ^T : bool = (# "ceq" x y : bool #)
+ when ^T : sbyte = (# "ceq" x y : bool #)
+ when ^T : int16 = (# "ceq" x y : bool #)
+ when ^T : int32 = (# "ceq" x y : bool #)
+ when ^T : int64 = (# "ceq" x y : bool #)
+ when ^T : byte = (# "ceq" x y : bool #)
+ when ^T : uint16 = (# "ceq" x y : bool #)
+ when ^T : uint32 = (# "ceq" x y : bool #)
+ when ^T : uint64 = (# "ceq" x y : bool #)
+ when ^T : float = (# "ceq" x y : bool #)
+ when ^T : float32 = (# "ceq" x y : bool #)
+ when ^T : char = (# "ceq" x y : bool #)
+ when ^T : nativeint = (# "ceq" x y : bool #)
+ when ^T : unativeint = (# "ceq" x y : bool #)
+ when ^T : string = System.String.Equals((# "" x : string #),(# "" y : string #))
+ when ^T : decimal = System.Decimal.op_Equality((# "" x:decimal #), (# "" y:decimal #))
+
+ let inline (<>) (x:^T) (y:^T) =
+ (^T : (static member (<>) : ^T * ^T -> bool) (x,y))
+ when ^T : bool = not (# "ceq" x y : bool #)
+ when ^T : sbyte = not (# "ceq" x y : bool #)
+ when ^T : int16 = not (# "ceq" x y : bool #)
+ when ^T : int32 = not (# "ceq" x y : bool #)
+ when ^T : int64 = not (# "ceq" x y : bool #)
+ when ^T : byte = not (# "ceq" x y : bool #)
+ when ^T : uint16 = not (# "ceq" x y : bool #)
+ when ^T : uint32 = not (# "ceq" x y : bool #)
+ when ^T : uint64 = not (# "ceq" x y : bool #)
+ when ^T : float = not (# "ceq" x y : bool #)
+ when ^T : float32 = not (# "ceq" x y : bool #)
+ when ^T : char = not (# "ceq" x y : bool #)
+ when ^T : nativeint = not (# "ceq" x y : bool #)
+ when ^T : unativeint = not (# "ceq" x y : bool #)
+ when ^T : string = not (System.String.Equals((# "" x : string #),(# "" y : string #)))
+ when ^T : decimal = System.Decimal.op_Inequality((# "" x:decimal #), (# "" y:decimal #))
+
+
+ []
+ let inline compare (x:^T) (y:^T) : int =
+ (if x < y then -1 elif x > y then 1 else 0)
+ when ^T : bool = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : sbyte = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : int16 = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : int32 = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : int64 = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : nativeint = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : byte = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
+ when ^T : uint16 = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
+ when ^T : uint32 = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
+ when ^T : uint64 = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
+ when ^T : unativeint = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
+ when ^T : float = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : float32 = if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)
+ when ^T : char = if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)
+ when ^T : string =
+ // NOTE: we don't have to null check here because System.String.CompareOrdinal
+ // gives reliable results on null values.
+ System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))
+ when ^T : decimal = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #))
+
+ []
+ let inline max (x:^T) y =
+ (if x < y then y else x)
+ when ^T : float = (System.Math.Max : float * float -> float)(retype<_,float> x, retype<_,float> y)
+ when ^T : float32 = (System.Math.Max : float32 * float32 -> float32)(retype<_,float32> x, retype<_,float32> y)
+
+ []
+ let inline min (x: ^T) y =
+ (if x < y then x else y)
+ when ^T : float = (System.Math.Min : float * float -> float)(retype<_,float> x, retype<_,float> y)
+ when ^T : float32 = (System.Math.Min : float32 * float32 -> float32)(retype<_,float32> x, retype<_,float32> y)
+
+ []
+ let inline hash (x:'T) =
+ x.GetHashCode()
+ when 'T : bool = (# "" x : int #)
+ when 'T : int32 = (# "" x : int #)
+ when 'T : byte = (# "" x : int #)
+ when 'T : uint32 = (# "" x : int #)
+ when 'T : char = HashCompare.HashChar (# "" x : char #)
+ when 'T : sbyte = HashCompare.HashSByte (# "" x : sbyte #)
+ when 'T : int16 = HashCompare.HashInt16 (# "" x : int16 #)
+ when 'T : int64 = HashCompare.HashInt64 (# "" x : int64 #)
+ when 'T : uint64 = HashCompare.HashUInt64 (# "" x : uint64 #)
+ when 'T : nativeint = HashCompare.HashIntPtr (# "" x : nativeint #)
+ when 'T : unativeint = HashCompare.HashUIntPtr (# "" x : unativeint #)
+ when 'T : uint16 = (# "" x : int #)
+ when 'T : string = HashCompare.HashString (# "" x : string #)
+
module Attributes =
open System.Runtime.CompilerServices
diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi
index 916232c3e87..dc8ee26bfdf 100644
--- a/src/fsharp/FSharp.Core/prim-types.fsi
+++ b/src/fsharp/FSharp.Core/prim-types.fsi
@@ -3047,6 +3047,73 @@ namespace Microsoft.FSharp.Core
/// The computed hash value.
val inline hash : 'T -> int
+ /// A module of comparison and equality operators that are statically resolved, but which are not fully generic and do not make structural comparison. Opening this
+ /// module may make code that relies on structural or generic comparison no longer compile.
+ module NonStructuralComparison =
+
+ /// Compares the two values for less-than
+ /// The first parameter.
+ /// The second parameter.
+ /// The result of the comparison.
+ val inline ( < ) : x:^T -> y:^U -> bool when (^T or ^U) : (static member ( < ) : ^T * ^U -> bool)
+
+ /// Compares the two values for greater-than
+ /// The first parameter.
+ /// The second parameter.
+ /// The result of the comparison.
+ val inline ( > ) : x:^T -> y:^U -> bool when (^T or ^U) : (static member ( > ) : ^T * ^U -> bool)
+
+ /// Compares the two values for greater-than-or-equal
+ /// The first parameter.
+ /// The second parameter.
+ /// The result of the comparison.
+ val inline ( >= ) : x:^T -> y:^U -> bool when (^T or ^U) : (static member ( >= ) : ^T * ^U -> bool)
+
+ /// Compares the two values for less-than-or-equal
+ /// The first parameter.
+ /// The second parameter.
+ /// The result of the comparison.
+ val inline ( <= ) : x:^T -> y:^U -> bool when (^T or ^U) : (static member ( <= ) : ^T * ^U -> bool)
+
+ /// Compares the two values for equality
+ /// The first parameter.
+ /// The second parameter.
+ /// The result of the comparison.
+ val inline ( = ) : x:^T -> y:^T -> bool when ^T : (static member ( = ) : ^T * ^T -> bool)
+
+ /// Compares the two values for inequality
+ /// The first parameter.
+ /// The second parameter.
+ /// The result of the comparison.
+ val inline ( <> ) : x:^T -> y:^T -> bool when ^T : (static member ( <> ) : ^T * ^T -> bool)
+
+ /// Compares the two values
+ /// The first value.
+ /// The second value.
+ /// The result of the comparison.
+ []
+ val inline compare: e1:'T -> e2:^T -> int when ^T : (static member ( < ) : ^T * ^T -> bool) and ^T : (static member ( > ) : ^T * ^T -> bool)
+
+ /// Maximum of the two values
+ /// The first value.
+ /// The second value.
+ /// The maximum value.
+ []
+ val inline max : e1:^T -> e2:^T -> ^T when ^T : (static member ( < ) : ^T * ^T -> bool)
+
+ /// Minimum of the two values
+ /// The first value.
+ /// The second value.
+ /// The minimum value.
+ []
+ val inline min : e1:^T -> e2:^T -> ^T when ^T : (static member ( < ) : ^T * ^T -> bool)
+
+ /// Calls GetHashCode() on the value
+ /// The value.
+ /// The hash code.
+ []
+ val inline hash :value:'T -> int when 'T : equality
+
/// This module contains the basic arithmetic operations with overflow checks.
module Checked =
/// Overloaded unary negation (checks for overflow)
diff --git a/src/fsharp/csolve.fs b/src/fsharp/csolve.fs
index 99b095a8d82..92f338e6e8e 100644
--- a/src/fsharp/csolve.fs
+++ b/src/fsharp/csolve.fs
@@ -226,6 +226,7 @@ let rec isIntegerTy g ty =
let isStringTy g ty = typeEquiv g g.string_ty ty
let isCharTy g ty = typeEquiv g g.char_ty ty
+let isBoolTy g ty = typeEquiv g g.bool_ty ty
/// float or float32 or float<_> or float32<_>
let isFpTy g ty =
@@ -240,6 +241,7 @@ let IsNonDecimalNumericOrIntegralEnumType g ty = isIntegerOrIntegerEnumTy g ty |
let IsNumericOrIntegralEnumType g ty = IsNonDecimalNumericOrIntegralEnumType g ty || isDecimalTy g ty
let IsNonDecimalNumericType g ty = isIntegerTy g ty || isFpTy g ty
let IsNumericType g ty = IsNonDecimalNumericType g ty || isDecimalTy g ty
+let IsRelationalType g ty = IsNumericType g ty || isStringTy g ty || isCharTy g ty || isBoolTy g ty
// Get measure of type, float<_> or float32<_> or decimal<_> but not float=float<1> or float32=float32<1> or decimal=decimal<1>
let GetMeasureOfType g ty =
@@ -259,6 +261,7 @@ type TraitConstraintSolution =
let BakedInTraitConstraintNames =
[ "op_Division" ; "op_Multiply"; "op_Addition"
+ "op_Equality" ; "op_Inequality"; "op_GreaterThan" ; "op_LessThan"; "op_LessThanOrEqual"; "op_GreaterThanOrEqual"
"op_Subtraction"; "op_Modulus";
"get_Zero"; "get_One";
"DivideByInt";"get_Item"; "set_Item";
@@ -977,6 +980,14 @@ and SolveMemberConstraint (csenv:ConstraintSolverEnv) permitWeakResolution ndeep
SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty argty1 ++ (fun () ->
ResultD TTraitBuiltIn))
+ | _,_,false,("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ),[argty1;argty2]
+ when // Ignore any explicit overloads from any basic integral types
+ (minfos |> List.forall (fun minfo -> isIntegerTy g minfo.EnclosingType ) &&
+ ( (IsRelationalType g argty1 && (permitWeakResolution || not (isTyparTy g argty2)))
+ || (IsRelationalType g argty2 && (permitWeakResolution || not (isTyparTy g argty1))))) ->
+ SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace argty2 argty1 ++ (fun () ->
+ SolveTypEqualsTypKeepAbbrevs csenv ndeep m2 trace rty g.bool_ty ++ (fun () ->
+ ResultD TTraitBuiltIn))
// We pretend for uniformity that the numeric types have a static property called Zero and One
// As with constants, only zero is polymorphic in its units
diff --git a/tests/fsharp/core/libtest/test.fsx b/tests/fsharp/core/libtest/test.fsx
index 5a8c9cefbd6..d29eeb64906 100644
--- a/tests/fsharp/core/libtest/test.fsx
+++ b/tests/fsharp/core/libtest/test.fsx
@@ -71,12 +71,11 @@ let reportFailure s =
#else
let argv = System.Environment.GetCommandLineArgs()
let SetCulture() =
- if argv.Length > 2 && argv.[1] = "--culture" then begin
+ if argv.Length > 2 && argv.[1] = "--culture" then
let cultureString = argv.[2] in
let culture = new System.Globalization.CultureInfo(cultureString) in
stdout.WriteLine ("Running under culture "+culture.ToString()+"...");
System.Threading.Thread.CurrentThread.CurrentCulture <- culture
- end
do SetCulture()
#endif
@@ -818,7 +817,7 @@ let _ = printString "type specific hash matches generic hash (9): "; if getObjec
!* check we can resolve overlapping constructor names using type names
*--------------------------------------------------------------------------- *)
-module OverlappingCOnstructorNames = begin
+module OverlappingCOnstructorNames =
type XY = X | Y
type YZ = Y | Z
@@ -842,13 +841,6 @@ module OverlappingCOnstructorNames = begin
| YZ.Y -> "X"
| YZ.Z -> "Y"
-end
-
-
-(*---------------------------------------------------------------------------
-!* hashing of large terms that contain back pointers (are infinite)
- *--------------------------------------------------------------------------- *)
-
(*---------------------------------------------------------------------------
!* Equality tests over structured values for data likely to contain
@@ -1444,7 +1436,7 @@ let _ = test "List.rev d" (List.rev [1; 2] = [2; 1])
-module MinMaxAverageSum = begin
+module MinMaxAverageSum =
do test "ceijoe9cewz" (Seq.sum [] = 0)
do test "ceijoe9cewx" (Seq.sum [1;2;3] = 6)
do test "ceijoe9cewv" (Seq.sum [0.0;1.0] = 1.0)
@@ -1506,10 +1498,10 @@ module MinMaxAverageSum = begin
do test "ceijoe9ceww" (List.max [1.0M;2.0M;3.0M] = 3.0M)
do test "ceijoe9cewe" (List.max [3.0M;2.0M;1.0M] = 3.0M)
-end
-module Pow = begin
+
+module Pow =
do test "cnod90km1" (pown 2.0 -3 = 0.125)
do test "cnod90km2" (pown 2.0 -2 = 0.25)
do test "cnod90km3" (pown 2.0 -1 = 0.5)
@@ -1615,9 +1607,9 @@ module Pow = begin
test "cnod90kmbb1a" (pown (byte baseIdx) 2 = (byte baseIdx) * (byte baseIdx));
)
done
-end
-module TakeUntilSkipWhile = begin
+
+module TakeUntilSkipWhile =
do test "oewvjrrovvr1" ([ ] |> Seq.takeWhile (fun x -> x <= 5) |> Seq.toList = [ ])
do test "oewvjrrovvr2" ([ 1 ] |> Seq.takeWhile (fun x -> x <= 5) |> Seq.toList = [ 1 ])
@@ -1631,7 +1623,6 @@ module TakeUntilSkipWhile = begin
do test "oewvjrrovvr9" ([ 1;2;3;4;5;6;7 ] |> Seq.skipWhile (fun x -> x <= 5) |> Seq.toList = [ 6;7 ])
do test "oewvjrrovvra" ([ 1;2;3;4;5;6;5;4;3;2;1 ] |> Seq.skipWhile (fun x -> x <= 5) |> Seq.toList = [ 6;5;4;3;2;1 ])
-end
(*---------------------------------------------------------------------------
@@ -2087,19 +2078,19 @@ let sort_test cmp ans =
let _ = sort_test compare [0;1;2;3;4;5]
let _ = sort_test (fun x y -> -(compare x y)) [5;4;3;2;1;0]
*)
-module StrangeOperatorTest = begin
- let (&&&) x y = x^y
- let (<<<) (x:string) (y:string) = x ^y^x
+module StrangeOperatorTest =
+ let (&&&) x y = x^y
+ let (<<<) (x:string) (y:string) = x ^y^x
- let e1 = ("0" &&& ("1" <<< "2"))
- let e2= (("0" &&& "1") <<< "2")
- let e3= ("0" &&& "1" <<< "2")
+ let e1 = ("0" &&& ("1" <<< "2"))
+ let e2= (("0" &&& "1") <<< "2")
+ let e3= ("0" &&& "1" <<< "2")
+
+ let _ = if (e1 <> e2) then stderr.WriteLine "Control Passed" else stderr.WriteLine "Control Failed"
+ let _ = if (e1 = e3) then (stderr.WriteLine "Parsed to Right! Wrong!" ; reportFailure "parsing")
+ let _ = if (e2 = e3) then stderr.WriteLine "Parsed to Left - correct!"
- let _ = if (e1 <> e2) then stderr.WriteLine "Control Passed" else stderr.WriteLine "Control Failed"
- let _ = if (e1 = e3) then (stderr.WriteLine "Parsed to Right! Wrong!" ; reportFailure "parsing")
- let _ = if (e2 = e3) then stderr.WriteLine "Parsed to Left - correct!"
-end
//let _ = if (3 then do ignore(4)) = 3 then stderr.WriteLine "OK!" else (stderr.WriteLine "Wrong!" ; reportFailure "unlabelled test")
//let _ = let x = ref 1 in if (!x then do x := !x + 1) = 1 then stderr.WriteLine "OK!" else (stderr.WriteLine "Wrong!" ; reportFailure "unlabelled test")
@@ -2331,12 +2322,11 @@ do check "type test double" 1.0 (match box(1.0) with | :? System.Int32 -> 3.14 |
!* type syntax
*--------------------------------------------------------------------------- *)
-module TypeSyntax = begin
- let x1 = [Map.add 1 (Map.add 1 1 Map.empty) Map.empty]
- let x2 : Map<'a,'b> list = [Map.empty]
- let x3 : Map<'a,'b> list = []
+module TypeSyntax =
+ let x1 = [Map.add 1 (Map.add 1 1 Map.empty) Map.empty]
+ let x2 : Map<'a,'b> list = [Map.empty]
+ let x3 : Map<'a,'b> list = []
-end
module IEnumerableTests = begin
@@ -2855,52 +2845,101 @@ let nan2 = (let r = ref Double.NaN in (if sprintf "Hello" = "Hello" then !r else
do printf "checking floating point relational operators\n"
let _ = check "d3wiojd30a" ((Double.NaN > Double.NaN)) false
-let _ = check "d3wiojd30a" (if (Double.NaN > Double.NaN) then "a" else "b") "b"
-let _ = check "d3wiojd30b" ((Double.NaN >= Double.NaN)) false
-let _ = check "d3wiojd30b" (if (Double.NaN >= Double.NaN) then "a" else "b") "b"
-let _ = check "d3wiojd30c" ((Double.NaN < Double.NaN)) false
-let _ = check "d3wiojd30c" (if (Double.NaN < Double.NaN) then "a" else "b") "b"
-let _ = check "d3wiojd30d" ((Double.NaN <= Double.NaN)) false
-let _ = check "d3wiojd30d" (if (Double.NaN <= Double.NaN) then "a" else "b") "b"
-let _ = check "d3wiojd30e" ((Double.NaN = Double.NaN)) false
-let _ = check "d3wiojd30e" (if (Double.NaN = Double.NaN) then "a" else "b") "b"
-let _ = check "d3wiojd30q" ((Double.NaN <> Double.NaN)) true
-let _ = check "d3wiojd30w" ((Double.NaN > 1.0)) false
-let _ = check "d3wiojd30e" ((Double.NaN >= 1.0)) false
-let _ = check "d3wiojd30r" ((Double.NaN < 1.0)) false
-let _ = check "d3wiojd30t" ((Double.NaN <= 1.0)) false
-let _ = check "d3wiojd30y" ((Double.NaN = 1.0)) false
-let _ = check "d3wiojd30u" ((Double.NaN <> 1.0)) true
-let _ = check "d3wiojd30i" ((1.0 > Double.NaN)) false
-let _ = check "d3wiojd30o" ((1.0 >= Double.NaN)) false
-let _ = check "d3wiojd30p" ((1.0 < Double.NaN)) false
-let _ = check "d3wiojd30a" ((1.0 <= Double.NaN)) false
-let _ = check "d3wiojd30s" ((1.0 = Double.NaN)) false
-let _ = check "d3wiojd30d" ((1.0 <> Double.NaN)) true
-let _ = check "d3wiojd30a" ((nan1 > Double.NaN)) false
-let _ = check "d3wiojd30b" ((nan1 >= nan2)) false
-let _ = check "d3wiojd30c" ((nan1 < nan2)) false
-let _ = check "d3wiojd30d" ((nan1 <= nan2)) false
-let _ = check "d3wiojd30e" ((nan1 = nan2)) false
-let _ = check "d3wiojd30q" ((nan1 <> nan2)) true
-let _ = check "d3wiojd30w" ((nan1 > 1.0)) false
-let _ = check "d3wiojd30e" ((nan1 >= 1.0)) false
-let _ = check "d3wiojd30r" ((nan1 < 1.0)) false
-let _ = check "d3wiojd30t" ((nan1 <= 1.0)) false
-let _ = check "d3wiojd30y" ((nan1 = 1.0)) false
-let _ = check "d3wiojd30u" ((nan1 <> 1.0)) true
-let _ = check "d3wiojd30i" ((1.0 > nan2)) false
-let _ = check "d3wiojd30o" ((1.0 >= nan2)) false
-let _ = check "d3wiojd30p" ((1.0 < nan2)) false
-let _ = check "d3wiojd30a" ((1.0 <= nan2)) false
-let _ = check "d3wiojd30s" ((1.0 = nan2)) false
-let _ = check "d3wiojd30d" ((1.0 <> nan2)) true
-let _ = check "d3wiojd30f" ((Double.NegativeInfinity = Double.NegativeInfinity)) true
-let _ = check "d3wiojd30g" ((Double.NegativeInfinity < Double.PositiveInfinity)) true
-let _ = check "d3wiojd30h" ((Double.NegativeInfinity > Double.PositiveInfinity)) false
-let _ = check "d3wiojd30j" ((Double.NegativeInfinity <= Double.NegativeInfinity)) true
-
-module FloatingPointStructured = begin
+check "d3wiojd30a" (if (Double.NaN > Double.NaN) then "a" else "b") "b"
+check "d3wiojd30b" ((Double.NaN >= Double.NaN)) false
+check "d3wiojd30b" (if (Double.NaN >= Double.NaN) then "a" else "b") "b"
+check "d3wiojd30c" ((Double.NaN < Double.NaN)) false
+check "d3wiojd30c" (if (Double.NaN < Double.NaN) then "a" else "b") "b"
+check "d3wiojd30d" ((Double.NaN <= Double.NaN)) false
+check "d3wiojd30d" (if (Double.NaN <= Double.NaN) then "a" else "b") "b"
+check "d3wiojd30e" ((Double.NaN = Double.NaN)) false
+check "d3wiojd30e" (if (Double.NaN = Double.NaN) then "a" else "b") "b"
+check "d3wiojd30q" ((Double.NaN <> Double.NaN)) true
+check "d3wiojd30w" ((Double.NaN > 1.0)) false
+check "d3wiojd30e" ((Double.NaN >= 1.0)) false
+check "d3wiojd30r" ((Double.NaN < 1.0)) false
+check "d3wiojd30t" ((Double.NaN <= 1.0)) false
+check "d3wiojd30y" ((Double.NaN = 1.0)) false
+check "d3wiojd30u" ((Double.NaN <> 1.0)) true
+check "d3wiojd30i" ((1.0 > Double.NaN)) false
+check "d3wiojd30o" ((1.0 >= Double.NaN)) false
+check "d3wiojd30p" ((1.0 < Double.NaN)) false
+check "d3wiojd30a" ((1.0 <= Double.NaN)) false
+check "d3wiojd30s" ((1.0 = Double.NaN)) false
+check "d3wiojd30d" ((1.0 <> Double.NaN)) true
+check "d3wiojd30a" ((nan1 > Double.NaN)) false
+check "d3wiojd30b" ((nan1 >= nan2)) false
+check "d3wiojd30c" ((nan1 < nan2)) false
+check "d3wiojd30d" ((nan1 <= nan2)) false
+check "d3wiojd30e" ((nan1 = nan2)) false
+check "d3wiojd30q" ((nan1 <> nan2)) true
+check "d3wiojd30w" ((nan1 > 1.0)) false
+check "d3wiojd30e" ((nan1 >= 1.0)) false
+check "d3wiojd30r" ((nan1 < 1.0)) false
+check "d3wiojd30t" ((nan1 <= 1.0)) false
+check "d3wiojd30y" ((nan1 = 1.0)) false
+check "d3wiojd30u" ((nan1 <> 1.0)) true
+check "d3wiojd30i" ((1.0 > nan2)) false
+check "d3wiojd30o" ((1.0 >= nan2)) false
+check "d3wiojd30p" ((1.0 < nan2)) false
+check "d3wiojd30a" ((1.0 <= nan2)) false
+check "d3wiojd30s" ((1.0 = nan2)) false
+check "d3wiojd30d" ((1.0 <> nan2)) true
+check "d3wiojd30f" ((Double.NegativeInfinity = Double.NegativeInfinity)) true
+check "d3wiojd30g" ((Double.NegativeInfinity < Double.PositiveInfinity)) true
+check "d3wiojd30h" ((Double.NegativeInfinity > Double.PositiveInfinity)) false
+check "d3wiojd30j" ((Double.NegativeInfinity <= Double.NegativeInfinity)) true
+
+module SameTestsUsingNonStructuralComparison1 =
+ open NonStructuralComparison
+
+ check "d3wiojd30a" (if (Double.NaN > Double.NaN) then "a" else "b") "b"
+ check "d3wiojd30b" ((Double.NaN >= Double.NaN)) false
+ check "d3wiojd30b" (if (Double.NaN >= Double.NaN) then "a" else "b") "b"
+ check "d3wiojd30c" ((Double.NaN < Double.NaN)) false
+ check "d3wiojd30c" (if (Double.NaN < Double.NaN) then "a" else "b") "b"
+ check "d3wiojd30d" ((Double.NaN <= Double.NaN)) false
+ check "d3wiojd30d" (if (Double.NaN <= Double.NaN) then "a" else "b") "b"
+ check "d3wiojd30e" ((Double.NaN = Double.NaN)) false
+ check "d3wiojd30e" (if (Double.NaN = Double.NaN) then "a" else "b") "b"
+ check "d3wiojd30q" ((Double.NaN <> Double.NaN)) true
+ check "d3wiojd30w" ((Double.NaN > 1.0)) false
+ check "d3wiojd30e" ((Double.NaN >= 1.0)) false
+ check "d3wiojd30r" ((Double.NaN < 1.0)) false
+ check "d3wiojd30t" ((Double.NaN <= 1.0)) false
+ check "d3wiojd30y" ((Double.NaN = 1.0)) false
+ check "d3wiojd30u" ((Double.NaN <> 1.0)) true
+ check "d3wiojd30i" ((1.0 > Double.NaN)) false
+ check "d3wiojd30o" ((1.0 >= Double.NaN)) false
+ check "d3wiojd30p" ((1.0 < Double.NaN)) false
+ check "d3wiojd30a" ((1.0 <= Double.NaN)) false
+ check "d3wiojd30s" ((1.0 = Double.NaN)) false
+ check "d3wiojd30d" ((1.0 <> Double.NaN)) true
+ check "d3wiojd30a" ((nan1 > Double.NaN)) false
+ check "d3wiojd30b" ((nan1 >= nan2)) false
+ check "d3wiojd30c" ((nan1 < nan2)) false
+ check "d3wiojd30d" ((nan1 <= nan2)) false
+ check "d3wiojd30e" ((nan1 = nan2)) false
+ check "d3wiojd30q" ((nan1 <> nan2)) true
+ check "d3wiojd30w" ((nan1 > 1.0)) false
+ check "d3wiojd30e" ((nan1 >= 1.0)) false
+ check "d3wiojd30r" ((nan1 < 1.0)) false
+ check "d3wiojd30t" ((nan1 <= 1.0)) false
+ check "d3wiojd30y" ((nan1 = 1.0)) false
+ check "d3wiojd30u" ((nan1 <> 1.0)) true
+ check "d3wiojd30i" ((1.0 > nan2)) false
+ check "d3wiojd30o" ((1.0 >= nan2)) false
+ check "d3wiojd30p" ((1.0 < nan2)) false
+ check "d3wiojd30a" ((1.0 <= nan2)) false
+ check "d3wiojd30s" ((1.0 = nan2)) false
+ check "d3wiojd30d" ((1.0 <> nan2)) true
+ check "d3wiojd30f" ((Double.NegativeInfinity = Double.NegativeInfinity)) true
+ check "d3wiojd30g" ((Double.NegativeInfinity < Double.PositiveInfinity)) true
+ check "d3wiojd30h" ((Double.NegativeInfinity > Double.PositiveInfinity)) false
+ check "d3wiojd30j" ((Double.NegativeInfinity <= Double.NegativeInfinity)) true
+
+
+module FloatingPointStructured =
type www = W of float
do printf "checking floating point relational operators on structured data\n"
@@ -2930,9 +2969,9 @@ module FloatingPointStructured = begin
let _ = check "d3wiojd31c" ((W Double.NegativeInfinity < W Double.PositiveInfinity)) true
let _ = check "d3wiojd3xx" ((W Double.NegativeInfinity > W Double.PositiveInfinity)) false
let _ = check "d3wiojd31z" ((W Double.NegativeInfinity <= W Double.NegativeInfinity)) true
-end
-module FloatingPointStructuredPoly = begin
+
+module FloatingPointStructuredPoly =
type 'a www = W of 'a
do printf "checking floating point relational operators on polymorphic structured data\n"
@@ -2960,9 +2999,9 @@ module FloatingPointStructuredPoly = begin
let _ = check "d3wiojd32z" ((W Double.NegativeInfinity < W Double.PositiveInfinity)) true
let _ = check "d3wiojd32x" ((W Double.NegativeInfinity > W Double.PositiveInfinity)) false
let _ = check "d3wiojd32c" ((W Double.NegativeInfinity <= W Double.NegativeInfinity)) true
-end
-module MoreStructuralEqHashCompareNaNChecks = begin
+
+module MoreStructuralEqHashCompareNaNChecks =
let test398275413() =
let floats = [1.0; 0.0; System.Double.NaN; System.Double.NegativeInfinity; System.Double.PositiveInfinity; nan] in
for x in floats do
@@ -3199,7 +3238,7 @@ module MoreStructuralEqHashCompareNaNChecks = begin
let _ = test398275416()
-end
+
// This test tests basic behavior of IEquatable and IComparable augmentations
module GenericComparisonAndEquality = begin
@@ -4268,6 +4307,188 @@ do check "cenonoiwc" (int64 4UL) 4L
do check "cenonoiwc" (uint64 4UL) 4UL
do check "cenonoiwc" (match null with null -> 2 | _ -> 1) 2
+module SameTestsUsingNonStructuralComparison2 =
+ open NonStructuralComparison
+
+ do check "ffcenonoiwe1" (3 > 1) true
+ do check "ffcenonoiwe2" (3y > 1y) true
+ do check "ffcenonoiwe3" (3uy > 1uy) true
+ do check "ffcenonoiwe4" (3s > 1s) true
+ do check "ffcenonoiwe5" (3us > 1us) true
+ do check "ffcenonoiwe6" (3 > 1) true
+ do check "ffcenonoiwe7" (3u > 1u) true
+ do check "ffcenonoiwe8" (3L > 1L) true
+ do check "ffcenonoiwe9" (3UL > 1UL) true
+ do check "ffcenonoiwe9" (3.14 > 3.1) true
+ do check "ffcenonoiwe9" (3.14f > 3.1f) true
+ do check "ffcenonoiwe9" ("bbb" > "aaa") true
+ do check "ffcenonoiwe9" ("bbb" > "bbb") false
+ do check "ffcenonoiwe9" ("aaa" > "bbb") false
+ do check "ffcenonoiwe9" ('b' > 'a') true
+ do check "ffcenonoiwe9" ('a' > 'b') false
+ do check "ffcenonoiwe9" ('b' > 'b') false
+
+ do check "ffcenonoiwea" (3 >= 3) true
+ do check "ffcenonoiwes" (3y >= 3y) true
+ do check "ffcenonoiwed" (3uy >= 3uy) true
+ do check "ffcenonoiwef" (3s >= 3s) true
+ do check "ffcenonoiweg" (3us >= 3us) true
+ do check "ffcenonoiweh" (3 >= 3) true
+ do check "ffcenonoiwej" (3u >= 3u) true
+ do check "ffcenonoiwek" (3L >= 3L) true
+ do check "ffcenonoiwel" (3UL >= 3UL) true
+ do check "ffcenonoiwem" (3.14 >= 3.1) true
+ do check "ffcenonoiwen" (3.14f >= 3.1f) true
+ do check "ffcenonoiwen" (3.14M >= 3.1M) true
+ do check "ffcenonoiwe91r" ("bbb" >= "aaa") true
+ do check "ffcenonoiwe92r" ("bbb" >= "bbb") true
+ do check "ffcenonoiwe93r" ("aaa" >= "bbb") false
+ do check "ffcenonoiwe94r" ('b' >= 'a') true
+ do check "ffcenonoiwe95r" ('a' >= 'b') false
+ do check "ffcenonoiwe96r" ('b' >= 'b') true
+
+
+ do check "ffcenonoiwd1" (3 < 1) false
+ do check "ffcenonoiwd2" (3y < 1y) false
+ do check "ffcenonoiwd3" (3uy < 1uy) false
+ do check "ffcenonoiwd4" (3s < 1s) false
+ do check "ffcenonoiwd5" (3us < 1us) false
+ do check "ffcenonoiwd6" (3 < 1) false
+ do check "ffcenonoiwd7" (3u < 1u) false
+ do check "ffcenonoiwd8" (3L < 1L) false
+ do check "ffcenonoiwd9" (3UL < 1UL) false
+ do check "ffcenonoiwd9" (3.14 < 1.0) false
+ do check "ffcenonoiwd9" (3.14f < 1.0f) false
+ do check "ffcenonoiwd9" (3.14M < 1.0M) false
+ do check "ffcenonoiwe91a" ("bbb" < "aaa") false
+ do check "ffcenonoiwe92a" ("bbb" < "bbb") false
+ do check "ffcenonoiwe93a" ("aaa" < "bbb") true
+ do check "ffcenonoiwe94a" ('b' < 'a') false
+ do check "ffcenonoiwe95a" ('a' < 'b') true
+ do check "ffcenonoiwe96a" ('b' < 'b') false
+
+
+ do check "ffcenonoiwdq" (3 <= 1) false
+ do check "ffcenonoiwdw" (3y <= 1y) false
+ do check "ffcenonoiwde" (3uy <= 1uy) false
+ do check "ffcenonoiwdr" (3s <= 1s) false
+ do check "ffcenonoiwdt" (3us <= 1us) false
+ do check "ffcenonoiwdy" (3 <= 1) false
+ do check "ffcenonoiwdu" (3u <= 1u) false
+ do check "ffcenonoiwdi" (3L <= 1L) false
+ do check "ffcenonoiwdo" (3UL <= 1UL) false
+ do check "ffcenonoiwdg" (3.14 <= 1.0) false
+ do check "ffcenonoiwdt" (3.14f <= 1.0f) false
+ do check "ffcenonoiwdt" (3.14M <= 1.0M) false
+ do check "ffcenonoiwe91q" ("bbb" <= "aaa") false
+ do check "ffcenonoiwe92q" ("bbb" <= "bbb") true
+ do check "ffcenonoiwe93q" ("aaa" <= "bbb") true
+ do check "ffcenonoiwe94q" ('b' <= 'a') false
+ do check "ffcenonoiwe95q" ('a' <= 'b') true
+ do check "ffcenonoiwe96q" ('b' <= 'b') true
+
+
+ do check "ffcenonoiwda" (3 <= 3) true
+ do check "ffcenonoiwds" (3y <= 3y) true
+ do check "ffcenonoiwdd" (3uy <= 3uy) true
+ do check "ffcenonoiwdf" (3s <= 3s) true
+ do check "ffcenonoiwdg" (3us <= 3us) true
+ do check "ffcenonoiwdh" (3 <= 3) true
+ do check "ffcenonoiwdj" (3u <= 3u) true
+ do check "ffcenonoiwdk" (3L <= 3L) true
+ do check "ffcenonoiwdl" (3UL <= 3UL) true
+ do check "ffcenonoiwdo" (3.14 <= 3.14) true
+ do check "ffcenonoiwdp" (3.14f <= 3.14f) true
+ do check "ffcenonoiwdp" (3.14M <= 3.14M) true
+
+
+module NonStructuralComparisonOverDateTime =
+ open NonStructuralComparison
+ let now = System.DateTime.Now
+ let tom = now.AddDays 1.0
+ do check "ffcenonoiwe90" (now = tom) false
+ do check "ffcenonoiwe9q" (now <> tom) true
+ do check "ffcenonoiwe91" (now < tom) true
+ do check "ffcenonoiwe92" (now <= now) true
+ do check "ffcenonoiwe93" (now <= tom) true
+ do check "ffcenonoiwe94" (tom > now) true
+ do check "ffcenonoiwe95" (now >= now) true
+ do check "ffcenonoiwe96" (tom >= now) true
+ do check "ffcenonoiwe97" (compare now now) 0
+ do check "ffcenonoiwe98" (compare now tom) -1
+ do check "ffcenonoiwe99" (compare tom now) 1
+ do check "ffcenonoiwe9a" (max tom tom) tom
+ do check "ffcenonoiwe9b" (max tom now) tom
+ do check "ffcenonoiwe9c" (max now tom) tom
+ do check "ffcenonoiwe9d" (min tom tom) tom
+ do check "ffcenonoiwe9e" (min tom now) now
+ do check "ffcenonoiwe9f" (min now tom) now
+
+ do check "ffcenonoiwe97a1" (ComparisonIdentity.NonStructural.Compare (1, 1)) 0
+ do check "ffcenonoiwe98b2" (ComparisonIdentity.NonStructural.Compare (0, 1)) -1
+ do check "ffcenonoiwe99c3" (ComparisonIdentity.NonStructural.Compare (1, 0)) 1
+
+ do check "ffcenonoiwe97a4" (ComparisonIdentity.NonStructural.Compare (now, now)) 0
+ do check "ffcenonoiwe98b5" (ComparisonIdentity.NonStructural.Compare (now, tom)) -1
+ do check "ffcenonoiwe99c6" (ComparisonIdentity.NonStructural.Compare (tom, now)) 1
+
+ do check "ffcenonoiwe97a7" (HashIdentity.NonStructural.Equals (now, now)) true
+ do check "ffcenonoiwe98b8" (HashIdentity.NonStructural.Equals (now, tom)) false
+ do check "ffcenonoiwe99c9" (HashIdentity.NonStructural.Equals (tom, now)) false
+
+ do check "ffcenonoiwe97a7" (HashIdentity.NonStructural.GetHashCode now) (hash now)
+ do check "ffcenonoiwe97a7" (HashIdentity.NonStructural.GetHashCode tom) (hash tom)
+ do check "ffcenonoiwe97a7" (HashIdentity.NonStructural.GetHashCode 11) (hash 11)
+ do check "ffcenonoiwe97a7" (HashIdentity.NonStructural.GetHashCode 11L) (hash 11L)
+ do check "ffcenonoiwe97a7" (HashIdentity.NonStructural.GetHashCode 11UL) (hash 11UL)
+
+ do check "ffcenonoiwe97aa" (HashIdentity.NonStructural.Equals (1, 1)) true
+ do check "ffcenonoiwe98bb" (HashIdentity.NonStructural.Equals (1, 0)) false
+ do check "ffcenonoiwe99cc" (HashIdentity.NonStructural.Equals (0, 1)) false
+
+
+module NonStructuralComparisonOverTimeSpan =
+ open NonStructuralComparison
+ let now = System.TimeSpan.Zero
+ let tom = System.TimeSpan.FromDays 1.0
+ do check "tscenonoiwe90" (now = tom) false
+ do check "tscenonoiwe9q" (now <> tom) true
+ do check "tscenonoiwe91" (now < tom) true
+ do check "tscenonoiwe92" (now <= now) true
+ do check "tscenonoiwe93" (now <= tom) true
+ do check "tscenonoiwe94" (tom > now) true
+ do check "tscenonoiwe95" (now >= now) true
+ do check "tscenonoiwe96" (tom >= now) true
+ do check "tscenonoiwe97" (compare now now) 0
+ do check "tscenonoiwe98" (compare now tom) -1
+ do check "tscenonoiwe99" (compare tom now) 1
+ do check "tscenonoiwe9a" (max tom tom) tom
+ do check "tscenonoiwe9b" (max tom now) tom
+ do check "tscenonoiwe9c" (max now tom) tom
+ do check "tscenonoiwe9d" (min tom tom) tom
+ do check "tscenonoiwe9e" (min tom now) now
+ do check "tscenonoiwe9f" (min now tom) now
+
+
+// Check you can use the operators without opening the module by naming them
+module NonStructuralComparisonOverTimeSpanDirect =
+ let now = System.TimeSpan.Zero
+ let tom = System.TimeSpan.FromDays 1.0
+ do check "tscenonoiwe90" (NonStructuralComparison.(=) now tom) false
+ do check "tscenonoiwe9q" (NonStructuralComparison.(<>) now tom) true
+ do check "tscenonoiwe91" (NonStructuralComparison.(<) now tom) true
+ do check "tscenonoiwe92" (NonStructuralComparison.(<=) now now) true
+ do check "tscenonoiwe94" (NonStructuralComparison.(>) tom now) true
+ do check "tscenonoiwe95" (NonStructuralComparison.(>=) now now) true
+ do check "tscenonoiwe97" (NonStructuralComparison.compare now now) 0
+ do check "tscenonoiwe9a" (NonStructuralComparison.max tom now) tom
+ do check "tscenonoiwe9e" (NonStructuralComparison.min tom now) now
+
+ do check "ffcenonoiwe97a7" (NonStructuralComparison.hash now) (Operators.hash now)
+ do check "ffcenonoiwe97a7" (NonStructuralComparison.hash tom) (Operators.hash tom)
+ do check "ffcenonoiwe97a7" (NonStructuralComparison.hash 11) (Operators.hash 11)
+ do check "ffcenonoiwe97a7" (NonStructuralComparison.hash 11L) (Operators.hash 11L)
+ do check "ffcenonoiwe97a7" (NonStructuralComparison.hash 11UL) (Operators.hash 11UL)
(*---------------------------------------------------------------------------
!* Bug 1029: Support conversion functions named after C# type names? e.g. uint for uint32
diff --git a/tests/fsharp/core/queriesLeafExpressionConvert/test.fsx b/tests/fsharp/core/queriesLeafExpressionConvert/test.fsx
index 5947fd02c1c..6b04b318f65 100644
--- a/tests/fsharp/core/queriesLeafExpressionConvert/test.fsx
+++ b/tests/fsharp/core/queriesLeafExpressionConvert/test.fsx
@@ -86,6 +86,33 @@ module LeafExpressionEvaluationTests =
let _ = 1
checkEval "2ver9ewve" (<@ () @>) ()
+ check "2ver9ewvr1" (Eval <@ (fun x -> NonStructuralComparison.(>) x 1) @> 3) true
+ check "2ver9ewvr1" (Eval <@ (fun x -> NonStructuralComparison.(>) x 4) @> 3) false
+ check "2ver9ewvr1" (Eval <@ (fun x -> NonStructuralComparison.(>) x 3) @> 3) false
+
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<) x 1) @> 3) false
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<) x 3) @> 3) false
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<) x 4) @> 3) true
+
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(>=) x 1) @> 3) true
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(>=) x 3) @> 3) true
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(>=) x 4) @> 3) false
+
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<=) x 1) @> 3) false
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<=) x 3) @> 3) true
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<=) x 4) @> 3) true
+
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(=) x 3) @> 3) true
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(=) x 4) @> 3) false
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(=) x 1) @> 3) false
+
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<>) x 4) @> 3) true
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<>) x 3) @> 3) false
+ check "2ver9ewvr2" (Eval <@ (fun x -> NonStructuralComparison.(<>) x 1) @> 3) true
+
+ check "2ver9ewvr" (Eval <@ (fun x -> x + 1) @> (3)) 4
+ check "2ver9ewvr" (Eval <@ (fun x -> x + 1) @> (3)) 4
+ check "2ver9ewvr" (Eval <@ (fun x -> x + 1) @> (3)) 4
check "2ver9ewvr" (Eval <@ (fun x -> x + 1) @> (3)) 4
check "2ver9ewvt" (Eval <@ (fun (x,y) -> x + 1) @> (3,4)) 4
check "2ver9ewvy" (Eval <@ (fun (x1,x2,x3) -> x1 + x2 + x3) @> (3,4,5)) (3+4+5)