hoisted_locals.Add (hoisted);
}
- if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit && !(hoisted.Storey is StateMachine))
+ if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit && !(hoisted.Storey is StateMachine) && hoisted.Storey != null)
hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
}
return Parameters;
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext rc)
{
- if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
- ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
+ if (rc.HasSet (ResolveContext.Options.ConstantScope)) {
+ rc.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
return null;
}
//
- // Set class type, set type
+ // Update top-level block generated duting parsing with actual top-level block
//
+ if (rc.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer) && rc.CurrentMemberDefinition.Parent.PartialContainer.PrimaryConstructorParameters != null) {
+ var tb = rc.ConstructorBlock.ParametersBlock.TopBlock;
+ if (Block.TopBlock != tb) {
+ Block b = Block;
+ while (b.Parent != Block.TopBlock && b != Block.TopBlock)
+ b = b.Parent;
+
+ b.Parent = tb;
+ tb.IncludeBlock (Block, Block.TopBlock);
+ b.ParametersBlock.TopBlock = tb;
+ }
+ }
eclass = ExprClass.Value;
//
type = InternalType.AnonymousMethod;
- if (!DoResolveParameters (ec))
+ if (!DoResolveParameters (rc))
return null;
return this;
// nothing, as we only exist to not do anything.
}
- public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc)
+ public static void Error_AddressOfCapturedVar (ResolveContext rc, IVariableReference var, Location loc)
{
- ec.Report.Error (1686, loc,
+ if (rc.CurrentAnonymousMethod is AsyncInitializer)
+ return;
+
+ rc.Report.Error (1686, loc,
"Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method, lambda expression or query expression",
var.Name);
}
Modifiers modifiers;
TypeDefinition parent = null;
+ TypeParameters hoisted_tparams = null;
+ ParametersCompiled method_parameters = parameters;
var src_block = Block.Original.Explicit;
if (src_block.HasCapturedVariable || src_block.HasCapturedThis) {
// use ldftn on non-boxed instances either to share mutated state
//
parent = sm_parent.Parent.PartialContainer;
+ hoisted_tparams = sm_parent.OriginalTypeParameters;
} else if (sm is IteratorStorey) {
//
// For iterators we can host everything in one class
parent = storey = ec.CurrentAnonymousMethod.Storey;
modifiers = Modifiers.STATIC | Modifiers.PRIVATE;
+
+ //
+ // Convert generated method to closed delegate method where unused
+ // this argument is generated during compilation which speeds up dispatch
+ // by about 25%
+ //
+ // Unused as it breaks compatibility
+ //
+ // method_parameters = ParametersCompiled.Prefix (method_parameters,
+ // new Parameter (null, null, 0, null, loc), ec.Module.Compiler.BuiltinTypes.Object);
}
+ if (storey == null && hoisted_tparams == null)
+ hoisted_tparams = ec.CurrentTypeParameters;
+
if (parent == null)
parent = ec.CurrentTypeDefinition.Parent.PartialContainer;
"m", null, parent.PartialContainer.CounterAnonymousMethods++);
MemberName member_name;
- if (storey == null && ec.CurrentTypeParameters != null) {
-
- var hoisted_tparams = ec.CurrentTypeParameters;
+ if (hoisted_tparams != null) {
var type_params = new TypeParameters (hoisted_tparams.Count);
for (int i = 0; i < hoisted_tparams.Count; ++i) {
type_params.Add (hoisted_tparams[i].CreateHoistedCopy (null));
return new AnonymousMethodMethod (parent,
this, storey, new TypeExpression (ReturnType, Location), modifiers,
- member_name, parameters);
+ member_name, method_parameters);
}
protected override Expression DoResolve (ResolveContext ec)
}
bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
- if (is_static && am_cache == null) {
+ if (is_static && am_cache == null && !ec.IsStaticConstructor) {
//
// Creates a field cache to store delegate instance if it's not generic
//
ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
} else {
- if (delegate_method.IsGeneric)
- delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters);
+ if (delegate_method.IsGeneric) {
+ TypeParameterSpec[] tparams;
+ var sm = ec.CurrentAnonymousMethod == null ? null : ec.CurrentAnonymousMethod.Storey as StateMachine;
+ if (sm != null && sm.OriginalTypeParameters != null) {
+ tparams = sm.CurrentTypeParameters.Types;
+ } else {
+ tparams = method.TypeParameters;
+ }
+
+ delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, tparams);
+ }
ec.Emit (OpCodes.Ldftn, delegate_method);
}
equals.Block = equals_block;
equals.Define ();
- equals.PrepareEmit ();
Members.Add (equals);
//
hashcode_block.AddStatement (new Return (hash_variable, loc));
hashcode.Block = hashcode_top;
hashcode.Define ();
- hashcode.PrepareEmit ();
Members.Add (hashcode);
//
tostring_block.AddStatement (new Return (string_concat, loc));
tostring.Block = tostring_block;
tostring.Define ();
- tostring.PrepareEmit ();
Members.Add (tostring);
return true;