sealed class ThisInitializer : Statement
{
readonly HoistedThis hoisted_this;
+ readonly AnonymousMethodStorey parent;
- public ThisInitializer (HoistedThis hoisted_this)
+ public ThisInitializer (HoistedThis hoisted_this, AnonymousMethodStorey parent)
{
this.hoisted_this = hoisted_this;
+ this.parent = parent;
}
protected override void DoEmit (EmitContext ec)
{
- hoisted_this.EmitAssign (ec, new CompilerGeneratedThis (ec.CurrentType, loc), false, false);
+ Expression source;
+
+ if (parent == null)
+ source = new CompilerGeneratedThis (ec.CurrentType, loc);
+ else {
+ source = new FieldExpr (parent.HoistedThis.Field, Location.Null) {
+ InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location.Null)
+ };
+ }
+
+ hoisted_this.EmitAssign (ec, source, false, false);
}
protected override void CloneTo (CloneContext clonectx, Statement target)
public Expression Instance;
bool initialize_hoisted_this;
+ AnonymousMethodStorey hoisted_this_parent;
public AnonymousMethodStorey (ExplicitBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind)
: base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation),
ID = parent.Module.CounterAnonymousContainers++;
}
- public void AddCapturedThisField (EmitContext ec)
+ public void AddCapturedThisField (EmitContext ec, AnonymousMethodStorey parent)
{
TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location);
Field f = AddCompilerGeneratedField ("$this", type_expr);
hoisted_this = new HoistedThis (this, f);
initialize_hoisted_this = true;
+ hoisted_this_parent = parent;
}
public Field AddCapturedVariable (string name, TypeSpec type)
// referenced indirectly
//
if (initialize_hoisted_this) {
- rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this));
+ rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this, hoisted_this_parent));
}
//
return null;
}
- protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters)
+ protected bool VerifyExplicitParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection parameters)
{
- if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode))
+ if (VerifyParameterCompatibility (ec, tic, delegate_type, parameters, ec.IsInProbingMode))
return true;
if (!ec.IsInProbingMode)
return false;
}
- protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors)
+ protected bool VerifyParameterCompatibility (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors)
{
if (Parameters.Count != invoke_pd.Count) {
if (ignore_errors)
continue;
TypeSpec type = invoke_pd.Types [i];
+
+ if (tic != null)
+ type = tic.InflateGenericArgument (ec, type);
- //
- // Assumes that generic mvar parameters are always inflated
- //
- if (ImplicitDelegateCreation.ContainsMethodTypeParameter (type))
- continue;
-
- if (!TypeSpecComparer.IsEqual (invoke_pd.Types [i], Parameters.Types [i])) {
+ if (!TypeSpecComparer.IsEqual (type, Parameters.Types [i])) {
if (ignore_errors)
return false;
//
// Infers type arguments based on explicit arguments
//
- public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type)
+ public bool ExplicitTypeInference (TypeInferenceContext type_inference, TypeSpec delegate_type)
{
if (!HasExplicitParameters)
return false;
return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types);
}
- if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) {
+ if (!VerifyExplicitParameters (ec, tic, delegate_type, delegate_parameters)) {
return null;
}
// enough. No hoisted variables only 'this' and don't need to
// propagate this to value type state machine.
//
- StateMachine sm_parent = null;
+ StateMachine sm_parent;
var pb = src_block.ParametersBlock;
do {
sm_parent = pb.StateMachine;
} else if (sm_parent.Kind == MemberKind.Struct) {
//
// Special case where parent class is used to emit instance method
- // because currect storey is of value type (async host). We cannot
+ // because currect storey is of value type (async host) and we cannot
// use ldftn on non-boxed instances either to share mutated state
//
parent = sm_parent.Parent.PartialContainer;
+ } else if (sm is IteratorStorey) {
+ //
+ // For iterators we can host everything in one class
+ //
+ parent = storey = sm;
}
}
-
- //
- // For iterators we can host everything in one class
- //
- if (sm is IteratorStorey)
- parent = storey = sm;
}
modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
// Special case for value type storey where this is not lifted but
// droped off to parent class
//
- for (var b = Block.Parent; b != null; b = b.Parent) {
- if (b.ParametersBlock.StateMachine != null) {
- ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec);
- break;
- }
- }
+ if (ec.CurrentAnonymousMethod != null && ec.AsyncTaskStorey != null)
+ ec.Emit (OpCodes.Ldfld, ec.AsyncTaskStorey.HoistedThis.Field.Spec);
}
var delegate_method = method.Spec;
Method tostring = new Method (this, new TypeExpression (Compiler.BuiltinTypes.String, loc),
Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc),
- Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
+ ParametersCompiled.EmptyReadOnlyParameters, null);
ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc);
Method hashcode = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Int, loc),
Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN,
new MemberName ("GetHashCode", loc),
- Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
+ ParametersCompiled.EmptyReadOnlyParameters, null);
//
// Modified FNV with good avalanche behavior and uniform