public override void PrepareEmit ()
{
- if (!Parameters.IsEmpty) {
- parameters.ResolveDefaultValues (this);
- }
+ if ((caching_flags & Flags.CloseTypeCreated) != 0)
+ return;
InvokeBuilder.PrepareEmit ();
if (BeginInvokeBuilder != null) {
//
public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler
{
+ bool conditional_access_receiver;
protected MethodSpec constructor_method;
protected MethodGroupExpr method_group;
var invoke_method = Delegate.GetInvokeMethod (type);
+ if (!ec.HasSet (ResolveContext.Options.ConditionalAccessReceiver)) {
+ if (method_group.HasConditionalAccess ()) {
+ conditional_access_receiver = true;
+ ec.Set (ResolveContext.Options.ConditionalAccessReceiver);
+ }
+ }
+
Arguments arguments = CreateDelegateMethodArguments (ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc);
method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate);
+
+ if (conditional_access_receiver)
+ ec.With (ResolveContext.Options.ConditionalAccessReceiver, false);
+
if (method_group == null)
return null;
public override void Emit (EmitContext ec)
{
- InstanceEmitter ie;
+ if (conditional_access_receiver)
+ ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
+
if (method_group.InstanceExpression == null) {
- ie = new InstanceEmitter ();
ec.EmitNull ();
} else {
- ie = new InstanceEmitter (method_group.InstanceExpression, false);
- ie.NullShortCircuit = method_group.NullShortCircuit;
- ie.Emit (ec);
+ var ie = new InstanceEmitter (method_group.InstanceExpression, false);
+ ie.Emit (ec, method_group.ConditionalAccess);
}
var delegate_method = method_group.BestCandidate;
ec.Emit (OpCodes.Newobj, constructor_method);
- if (method_group.NullShortCircuit) {
- ie.EmitResultLift (ec, type, false);
- }
+ if (conditional_access_receiver)
+ ec.CloseConditionalAccess (null);
}
- public override void FlowAnalysis (FlowAnalysisContext fc) {
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
base.FlowAnalysis (fc);
method_group.FlowAnalysis (fc);
+
+ if (conditional_access_receiver)
+ fc.ConditionalAccessEnd ();
}
void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type)
var invoke = Delegate.GetInvokeMethod (target_type);
Arguments arguments = CreateDelegateMethodArguments (ec, invoke.Parameters, invoke.Parameters.Types, mg.Location);
- return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null;
+ mg = mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly);
+ return mg != null && Delegate.IsTypeCovariant (ec, mg.BestCandidateReturnType, invoke.ReturnType);
}
#region IErrorHandler Members
class DelegateInvocation : ExpressionStatement
{
readonly Expression InstanceExpr;
+ readonly bool conditionalAccessReceiver;
Arguments arguments;
MethodSpec method;
- public DelegateInvocation (Expression instance_expr, Arguments args, Location loc)
+ public DelegateInvocation (Expression instance_expr, Arguments args, bool conditionalAccessReceiver, Location loc)
{
this.InstanceExpr = instance_expr;
this.arguments = args;
+ this.conditionalAccessReceiver = conditionalAccessReceiver;
this.loc = loc;
}
return null;
type = method.ReturnType;
+ if (conditionalAccessReceiver)
+ type = LiftMemberType (ec, type);
+
eclass = ExprClass.Value;
return this;
}
public override void Emit (EmitContext ec)
{
+ if (conditionalAccessReceiver) {
+ ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
+ }
+
//
// Invocation on delegates call the virtual Invoke member
// so we are always `instance' calls
var call = new CallEmitter ();
call.InstanceExpression = InstanceExpr;
call.Emit (ec, method, arguments, loc);
+
+ if (conditionalAccessReceiver)
+ ec.CloseConditionalAccess (type.IsNullableType && type != method.ReturnType ? type : null);
}
public override void EmitStatement (EmitContext ec)
{
+ if (conditionalAccessReceiver) {
+ ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ()) {
+ Statement = true
+ };
+ }
+
var call = new CallEmitter ();
call.InstanceExpression = InstanceExpr;
call.EmitStatement (ec, method, arguments, loc);
+
+ if (conditionalAccessReceiver)
+ ec.CloseConditionalAccess (null);
}
public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)