| File: Binder\Semantics\Operators\BinaryOperatorSignature.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Symbols; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { internal struct BinaryOperatorSignature : IEquatable<BinaryOperatorSignature> { public static BinaryOperatorSignature Error = default(BinaryOperatorSignature); public readonly TypeSymbol LeftType; public readonly TypeSymbol RightType; public readonly TypeSymbol ReturnType; public readonly MethodSymbol Method; public readonly TypeSymbol ConstrainedToTypeOpt; public readonly BinaryOperatorKind Kind; /// <summary> /// To duplicate native compiler behavior for some scenarios we force a priority among /// operators. If two operators are both applicable and both have a non-null Priority, /// the one with the numerically lower Priority value is preferred. /// </summary> public int? Priority; public BinaryOperatorSignature(BinaryOperatorKind kind, TypeSymbol leftType, TypeSymbol rightType, TypeSymbol returnType) { this.Kind = kind; this.LeftType = leftType; this.RightType = rightType; this.ReturnType = returnType; this.Method = null; this.ConstrainedToTypeOpt = null; this.Priority = null; } public BinaryOperatorSignature(BinaryOperatorKind kind, TypeSymbol leftType, TypeSymbol rightType, TypeSymbol returnType, MethodSymbol method, TypeSymbol constrainedToTypeOpt) { this.Kind = kind; this.LeftType = leftType; this.RightType = rightType; this.ReturnType = returnType; this.Method = method; this.ConstrainedToTypeOpt = constrainedToTypeOpt; this.Priority = null; } public override string ToString() { return $"kind: {this.Kind} leftType: {this.LeftType} leftRefKind: {this.LeftRefKind} rightType: {this.RightType} rightRefKind: {this.RightRefKind} return: {this.ReturnType}"; } public bool Equals(BinaryOperatorSignature other) { return this.Kind == other.Kind && TypeSymbol.Equals(this.LeftType, other.LeftType, TypeCompareKind.ConsiderEverything2) && TypeSymbol.Equals(this.RightType, other.RightType, TypeCompareKind.ConsiderEverything2) && TypeSymbol.Equals(this.ReturnType, other.ReturnType, TypeCompareKind.ConsiderEverything2) && Symbol.Equals(this.Method, other.Method, TypeCompareKind.ConsiderEverything); } public static bool operator ==(BinaryOperatorSignature x, BinaryOperatorSignature y) { return x.Equals(y); } public static bool operator !=(BinaryOperatorSignature x, BinaryOperatorSignature y) { return !x.Equals(y); } public override bool Equals(object obj) { return obj is BinaryOperatorSignature && Equals((BinaryOperatorSignature)obj); } public override int GetHashCode() { return Hash.Combine(ReturnType, Hash.Combine(LeftType, Hash.Combine(RightType, Hash.Combine(Method, (int)Kind)))); } public RefKind LeftRefKind { get { if ((object)Method != null && Method.IsStatic) { Debug.Assert(Method.ParameterCount == 2); if (!Method.ParameterRefKinds.IsDefaultOrEmpty) { Debug.Assert(Method.ParameterRefKinds.Length == 2); return Method.ParameterRefKinds[0]; } } return RefKind.None; } } public RefKind RightRefKind { get { if ((object)Method != null) { int rightIndex = Method.IsStatic ? 1 : 0; Debug.Assert(Method.ParameterCount == rightIndex + 1); if (!Method.ParameterRefKinds.IsDefaultOrEmpty) { Debug.Assert(Method.ParameterRefKinds.Length == rightIndex + 1); return Method.ParameterRefKinds[rightIndex]; } } return RefKind.None; } } } }