internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            var concept    = ImplementingMethod.ContainingType;
            var conceptLoc = concept.Locations.IsEmpty ? Location.None : concept.Locations[0];

            // TODO: wrong location?

            Debug.Assert(concept.IsConcept, "Tried to synthesise default struct implementation on a non-concept interface");

            var instance    = ContainingType;
            var instanceLoc = instance.Locations.IsEmpty ? Location.None : instance.Locations[0];

            // TODO: wrong location?

            Debug.Assert(instance.IsInstance, "Tried to synthesise default struct implementation for a non-instance");

            SyntheticBoundNodeFactory F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);

            F.CurrentMethod = OriginalDefinition;

            try
            {
                // Now try to find the default struct using the instance's scope...
                var binder = new BinderFactory(compilationState.Compilation, instance.GetNonNullSyntaxNode().SyntaxTree).GetBinder(instance.GetNonNullSyntaxNode());

                var ignore = new HashSet <DiagnosticInfo>();
                var defs   = concept.GetDefaultStruct(binder, false, ref ignore);

                if (defs == null)
                {
                    diagnostics.Add(ErrorCode.ERR_ConceptMethodNotImplementedAndNoDefault, instanceLoc, instance.Name, concept.Name, ImplementingMethod.ToDisplayString());
                    F.CloseMethod(F.ThrowNull());
                    return;
                }

                // Suppose the target concept is Foo<A, B>.
                // Then, the default must take type parameters <A, B, FooAB>,
                // where FooAB : Foo<A, B>.  Thus, the arity is one higher than
                // the concept.
                if (defs.Arity != concept.Arity + 1)
                {
                    // Don't use the default struct's location: it is an
                    // implementation detail and may not actually exist.
                    diagnostics.Add(ErrorCode.ERR_DefaultStructBadArity, conceptLoc, concept.Name, defs.Arity, concept.Arity + 1);
                    F.CloseMethod(F.ThrowNull());
                    return;
                }

                // Due to above, arity must be at least 1.

                var witnessPar = defs.TypeParameters[defs.Arity - 1];
                if (!witnessPar.IsConceptWitness)
                {
                    diagnostics.Add(ErrorCode.ERR_DefaultStructNoWitnessParam, conceptLoc, concept.Name);
                    F.CloseMethod(F.ThrowNull());
                    return;
                }

                var newTypeArguments = GenerateDefaultTypeArguments();
                Debug.Assert(newTypeArguments.Length == concept.TypeArguments.Length + 1,
                             "Conversion from concept type parameters to default struct lost or gained some entries.");

                // Now make the receiver for the call.  As usual, it's a default().
                var recvType = new ConstructedNamedTypeSymbol(defs, newTypeArguments);
                var receiver = F.Default(recvType);

                var arguments = GenerateInnerCallArguments(F);
                Debug.Assert(arguments.Length == ImplementingMethod.Parameters.Length,
                             "Conversion from parameters to arguments lost or gained some entries.");

                var call = F.MakeInvocationExpression(BinderFlags.None, F.Syntax, receiver, ImplementingMethod.Name, arguments, diagnostics, ImplementingMethod.TypeArguments);
                if (call.HasErrors)
                {
                    F.CloseMethod(F.ThrowNull());
                    return;
                }

                // If whichever call we end up making returns void, then we
                // can't just return its result; instead, we have to do the
                // call on its own _then_ return.
                BoundBlock block;
                if (call.Type.SpecialType == SpecialType.System_Void)
                {
                    block = F.Block(F.ExpressionStatement(call), F.Return());
                }
                else
                {
                    block = F.Block(F.Return(call));
                }

                F.CloseMethod(block);
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
            {
                diagnostics.Add(ex.Diagnostic);
                F.CloseMethod(F.ThrowNull());
            }
        }
        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));
        }