}
if (hoisted == null) {
- hoisted = new HoistedLocalVariable (this, localVariable, GetVariableMangledName (localVariable));
+ hoisted = new HoistedLocalVariable (this, localVariable, GetVariableMangledName (ec, localVariable));
localVariable.HoistedVariant = hoisted;
if (hoisted_locals == null)
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);
}
fexpr.EmitAssign (ec, source, false, false);
Instance = fexpr;
} else {
- var local = TemporaryVariableReference.Create (source.Type, block, Location);
+ var local = TemporaryVariableReference.Create (source.Type, block, Location, writeToSymbolFile: true);
if (source.Type.IsStruct) {
local.LocalInfo.CreateBuilder (ec);
} else {
return f_ind;
}
- protected virtual string GetVariableMangledName (LocalVariable local_info)
+ protected virtual string GetVariableMangledName (ResolveContext rc, LocalVariable local_info)
{
//
// No need to mangle anonymous method hoisted variables cause they
prev = null;
}
- var body = CompatibleMethodBody (ec, tic, null, delegate_type);
+ HashSet<LocalVariable> undeclaredVariables = null;
+ var body = CompatibleMethodBody (ec, tic, null, delegate_type, ref undeclaredVariables);
if (body != null) {
am = body.Compatible (ec, body);
} else {
if (TypeInferenceReportPrinter != null) {
ec.Report.SetPrinter (prev);
}
+
+ if (undeclaredVariables != null) {
+ body.Block.TopBlock.SetUndeclaredVariables (undeclaredVariables);
+ }
}
if (am == null)
if (compatibles.TryGetValue (type, out am))
return am;
+ if (type == InternalType.ErrorType)
+ return null;
+
TypeSpec delegate_type = CompatibleChecks (ec, type);
if (delegate_type == null)
return null;
// we satisfy the rule by setting the return type on the EmitContext
// to be the delegate type return type.
//
-
- var body = CompatibleMethodBody (ec, null, return_type, delegate_type);
+ HashSet<LocalVariable> undeclaredVariables = null;
+ var body = CompatibleMethodBody (ec, null, return_type, delegate_type, ref undeclaredVariables);
if (body == null)
return null;
throw;
} catch (Exception e) {
throw new InternalErrorException (e, loc);
+ } finally {
+ //
+ // LocalVariable is not stateless and it's not easy to clone because it's
+ // cached in toplevel block. Unsetting any initialized variables should
+ // be enough
+ //
+ if (undeclaredVariables != null) {
+ body.Block.TopBlock.SetUndeclaredVariables (undeclaredVariables);
+ }
}
if (!ec.IsInProbingMode && !etree_conversion) {
return ExprClassName;
}
- AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type)
+ AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type, ref HashSet<LocalVariable> undeclaredVariables)
{
ParametersCompiled p = ResolveParameters (ec, tic, delegate_type);
if (p == null)
return null;
- ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block;
+ ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone (ref undeclaredVariables) : Block;
if (b.IsAsync) {
var rt = return_type;
fc.ParametersBlock = Block;
var da_ontrue = fc.DefiniteAssignmentOnTrue;
var da_onfalse = fc.DefiniteAssignmentOnFalse;
+ var prev_tf = fc.TryFinally;
fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = null;
+ fc.TryFinally = null;
block.FlowAnalysis (fc);
fc.ParametersBlock = prev_pb;
fc.DefiniteAssignment = das;
fc.DefiniteAssignmentOnTrue = da_ontrue;
fc.DefiniteAssignmentOnFalse = da_onfalse;
+ fc.TryFinally = prev_tf;
}
public override void MarkReachable (Reachability rc)
var delegate_method = method.Spec;
if (storey != null && storey.MemberName.IsGeneric) {
- TypeSpec t = storey.Instance.Type;
-
//
// Mutate anonymous method instance type if we are in nested
// hoisted generic anonymous method storey
//
if (ec.IsAnonymousStoreyMutateRequired) {
- t = storey.Mutator.Mutate (t);
+ ec.Emit (OpCodes.Ldftn, delegate_method);
+ } else {
+ TypeSpec t = storey.Instance.Type;
+ ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
}
-
- ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
} else {
if (delegate_method.IsGeneric) {
TypeParameterSpec[] tparams;