protected override BoundExpression GenerateCall(SyntheticBoundNodeFactory f, BoundExpression receiver, ImmutableArray <BoundExpression> arguments, ImmutableArray <RefKind> refKinds, DiagnosticBag diagnostics) { // For user-defined operators, the normal shim call approach works // fine. However, we also want to permit shim calls into types // with builtin operators, for which we need to do an actual // lookup as to which operator we're defining, and a quick // jump into part of the operator overload resolution code to see // if we're actually in one of those types. // // This may be incomplete, but is probably(??) sound. // TODO(@MattWindsor91): consider refkinds? if (ImplementingMethod.OriginalDefinition is SourceUserDefinedOperatorSymbol op) { Debug.Assert(receiver.Kind == BoundKind.TypeExpression, "receiver of an operator should always be a type"); var rectype = (BoundTypeExpression)receiver; var opdecl = op.GetSyntax(); Debug.Assert(opdecl != null, "should have operator syntax here"); var opsyn = opdecl.OperatorToken; var opkind = opsyn.Kind(); var binder = DeclaringCompilation.GetBinder(ImplementingMethod.GetNonNullSyntaxNode()).WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.InShim, this); var ovr = new OverloadResolution(binder); var ignore = new HashSet <DiagnosticInfo>(); if (arguments.Length == 1) { (var usuccess, var ukind) = TryGetUnaryOperatorKind(opsyn.Kind()); if (usuccess) { var result = UnaryOperatorOverloadResolutionResult.GetInstance(); ovr.UnaryOperatorOverloadResolution(ukind, arguments[0], result, ref ignore); if (result.SingleValid()) { var bsig = result.Best.Signature; if (bsig.Method == null) { return(f.Unary(bsig.Kind, bsig.ReturnType, arguments[0])); } } } } else if (arguments.Length == 2) { (var bsuccess, var bkind) = TryGetBinaryOperatorKind(opsyn.Kind()); if (bsuccess) { var result = BinaryOperatorOverloadResolutionResult.GetInstance(); ovr.BinaryOperatorOverloadResolution(bkind, arguments[0], arguments[1], result, ref ignore); if (result.SingleValid()) { var bsig = result.Best.Signature; if (bsig.Method == null) { return(f.Binary(bsig.Kind, bsig.ReturnType, arguments[0], arguments[1])); } } } } } return(base.GenerateCall(f, receiver, arguments, refKinds, diagnostics)); }