diff --git a/src/compiler/WebSharper.Compiler.CSharp/CodeReader.fs b/src/compiler/WebSharper.Compiler.CSharp/CodeReader.fs index 8c4703de9..434b8d2a1 100644 --- a/src/compiler/WebSharper.Compiler.CSharp/CodeReader.fs +++ b/src/compiler/WebSharper.Compiler.CSharp/CodeReader.fs @@ -1268,17 +1268,31 @@ type RoslynTransformer(env: Environment) = let leftType = env.SemanticModel.GetTypeInfo(x.Left.Node).ConvertedType |> sr.ReadType Coalesce(left, leftType, right) | _ -> - let symbol = env.SemanticModel.GetSymbolInfo(x.Node).Symbol :?> IMethodSymbol - let typ, meth = getTypeAndMethod symbol - if List.isEmpty meth.Generics then - // add fake generics type information to resolve nullable operations - let leftType = env.SemanticModel.GetTypeInfo(x.Left.Node).Type |> sr.ReadType - let rightType = env.SemanticModel.GetTypeInfo(x.Right.Node).Type |> sr.ReadType - let meth = - { meth with Generics = [leftType; rightType] } - Call(None, typ, meth, [left; right]) - else - Call(None, typ, meth, [left; right]) + let leftTypeSymbol = env.SemanticModel.GetTypeInfo(x.Left.Node).Type + let rightTypeSymbol = env.SemanticModel.GetTypeInfo(x.Right.Node).Type + let tupleOp = + if leftTypeSymbol.IsTupleType && rightTypeSymbol.IsTupleType then + match x.Kind with + | BinaryExpressionKind.EqualsExpression -> + Some (Macros.UncheckedEquals left right) + | BinaryExpressionKind.NotEqualsExpression -> + Some (Unary(UnaryOperator.``!``, Macros.UncheckedEquals left right)) + | _ -> None + else None + match tupleOp with + | Some res -> res + | _ -> + let symbol = env.SemanticModel.GetSymbolInfo(x.Node).Symbol :?> IMethodSymbol + let typ, meth = getTypeAndMethod symbol + if List.isEmpty meth.Generics then + // add fake generics type information to resolve nullable operations + let leftType = leftTypeSymbol |> sr.ReadType + let rightType = rightTypeSymbol |> sr.ReadType + let meth = + { meth with Generics = [leftType; rightType] } + Call(None, typ, meth, [left; right]) + else + Call(None, typ, meth, [left; right]) |> withExprSourcePos x.Node member this.TransformConditionalExpression (x: ConditionalExpressionData) : Expression = diff --git a/src/compiler/WebSharper.Core/Macros.fs b/src/compiler/WebSharper.Core/Macros.fs index 733d1c867..8142fa50d 100644 --- a/src/compiler/WebSharper.Core/Macros.fs +++ b/src/compiler/WebSharper.Core/Macros.fs @@ -165,6 +165,9 @@ let opUncheckedTy, equalsMeth, compareMeth, hashMeth = Reflection.ReadMethod hmi | _ -> failwith "Expecting a Call pattern" +let UncheckedEquals x y = + Call (None, NonGeneric opUncheckedTy, NonGeneric equalsMeth, [x; y]) + let makeComparison cmp x y = let eq x y = Call (None, NonGeneric opUncheckedTy, NonGeneric equalsMeth, [x; y]) let c b i = Binary (Call(None, NonGeneric opUncheckedTy, NonGeneric compareMeth, [x; y]), b, Value(Int i)) diff --git a/src/compiler/WebSharper.Core/Macros.fsi b/src/compiler/WebSharper.Core/Macros.fsi index aa4ef48c2..13be130f3 100644 --- a/src/compiler/WebSharper.Core/Macros.fsi +++ b/src/compiler/WebSharper.Core/Macros.fsi @@ -158,4 +158,6 @@ type Tuple = [] type TupleExtensions = new : unit -> TupleExtensions - inherit Macro \ No newline at end of file + inherit Macro + +val UncheckedEquals : AST.Expression -> AST.Expression -> AST.Expression \ No newline at end of file