2010-07-14 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / statement.cs
index a19150d5115daa1b535b356516bb22daccab22f0..51a975d549f59797a6eeff5bfbe67ab96fdd1cc1 100644 (file)
@@ -92,16 +92,15 @@ namespace Mono.CSharp {
 
                        return Clone (clonectx);
                }
-
-               public abstract void MutateHoistedGenericType (AnonymousMethodStorey storey);
        }
 
-       public sealed class EmptyStatement : Statement {
-               
-               private EmptyStatement () {}
+       public sealed class EmptyStatement : Statement
+       {
+               public EmptyStatement (Location loc)
+               {
+                       this.loc = loc;
+               }
                
-               public static readonly EmptyStatement Value = new EmptyStatement ();
-
                public override bool Resolve (BlockContext ec)
                {
                        return true;
@@ -112,12 +111,13 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               protected override void DoEmit (EmitContext ec)
+               public override void Emit (EmitContext ec)
                {
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               protected override void DoEmit (EmitContext ec)
                {
+                       throw new NotSupportedException ();
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -149,14 +149,6 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-                       TrueStatement.MutateHoistedGenericType (storey);
-                       if (FalseStatement != null)
-                               FalseStatement.MutateHoistedGenericType (storey);
-               }
-
                public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
@@ -215,8 +207,7 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label false_target = ig.DefineLabel ();
+                       Label false_target = ec.DefineLabel ();
                        Label end;
 
                        //
@@ -242,19 +233,19 @@ namespace Mono.CSharp {
                        if (FalseStatement != null){
                                bool branch_emitted = false;
                                
-                               end = ig.DefineLabel ();
+                               end = ec.DefineLabel ();
                                if (!is_true_ret){
-                                       ig.Emit (OpCodes.Br, end);
+                                       ec.Emit (OpCodes.Br, end);
                                        branch_emitted = true;
                                }
 
-                               ig.MarkLabel (false_target);
+                               ec.MarkLabel (false_target);
                                FalseStatement.Emit (ec);
 
                                if (branch_emitted)
-                                       ig.MarkLabel (end);
+                                       ec.MarkLabel (end);
                        } else {
-                               ig.MarkLabel (false_target);
+                               ec.MarkLabel (false_target);
                        }
                }
 
@@ -312,17 +303,16 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label loop = ig.DefineLabel ();
+                       Label loop = ec.DefineLabel ();
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
                        
-                       ec.LoopBegin = ig.DefineLabel ();
-                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.LoopBegin = ec.DefineLabel ();
+                       ec.LoopEnd = ec.DefineLabel ();
                                
-                       ig.MarkLabel (loop);
+                       ec.MarkLabel (loop);
                        EmbeddedStatement.Emit (ec);
-                       ig.MarkLabel (ec.LoopBegin);
+                       ec.MarkLabel (ec.LoopBegin);
 
                        //
                        // Dead code elimination
@@ -332,22 +322,16 @@ namespace Mono.CSharp {
 
                                expr.EmitSideEffect (ec);
                                if (res)
-                                       ec.ig.Emit (OpCodes.Br, loop); 
+                                       ec.Emit (OpCodes.Br, loop); 
                        } else
                                expr.EmitBranchable (ec, loop, true);
                        
-                       ig.MarkLabel (ec.LoopEnd);
+                       ec.MarkLabel (ec.LoopEnd);
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-                       EmbeddedStatement.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Do target = (Do) t;
@@ -416,42 +400,41 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
                        
-                       ec.LoopBegin = ig.DefineLabel ();
-                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.LoopBegin = ec.DefineLabel ();
+                       ec.LoopEnd = ec.DefineLabel ();
 
                        //
                        // Inform whether we are infinite or not
                        //
                        if (expr is Constant){
                                // expr is 'true', since the 'empty' case above handles the 'false' case
-                               ig.MarkLabel (ec.LoopBegin);
+                               ec.MarkLabel (ec.LoopBegin);
                                expr.EmitSideEffect (ec);
                                Statement.Emit (ec);
-                               ig.Emit (OpCodes.Br, ec.LoopBegin);
+                               ec.Emit (OpCodes.Br, ec.LoopBegin);
                                        
                                //
                                // Inform that we are infinite (ie, `we return'), only
                                // if we do not `break' inside the code.
                                //
-                               ig.MarkLabel (ec.LoopEnd);
+                               ec.MarkLabel (ec.LoopEnd);
                        } else {
-                               Label while_loop = ig.DefineLabel ();
+                               Label while_loop = ec.DefineLabel ();
 
-                               ig.Emit (OpCodes.Br, ec.LoopBegin);
-                               ig.MarkLabel (while_loop);
+                               ec.Emit (OpCodes.Br, ec.LoopBegin);
+                               ec.MarkLabel (while_loop);
 
                                Statement.Emit (ec);
                        
-                               ig.MarkLabel (ec.LoopBegin);
+                               ec.MarkLabel (ec.LoopBegin);
                                ec.Mark (loc);
 
                                expr.EmitBranchable (ec, while_loop, true);
                                
-                               ig.MarkLabel (ec.LoopEnd);
+                               ec.MarkLabel (ec.LoopEnd);
                        }       
 
                        ec.LoopBegin = old_begin;
@@ -470,12 +453,6 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                        target.Statement = Statement.Clone (clonectx);
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-                       Statement.MutateHoistedGenericType (storey);
-               }
        }
 
        public class For : Statement {
@@ -559,7 +536,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       if (InitStatement != null && InitStatement != EmptyStatement.Value)
+                       if (InitStatement != null)
                                InitStatement.Emit (ec);
 
                        if (empty) {
@@ -567,24 +544,22 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       Label loop = ig.DefineLabel ();
-                       Label test = ig.DefineLabel ();
+                       Label loop = ec.DefineLabel ();
+                       Label test = ec.DefineLabel ();
 
-                       ec.LoopBegin = ig.DefineLabel ();
-                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.LoopBegin = ec.DefineLabel ();
+                       ec.LoopEnd = ec.DefineLabel ();
 
-                       ig.Emit (OpCodes.Br, test);
-                       ig.MarkLabel (loop);
+                       ec.Emit (OpCodes.Br, test);
+                       ec.MarkLabel (loop);
                        Statement.Emit (ec);
 
-                       ig.MarkLabel (ec.LoopBegin);
-                       if (Increment != EmptyStatement.Value)
-                               Increment.Emit (ec);
+                       ec.MarkLabel (ec.LoopBegin);
+                       Increment.Emit (ec);
 
-                       ig.MarkLabel (test);
+                       ec.MarkLabel (test);
                        //
                        // If test is null, there is no test, and we are just
                        // an infinite loop
@@ -597,31 +572,19 @@ namespace Mono.CSharp {
                                //
                                if (Test is Constant) {
                                        Test.EmitSideEffect (ec);
-                                       ig.Emit (OpCodes.Br, loop);
+                                       ec.Emit (OpCodes.Br, loop);
                                } else {
                                        Test.EmitBranchable (ec, loop, true);
                                }
                                
                        } else
-                               ig.Emit (OpCodes.Br, loop);
-                       ig.MarkLabel (ec.LoopEnd);
+                               ec.Emit (OpCodes.Br, loop);
+                       ec.MarkLabel (ec.LoopEnd);
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       if (InitStatement != null)
-                               InitStatement.MutateHoistedGenericType (storey);
-                       if (Test != null)
-                               Test.MutateHoistedGenericType (storey);
-                       if (Increment != null)
-                               Increment.MutateHoistedGenericType (storey);
-
-                       Statement.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        For target = (For) t;
@@ -656,11 +619,6 @@ namespace Mono.CSharp {
                        expr.EmitStatement (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-               }
-
                public override string ToString ()
                {
                        return "StatementExpression (" + expr + ")";
@@ -674,6 +632,55 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // Simple version of statement list not requiring a block
+       //
+       public class StatementList : Statement
+       {
+               List<Statement> statements;
+
+               public StatementList (Statement first, Statement second)
+               {
+                       statements = new List<Statement> () { first, second };
+               }
+
+               #region Properties
+               public IList<Statement> Statements {
+                       get {
+                               return statements;
+                       }
+               }
+               #endregion
+
+               public void Add (Statement statement)
+               {
+                       statements.Add (statement);
+               }
+
+               public override bool Resolve (BlockContext ec)
+               {
+                       foreach (var s in statements)
+                               s.Resolve (ec);
+
+                       return true;
+               }
+
+               protected override void DoEmit (EmitContext ec)
+               {
+                       foreach (var s in statements)
+                               s.Emit (ec);
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Statement target)
+               {
+                       StatementList t = (StatementList) target;
+
+                       t.statements = new List<Statement> (statements.Count);
+                       foreach (Statement s in statements)
+                               t.statements.Add (s.Clone (clonectx));
+               }
+       }
+
        // A 'return' or a 'yield break'
        public abstract class ExitStatement : Statement
        {
@@ -701,14 +708,23 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the return statement
        /// </summary>
-       public class Return : ExitStatement {
+       public class Return : ExitStatement
+       {
                protected Expression Expr;
                public Return (Expression expr, Location l)
                {
                        Expr = expr;
                        loc = l;
                }
-               
+
+               #region Properties
+               public Expression Expression {
+                       get {
+                               return Expr;
+                       }
+               }
+               #endregion
+
                protected override bool DoResolve (BlockContext ec)
                {
                        if (Expr == null) {
@@ -763,19 +779,13 @@ namespace Mono.CSharp {
                                Expr.Emit (ec);
 
                                if (unwind_protect)
-                                       ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
+                                       ec.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
                        }
 
                        if (unwind_protect)
-                               ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+                               ec.Emit (OpCodes.Leave, ec.ReturnLabel);
                        else
-                               ec.ig.Emit (OpCodes.Ret);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       if (Expr != null)
-                               Expr.MutateHoistedGenericType (storey);
+                               ec.Emit (OpCodes.Ret);
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -825,11 +835,7 @@ namespace Mono.CSharp {
                        if (label == null)
                                throw new InternalErrorException ("goto emitted before target resolved");
                        Label l = label.LabelTarget (ec);
-                       ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
+                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
                }
        }
 
@@ -838,7 +844,6 @@ namespace Mono.CSharp {
                bool defined;
                bool referenced;
                Label label;
-               ILGenerator ig;
 
                FlowBranching.UsageVector vectors;
                
@@ -852,10 +857,9 @@ namespace Mono.CSharp {
                {
                        if (defined)
                                return label;
-                       ig = ec.ig;
-                       label = ec.ig.DefineLabel ();
-                       defined = true;
 
+                       label = ec.DefineLabel ();
+                       defined = true;
                        return label;
                }
 
@@ -896,14 +900,8 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       if (ig != null && ig != ec.ig)
-                               throw new InternalErrorException ("cannot happen");
                        LabelTarget (ec);
-                       ec.ig.MarkLabel (label);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
+                       ec.MarkLabel (label);
                }
 
                public void AddReference ()
@@ -947,11 +945,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
+                       ec.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
                }
        }
 
@@ -987,7 +981,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       Type type = ec.Switch.SwitchType;
+                       TypeSpec type = ec.Switch.SwitchType;
                        Constant res = c.TryReduce (ec, type, c.Location);
                        if (res == null) {
                                c.Error_ValueCannotBeConverted (ec, loc, type, true);
@@ -1014,12 +1008,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
+                       ec.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1063,20 +1052,14 @@ namespace Mono.CSharp {
                protected override void DoEmit (EmitContext ec)
                {
                        if (expr == null)
-                               ec.ig.Emit (OpCodes.Rethrow);
+                               ec.Emit (OpCodes.Rethrow);
                        else {
                                expr.Emit (ec);
 
-                               ec.ig.Emit (OpCodes.Throw);
+                               ec.Emit (OpCodes.Throw);
                        }
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       if (expr != null)
-                               expr.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Throw target = (Throw) t;
@@ -1104,13 +1087,9 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
+                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-               }
-               
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        // nothing needed
@@ -1135,11 +1114,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
+                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1166,7 +1141,7 @@ namespace Mono.CSharp {
        public class LocalInfo : IKnownVariable, ILocalVariable {
                public readonly FullNamedExpression Type;
 
-               public Type VariableType;
+               public TypeSpec VariableType;
                public readonly string Name;
                public readonly Location Location;
                public readonly Block Block;
@@ -1203,9 +1178,9 @@ namespace Mono.CSharp {
                        Location = l;
                }
 
-               public LocalInfo (DeclSpace ds, Block block, Location l)
+               public LocalInfo (TypeContainer ds, Block block, Location l)
                {
-                       VariableType = ds.IsGeneric ? ds.CurrentType : ds.TypeBuilder;
+                       VariableType = ds.IsGeneric ? ds.CurrentType : ds.Definition;
                        Block = block;
                        Location = l;
                }
@@ -1216,23 +1191,23 @@ namespace Mono.CSharp {
                                return;
 
                        if (builder == null) {
-                               builder = ec.ig.DeclareLocal (TypeManager.TypeToReflectionType (VariableType), Pinned);
+                               builder = ec.DeclareLocal (VariableType, Pinned);
                        }
                }
 
                public void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldloc, builder);
+                       ec.Emit (OpCodes.Ldloc, builder);
                }
 
                public void EmitAssign (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Stloc, builder);
+                       ec.Emit (OpCodes.Stloc, builder);
                }
 
                public void EmitAddressOf (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldloca, builder);
+                       ec.Emit (OpCodes.Ldloca, builder);
                }
 
                public void EmitSymbolInfo (EmitContext ec)
@@ -1283,10 +1258,7 @@ namespace Mono.CSharp {
                                
                        VariableType = texpr.Type;
 
-                       if (TypeManager.IsGenericParameter (VariableType))
-                               return true;
-
-                       if (VariableType.IsAbstract && VariableType.IsSealed) {
+                       if (VariableType.IsStatic) {
                                FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType, ec.Report);
                                return false;
                        }
@@ -1478,6 +1450,8 @@ namespace Mono.CSharp {
 
                List<ToplevelBlock> anonymous_children;
 
+               int? resolving_init_idx;
+
                protected static int id;
 
                int this_id;
@@ -1531,13 +1505,7 @@ namespace Mono.CSharp {
                        statements = new List<Statement> (4);
                }
 
-               public Block CreateSwitchBlock (Location start)
-               {
-                       // FIXME: should this be implicit?
-                       Block new_block = new ExplicitBlock (this, start, start);
-                       new_block.switch_block = this;
-                       return new_block;
-               }
+               #region Properties
 
                public int ID {
                        get { return this_id; }
@@ -1551,6 +1519,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               #endregion
+
+               public Block CreateSwitchBlock (Location start)
+               {
+                       // FIXME: should this be implicit?
+                       Block new_block = new ExplicitBlock (this, start, start);
+                       new_block.switch_block = this;
+                       return new_block;
+               }
+
                void AddChild (Block b)
                {
                        if (children == null)
@@ -1724,7 +1702,7 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               protected virtual bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
+               protected bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
                {
                        LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
@@ -1739,13 +1717,13 @@ namespace Mono.CSharp {
                        }
 
                        if (block != null) {
-                               Expression e = block.GetParameterReference (name, Location.Null);
-                               if (e != null) {
-                                       ParameterReference pr = e as ParameterReference;
-                                       if (this is Linq.QueryBlock && (pr != null && pr.Parameter is Linq.QueryBlock.ImplicitQueryParameter || e is MemberAccess))
+                               var tblock = block.CheckParameterNameConflict (name);
+                               if (tblock != null) {
+                                       if (block == tblock && block is Linq.QueryBlock)
                                                Error_AlreadyDeclared (loc, name);
                                        else
                                                Error_AlreadyDeclared (loc, name, "parent or current");
+
                                        return false;
                                }
                        }
@@ -1758,16 +1736,6 @@ namespace Mono.CSharp {
                        if (!CheckParentConflictName (Toplevel, name, l))
                                return null;
 
-                       if (Toplevel.GenericMethod != null) {
-                               foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
-                                       if (tp.Name == name) {
-                                               Toplevel.Report.SymbolRelatedToPreviousError (tp);
-                                               Error_AlreadyDeclaredTypeParameter (Toplevel.Report, loc, name, "local variable");
-                                               return null;
-                                       }
-                               }
-                       }                       
-
                        IKnownVariable kvi = Explicit.GetKnownVariable (name);
                        if (kvi != null) {
                                Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
@@ -1809,9 +1777,9 @@ namespace Mono.CSharp {
                                "A local variable named `{0}' is already defined in this scope", name);
                }
                                        
-               public virtual void Error_AlreadyDeclaredTypeParameter (Report r, Location loc, string name, string conflict)
+               public virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
                {
-                       r.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
+                       Toplevel.Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
                                name, conflict);
                }
 
@@ -1852,9 +1820,8 @@ namespace Mono.CSharp {
                {
                        LocalInfo ret;
                        for (Block b = this; b != null; b = b.Parent) {
-                               if (b.variables != null) {
-                                       if (b.variables.TryGetValue (name, out ret))
-                                               return ret;
+                               if (b.variables != null && b.variables.TryGetValue (name, out ret)) {
+                                       return ret;
                                }
                        }
 
@@ -1888,7 +1855,18 @@ namespace Mono.CSharp {
                        if (scope_initializers == null)
                                scope_initializers = new List<Statement> ();
 
-                       scope_initializers.Add (s);
+                       //
+                       // Simple recursive helper, when resolve scope initializer another
+                       // new scope initializer can be added, this ensures it's initialized
+                       // before existing one. For now this can happen with expression trees
+                       // in base ctor initializer only
+                       //
+                       if (resolving_init_idx.HasValue) {
+                               scope_initializers.Insert (resolving_init_idx.Value, s);
+                               ++resolving_init_idx;
+                       } else {
+                               scope_initializers.Add (s);
+                       }
                }
                
                public void AddStatement (Statement s)
@@ -1942,7 +1920,7 @@ namespace Mono.CSharp {
                        foreach (var de in variables) {
                                string name = de.Key;
                                LocalInfo vi = de.Value;
-                               Type variable_type = vi.VariableType;
+                               TypeSpec variable_type = vi.VariableType;
 
                                if (variable_type == null) {
                                        if (vi.Type is VarExpr)
@@ -1960,7 +1938,7 @@ namespace Mono.CSharp {
                                // which in turn causes the 'must be constant' error to be triggered.
                                constants.Remove (name);
 
-                               if (!Const.IsConstantTypeValid (variable_type)) {
+                               if (!variable_type.IsConstantCompatible) {
                                        Const.Error_InvalidConstantType (variable_type, loc, ec.Report);
                                        continue;
                                }
@@ -2110,8 +2088,11 @@ namespace Mono.CSharp {
                        // Compiler generated scope statements
                        //
                        if (scope_initializers != null) {
-                               foreach (Statement s in scope_initializers)
-                                       s.Resolve (ec);
+                               for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) {
+                                       scope_initializers[resolving_init_idx.Value].Resolve (ec);
+                               }
+
+                               resolving_init_idx = null;
                        }
 
                        //
@@ -2158,12 +2139,12 @@ namespace Mono.CSharp {
                                        if (ec.IsInProbingMode)
                                                break;
 
-                                       statements [ix] = EmptyStatement.Value;
+                                       statements [ix] = new EmptyStatement (s.loc);
                                        continue;
                                }
 
                                if (unreachable && !(s is LabeledStatement) && !(s is Block))
-                                       statements [ix] = EmptyStatement.Value;
+                                       statements [ix] = new EmptyStatement (s.loc);
 
                                unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
                                if (unreachable && s is LabeledStatement)
@@ -2218,8 +2199,7 @@ namespace Mono.CSharp {
                protected override void DoEmit (EmitContext ec)
                {
                        for (int ix = 0; ix < statements.Count; ix++){
-                               Statement s = (Statement) statements [ix];
-                               s.Emit (ec);
+                               statements [ix].Emit (ec);
                        }
                }
 
@@ -2237,14 +2217,14 @@ namespace Mono.CSharp {
 
                protected void EmitScopeInitializers (EmitContext ec)
                {
-                       SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
+                       SymbolWriter.OpenCompilerGeneratedBlock (ec);
 
                        using (ec.With (EmitContext.Options.OmitDebugInfo, true)) {
                                foreach (Statement s in scope_initializers)
                                        s.Emit (ec);
                        }
 
-                       SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
+                       SymbolWriter.CloseCompilerGeneratedBlock (ec);
                }
 
                protected virtual void EmitSymbolInfo (EmitContext ec)
@@ -2256,36 +2236,9 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       MutateVariables (storey);
-
-                       if (scope_initializers != null) {
-                               foreach (Statement s in scope_initializers)
-                                       s.MutateHoistedGenericType (storey);
-                       }
-
-                       foreach (Statement s in statements)
-                               s.MutateHoistedGenericType (storey);
-               }
-
-               void MutateVariables (AnonymousMethodStorey storey)
-               {
-                       if (variables != null) {
-                               foreach (LocalInfo vi in variables.Values) {
-                                       vi.VariableType = storey.MutateType (vi.VariableType);
-                               }
-                       }
-
-                       if (temporary_variables != null) {
-                               foreach (LocalInfo vi in temporary_variables)
-                                       vi.VariableType = storey.MutateType (vi.VariableType);
-                       }
-               }
-
                public override string ToString ()
                {
-                       return String.Format ("{0} ({1}:{2})", GetType (),ID, StartLocation);
+                       return String.Format ("{0} ({1}:{2})", GetType (), this_id, StartLocation);
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -2294,7 +2247,7 @@ namespace Mono.CSharp {
 
                        clonectx.AddBlockMap (this, target);
 
-                       //target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
+                       target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
                        target.Explicit = (ExplicitBlock) clonectx.LookupBlock (Explicit);
                        if (Parent != null)
                                target.Parent = clonectx.RemapBlockCopy (Parent);
@@ -2387,7 +2340,7 @@ namespace Mono.CSharp {
                                //
                                // Creates anonymous method storey for this block
                                //
-                               am_storey = new AnonymousMethodStorey (this, ec.CurrentTypeDefinition, mc, gm, "AnonStorey");
+                               am_storey = new AnonymousMethodStorey (this, ec.CurrentMemberDefinition.Parent.PartialContainer, mc, gm, "AnonStorey");
                        }
 
                        return am_storey;
@@ -2427,14 +2380,21 @@ namespace Mono.CSharp {
                                                while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey)
                                                        parent = parent.Parent.Explicit;
 
-                                               am_storey.AddParentStoreyReference (parent.am_storey);
+                                               am_storey.AddParentStoreyReference (ec, parent.am_storey);
                                        }
 
-                                       am_storey.ChangeParentStorey (ec.CurrentAnonymousMethod.Storey);
+                                       am_storey.SetNestedStoryParent (ec.CurrentAnonymousMethod.Storey);
+
+                                       // TODO MemberCache: Review
+                                       am_storey.Mutator = ec.CurrentAnonymousMethod.Storey.Mutator;
                                }
 
+                               am_storey.CreateType ();
+                               if (am_storey.Mutator == null && ec.CurrentTypeParameters != null)
+                                       am_storey.Mutator = new TypeParameterMutator (ec.CurrentTypeParameters, am_storey.CurrentTypeParameters);
+
                                am_storey.DefineType ();
-                               am_storey.ResolveType ();
+                               am_storey.ResolveTypeParameters ();
                                am_storey.Define ();
                                am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
 
@@ -2443,7 +2403,7 @@ namespace Mono.CSharp {
                                        foreach (ExplicitBlock ref_block in ref_blocks) {
                                                for (ExplicitBlock b = ref_block.Explicit; b != this; b = b.Parent.Explicit) {
                                                        if (b.am_storey != null) {
-                                                               b.am_storey.AddParentStoreyReference (am_storey);
+                                                               b.am_storey.AddParentStoreyReference (ec, am_storey);
 
                                                                // Stop propagation inside same top block
                                                                if (b.Toplevel == Toplevel)
@@ -2460,15 +2420,13 @@ namespace Mono.CSharp {
                        base.EmitMeta (ec);
                }
 
-               internal IKnownVariable GetKnownVariable (string name)
+               public IKnownVariable GetKnownVariable (string name)
                {
                        if (known_variables == null)
                                return null;
 
                        IKnownVariable kw;
-                       if (!known_variables.TryGetValue (name, out kw))
-                               return null;
-
+                       known_variables.TryGetValue (name, out kw);
                        return kw;
                }
 
@@ -2504,7 +2462,7 @@ namespace Mono.CSharp {
                        get { return Block.Parameters [Index]; }
                }
 
-               public Type ParameterType {
+               public TypeSpec ParameterType {
                        get { return Block.Parameters.Types [Index]; }
                }
 
@@ -2568,18 +2526,10 @@ namespace Mono.CSharp {
                                block.EmitScopeInitializers (ec);
                                child.Emit (ec);
                        }
-
-                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-                       {
-                               type = storey.MutateType (type);
-                               child.MutateHoistedGenericType (storey);
-                               block.MutateHoistedGenericType (storey);
-                       }
                }
 
-               GenericMethod generic;
                protected ParametersCompiled parameters;
-               ToplevelParameterInfo[] parameter_info;
+               protected ToplevelParameterInfo[] parameter_info;
                LocalInfo this_variable;
                bool resolved;
                bool unreachable;
@@ -2604,10 +2554,6 @@ namespace Mono.CSharp {
                        get { return compiler.Report; }
                }
 
-               public GenericMethod GenericMethod {
-                       get { return generic; }
-               }
-
                public ToplevelBlock Container {
                        get { return Parent == null ? null : Parent.Toplevel; }
                }
@@ -2617,12 +2563,6 @@ namespace Mono.CSharp {
                {
                }
 
-               public ToplevelBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, GenericMethod generic, Location start) :
-                       this (ctx, parent, parameters, start)
-               {
-                       this.generic = generic;
-               }
-
                public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) :
                        this (ctx, null, (Flags) 0, parameters, start)
                {
@@ -2660,10 +2600,11 @@ namespace Mono.CSharp {
                        ToplevelBlock target = (ToplevelBlock) t;
                        base.CloneTo (clonectx, t);
 
-                       if (parameters.Count != 0)
-                               target.parameter_info = new ToplevelParameterInfo [parameters.Count];
-                       for (int i = 0; i < parameters.Count; ++i)
-                               target.parameter_info [i] = new ToplevelParameterInfo (target, i);
+                       if (parameters.Count != 0) {
+                               target.parameter_info = new ToplevelParameterInfo[parameters.Count];
+                               for (int i = 0; i < parameters.Count; ++i)
+                                       target.parameter_info[i] = new ToplevelParameterInfo (target, i);
+                       }
                }
 
                public bool CheckError158 (string name, Location loc)
@@ -2756,6 +2697,9 @@ namespace Mono.CSharp {
                public Expression GetParameterReference (string name, Location loc)
                {
                        for (ToplevelBlock t = this; t != null; t = t.Container) {
+                               if (t.parameters.IsEmpty)
+                                       continue;
+
                                Expression expr = t.GetParameterReferenceExpression (name, loc);
                                if (expr != null)
                                        return expr;
@@ -2771,6 +2715,21 @@ namespace Mono.CSharp {
                                null : new ParameterReference (parameter_info [idx], loc);
                }
 
+               public ToplevelBlock CheckParameterNameConflict (string name)
+               {
+                       for (ToplevelBlock t = this; t != null; t = t.Container) {
+                               if (t.HasParameterWithName (name))
+                                       return t;
+                       }
+
+                       return null;
+               }
+
+               protected virtual bool HasParameterWithName (string name)
+               {
+                       return parameters.GetParameterIndexByName (name) >= 0;
+               }
+
                // <summary>
                //   Returns the "this" instance variable of this block.
                //   See AddThisVariable() for more information.
@@ -2786,7 +2745,7 @@ namespace Mono.CSharp {
                //   analysis code to ensure that it's been fully initialized before control
                //   leaves the constructor.
                // </summary>
-               public LocalInfo AddThisVariable (DeclSpace ds, Location l)
+               public LocalInfo AddThisVariable (TypeContainer ds, Location l)
                {
                        if (this_variable == null) {
                                this_variable = new LocalInfo (ds, this, l);
@@ -2838,15 +2797,18 @@ namespace Mono.CSharp {
 
                                        unreachable = top_level.End ();
                                }
-                       } catch (Exception) {
-#if PRODUCTION
+                       } catch (Exception e) {
+                               if (e is CompletionResult || rc.Report.IsDisabled)
+                                       throw;
+
                                if (rc.CurrentBlock != null) {
-                                       ec.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: Phase Resolve");
+                                       rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message);
                                } else {
-                                       ec.Report.Error (587, "Internal compiler error: Phase Resolve");
+                                       rc.Report.Error (587, "Internal compiler error: {0}", e.Message);
                                }
-#endif
-                               throw;
+
+                               if (Report.DebugFlags > 0)
+                                       throw;
                        }
 
                        if (rc.ReturnType != TypeManager.void_type && !unreachable) {
@@ -2928,18 +2890,18 @@ namespace Mono.CSharp {
                        EmitMeta (ec);
 
                        if (ec.HasReturnLabel)
-                               ec.ReturnLabel = ec.ig.DefineLabel ();
+                               ec.ReturnLabel = ec.DefineLabel ();
 
                        base.Emit (ec);
 
                        ec.Mark (EndLocation);
 
                        if (ec.HasReturnLabel)
-                               ec.ig.MarkLabel (ec.ReturnLabel);
+                               ec.MarkLabel (ec.ReturnLabel);
 
                        if (ec.return_value != null) {
-                               ec.ig.Emit (OpCodes.Ldloc, ec.return_value);
-                               ec.ig.Emit (OpCodes.Ret);
+                               ec.Emit (OpCodes.Ldloc, ec.return_value);
+                               ec.Emit (OpCodes.Ret);
                        } else {
                                //
                                // If `HasReturnLabel' is set, then we already emitted a
@@ -2956,8 +2918,8 @@ namespace Mono.CSharp {
 
                                if (ec.HasReturnLabel || !unreachable) {
                                        if (ec.ReturnType != TypeManager.void_type)
-                                               ec.ig.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
-                                       ec.ig.Emit (OpCodes.Ret);
+                                               ec.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
+                                       ec.Emit (OpCodes.Ret);
                                }
                        }
 
@@ -2974,8 +2936,6 @@ namespace Mono.CSharp {
 
                public override void EmitMeta (EmitContext ec)
                {
-                       parameters.ResolveVariable ();
-
                        // Avoid declaring an IL variable for this_variable since it is not accessed
                        // from the generated IL
                        if (this_variable != null)
@@ -3033,7 +2993,7 @@ namespace Mono.CSharp {
                public Label GetILLabel (EmitContext ec)
                {
                        if (!il_label_set){
-                               il_label = ec.ig.DefineLabel ();
+                               il_label = ec.DefineLabel ();
                                il_label_set = true;
                        }
                        return il_label;
@@ -3042,7 +3002,7 @@ namespace Mono.CSharp {
                public Label GetILLabelCode (EmitContext ec)
                {
                        if (!il_label_code_set){
-                               il_label_code = ec.ig.DefineLabel ();
+                               il_label_code = ec.DefineLabel ();
                                il_label_code_set = true;
                        }
                        return il_label_code;
@@ -3052,7 +3012,7 @@ namespace Mono.CSharp {
                // Resolves the expression, reduces it to a literal if possible
                // and then converts it to the requested type.
                //
-               public bool ResolveAndReduce (ResolveContext ec, Type required_type, bool allow_nullable)
+               public bool ResolveAndReduce (ResolveContext ec, TypeSpec required_type, bool allow_nullable)
                {       
                        Expression e = label.Resolve (ec);
 
@@ -3083,7 +3043,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public void Error_AlreadyOccurs (ResolveContext ec, Type switch_type, SwitchLabel collision_with)
+               public void Error_AlreadyOccurs (ResolveContext ec, TypeSpec switch_type, SwitchLabel collision_with)
                {
                        string label;
                        if (converted == null)
@@ -3137,7 +3097,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   The governing switch type
                /// </summary>
-               public Type SwitchType;
+               public TypeSpec SwitchType;
 
                //
                // Computed
@@ -3167,7 +3127,7 @@ namespace Mono.CSharp {
                // The types allowed to be implicitly cast from
                // on the governing type
                //
-               static Type [] allowed_types;
+               static TypeSpec [] allowed_types;
 
                public Switch (Expression e, List<SwitchSection> sects, Location l)
                {
@@ -3196,7 +3156,7 @@ namespace Mono.CSharp {
                //
                Expression SwitchGoverningType (ResolveContext ec, Expression expr)
                {
-                       Type t = expr.Type;
+                       TypeSpec t = expr.Type;
 
                        if (t == TypeManager.byte_type ||
                            t == TypeManager.sbyte_type ||
@@ -3213,7 +3173,7 @@ namespace Mono.CSharp {
                                return expr;
 
                        if (allowed_types == null){
-                               allowed_types = new Type [] {
+                               allowed_types = new TypeSpec [] {
                                        TypeManager.sbyte_type,
                                        TypeManager.byte_type,
                                        TypeManager.short_type,
@@ -3234,7 +3194,7 @@ namespace Mono.CSharp {
                        // conversions, we have to report an error
                        //
                        Expression converted = null;
-                       foreach (Type tt in allowed_types){
+                       foreach (TypeSpec tt in allowed_types){
                                Expression e;
                                
                                e = Convert.ImplicitUserConversion (ec, expr, tt, loc);
@@ -3301,50 +3261,50 @@ namespace Mono.CSharp {
                        return !error;
                }
 
-               void EmitObjectInteger (ILGenerator ig, object k)
+               void EmitObjectInteger (EmitContext ec, object k)
                {
                        if (k is int)
-                               IntConstant.EmitInt (ig, (int) k);
+                               ec.EmitInt ((int) k);
                        else if (k is Constant) {
-                               EmitObjectInteger (ig, ((Constant) k).GetValue ());
+                               EmitObjectInteger (ec, ((Constant) k).GetValue ());
                        } 
                        else if (k is uint)
-                               IntConstant.EmitInt (ig, unchecked ((int) (uint) k));
+                               ec.EmitInt (unchecked ((int) (uint) k));
                        else if (k is long)
                        {
                                if ((long) k >= int.MinValue && (long) k <= int.MaxValue)
                                {
-                                       IntConstant.EmitInt (ig, (int) (long) k);
-                                       ig.Emit (OpCodes.Conv_I8);
+                                       ec.EmitInt ((int) (long) k);
+                                       ec.Emit (OpCodes.Conv_I8);
                                }
                                else
-                                       LongConstant.EmitLong (ig, (long) k);
+                                       ec.EmitLong ((long) k);
                        }
                        else if (k is ulong)
                        {
                                ulong ul = (ulong) k;
                                if (ul < (1L<<32))
                                {
-                                       IntConstant.EmitInt (ig, unchecked ((int) ul));
-                                       ig.Emit (OpCodes.Conv_U8);
+                                       ec.EmitInt (unchecked ((int) ul));
+                                       ec.Emit (OpCodes.Conv_U8);
                                }
                                else
                                {
-                                       LongConstant.EmitLong (ig, unchecked ((long) ul));
+                                       ec.EmitLong (unchecked ((long) ul));
                                }
                        }
                        else if (k is char)
-                               IntConstant.EmitInt (ig, (int) ((char) k));
+                               ec.EmitInt ((int) ((char) k));
                        else if (k is sbyte)
-                               IntConstant.EmitInt (ig, (int) ((sbyte) k));
+                               ec.EmitInt ((int) ((sbyte) k));
                        else if (k is byte)
-                               IntConstant.EmitInt (ig, (int) ((byte) k));
+                               ec.EmitInt ((int) ((byte) k));
                        else if (k is short)
-                               IntConstant.EmitInt (ig, (int) ((short) k));
+                               ec.EmitInt ((int) ((short) k));
                        else if (k is ushort)
-                               IntConstant.EmitInt (ig, (int) ((ushort) k));
+                               ec.EmitInt ((int) ((ushort) k));
                        else if (k is bool)
-                               IntConstant.EmitInt (ig, ((bool) k) ? 1 : 0);
+                               ec.EmitInt (((bool) k) ? 1 : 0);
                        else
                                throw new Exception ("Unhandled case");
                }
@@ -3453,25 +3413,24 @@ namespace Mono.CSharp {
                        key_blocks.Sort ();
 
                        // okay now we can start...
-                       ILGenerator ig = ec.ig;
-                       Label lbl_end = ig.DefineLabel ();      // at the end ;-)
+                       Label lbl_end = ec.DefineLabel ();      // at the end ;-)
                        Label lbl_default = default_target;
 
                        Type type_keys = null;
                        if (element_keys.Length > 0)
                                type_keys = element_keys [0].GetType ();        // used for conversions
 
-                       Type compare_type;
+                       TypeSpec compare_type;
                        
                        if (TypeManager.IsEnumType (SwitchType))
-                               compare_type = TypeManager.GetEnumUnderlyingType (SwitchType);
+                               compare_type = EnumSpec.GetUnderlyingType (SwitchType);
                        else
                                compare_type = SwitchType;
                        
                        for (int iBlock = key_blocks.Count - 1; iBlock >= 0; --iBlock)
                        {
                                KeyBlock kb = ((KeyBlock) key_blocks [iBlock]);
-                               lbl_default = (iBlock == 0) ? default_target : ig.DefineLabel ();
+                               lbl_default = (iBlock == 0) ? default_target : ec.DefineLabel ();
                                if (kb.Length <= 2)
                                {
                                        foreach (object key in kb.element_keys) {
@@ -3480,8 +3439,8 @@ namespace Mono.CSharp {
                                                        val.EmitBranchable (ec, sl.GetILLabel (ec), false);
                                                } else {
                                                        val.Emit (ec);
-                                                       EmitObjectInteger (ig, key);
-                                                       ig.Emit (OpCodes.Beq, sl.GetILLabel (ec));
+                                                       EmitObjectInteger (ec, key);
+                                                       ec.Emit (OpCodes.Beq, sl.GetILLabel (ec));
                                                }
                                        }
                                }
@@ -3496,20 +3455,20 @@ namespace Mono.CSharp {
 
                                                // check block range (could be > 2^31)
                                                val.Emit (ec);
-                                               EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys));
-                                               ig.Emit (OpCodes.Blt, lbl_default);
+                                               EmitObjectInteger (ec, System.Convert.ChangeType (kb.first, type_keys));
+                                               ec.Emit (OpCodes.Blt, lbl_default);
                                                val.Emit (ec);
-                                               EmitObjectInteger (ig, System.Convert.ChangeType (kb.last, type_keys));
-                                               ig.Emit (OpCodes.Bgt, lbl_default);
+                                               EmitObjectInteger (ec, System.Convert.ChangeType (kb.last, type_keys));
+                                               ec.Emit (OpCodes.Bgt, lbl_default);
 
                                                // normalize range
                                                val.Emit (ec);
                                                if (kb.first != 0)
                                                {
-                                                       EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys));
-                                                       ig.Emit (OpCodes.Sub);
+                                                       EmitObjectInteger (ec, System.Convert.ChangeType (kb.first, type_keys));
+                                                       ec.Emit (OpCodes.Sub);
                                                }
-                                               ig.Emit (OpCodes.Conv_I4);      // assumes < 2^31 labels!
+                                               ec.Emit (OpCodes.Conv_I4);      // assumes < 2^31 labels!
                                        }
                                        else
                                        {
@@ -3518,13 +3477,13 @@ namespace Mono.CSharp {
                                                int first = (int) kb.first;
                                                if (first > 0)
                                                {
-                                                       IntConstant.EmitInt (ig, first);
-                                                       ig.Emit (OpCodes.Sub);
+                                                       ec.EmitInt (first);
+                                                       ec.Emit (OpCodes.Sub);
                                                }
                                                else if (first < 0)
                                                {
-                                                       IntConstant.EmitInt (ig, -first);
-                                                       ig.Emit (OpCodes.Add);
+                                                       ec.EmitInt (-first);
+                                                       ec.Emit (OpCodes.Add);
                                                }
                                        }
 
@@ -3545,12 +3504,12 @@ namespace Mono.CSharp {
                                                        switch_labels [iJump] = lbl_default;
                                        }
                                        // emit the switch opcode
-                                       ig.Emit (OpCodes.Switch, switch_labels);
+                                       ec.Emit (OpCodes.Switch, switch_labels);
                                }
 
                                // mark the default for this block
                                if (iBlock != 0)
-                                       ig.MarkLabel (lbl_default);
+                                       ec.MarkLabel (lbl_default);
                        }
 
                        // TODO: find the default case and emit it here,
@@ -3559,7 +3518,7 @@ namespace Mono.CSharp {
 
                        // the last default just goes to the end
                        if (element_keys.Length > 0)
-                               ig.Emit (OpCodes.Br, lbl_default);
+                               ec.Emit (OpCodes.Br, lbl_default);
 
                        // now emit the code for the sections
                        bool found_default = false;
@@ -3567,27 +3526,27 @@ namespace Mono.CSharp {
                        foreach (SwitchSection ss in Sections) {
                                foreach (SwitchLabel sl in ss.Labels) {
                                        if (sl.Converted == SwitchLabel.NullStringCase) {
-                                               ig.MarkLabel (null_target);
+                                               ec.MarkLabel (null_target);
                                        } else if (sl.Label == null) {
-                                               ig.MarkLabel (lbl_default);
+                                               ec.MarkLabel (lbl_default);
                                                found_default = true;
                                                if (!has_null_case)
-                                                       ig.MarkLabel (null_target);
+                                                       ec.MarkLabel (null_target);
                                        }
-                                       ig.MarkLabel (sl.GetILLabel (ec));
-                                       ig.MarkLabel (sl.GetILLabelCode (ec));
+                                       ec.MarkLabel (sl.GetILLabel (ec));
+                                       ec.MarkLabel (sl.GetILLabelCode (ec));
                                }
                                ss.Block.Emit (ec);
                        }
                        
                        if (!found_default) {
-                               ig.MarkLabel (lbl_default);
+                               ec.MarkLabel (lbl_default);
                                if (!has_null_case) {
-                                       ig.MarkLabel (null_target);
+                                       ec.MarkLabel (null_target);
                                }
                        }
                        
-                       ig.MarkLabel (lbl_end);
+                       ec.MarkLabel (lbl_end);
                }
 
                SwitchSection FindSection (SwitchLabel label)
@@ -3602,12 +3561,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       foreach (SwitchSection ss in Sections)
-                               ss.Block.MutateHoistedGenericType (storey);
-               }
-
                public static void Reset ()
                {
                        unique_counter = 0;
@@ -3731,12 +3684,13 @@ namespace Mono.CSharp {
                                string_dictionary_type = new MemberAccess (system_collections_generic, "Hashtable", loc);
                        }
 
-                       Field field = new Field (ec.CurrentTypeDefinition, string_dictionary_type,
+                       var ctype = ec.CurrentMemberDefinition.Parent.PartialContainer;
+                       Field field = new Field (ctype, string_dictionary_type,
                                Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
                                new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null);
                        if (!field.Define ())
                                return;
-                       ec.CurrentTypeDefinition.PartialContainer.AddField (field);
+                       ctype.AddField (field);
 
                        var init = new List<Expression> ();
                        int counter = 0;
@@ -3776,8 +3730,7 @@ namespace Mono.CSharp {
 
                void DoEmitStringSwitch (LocalTemporary value, EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label l_initialized = ig.DefineLabel ();
+                       Label l_initialized = ec.DefineLabel ();
 
                        //
                        // Skip initialization when value is null
@@ -3789,7 +3742,7 @@ namespace Mono.CSharp {
                        //
                        switch_cache_field.EmitBranchable (ec, l_initialized, true);
                        string_dictionary.EmitStatement (ec);
-                       ig.MarkLabel (l_initialized);
+                       ec.MarkLabel (l_initialized);
 
                        LocalTemporary string_switch_variable = new LocalTemporary (TypeManager.int32_type);
 
@@ -3811,13 +3764,13 @@ namespace Mono.CSharp {
                                Arguments get_value_args = new Arguments (1);
                                get_value_args.Add (new Argument (value));
 
-                               Expression get_item = new IndexerAccess (new ElementAccess (switch_cache_field, get_value_args), loc).Resolve (rc);
+                               Expression get_item = new IndexerAccess (new ElementAccess (switch_cache_field, get_value_args, loc), loc).Resolve (rc);
                                if (get_item == null)
                                        return;
 
                                LocalTemporary get_item_object = new LocalTemporary (TypeManager.object_type);
                                get_item_object.EmitAssign (ec, get_item, true, false);
-                               ec.ig.Emit (OpCodes.Brfalse, default_target);
+                               ec.Emit (OpCodes.Brfalse, default_target);
 
                                ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable,
                                        new Cast (new TypeExpression (TypeManager.int32_type, loc), get_item_object, loc)).Resolve (rc);
@@ -3832,10 +3785,8 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
-                       default_target = ig.DefineLabel ();
-                       null_target = ig.DefineLabel ();
+                       default_target = ec.DefineLabel ();
+                       null_target = ec.DefineLabel ();
 
                        // Store variable for comparission purposes
                        // TODO: Don't duplicate non-captured VariableReference
@@ -3843,7 +3794,7 @@ namespace Mono.CSharp {
                        if (HaveUnwrap) {
                                value = new LocalTemporary (SwitchType);
                                unwrap.EmitCheck (ec);
-                               ig.Emit (OpCodes.Brfalse, null_target);
+                               ec.Emit (OpCodes.Brfalse, null_target);
                                new_expr.Emit (ec);
                                value.Store (ec);
                        } else if (!is_constant) {
@@ -3859,7 +3810,7 @@ namespace Mono.CSharp {
                        Label old_end = ec.LoopEnd;
                        Switch old_switch = ec.Switch;
                        
-                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.LoopEnd = ec.DefineLabel ();
                        ec.Switch = this;
 
                        // Emit Code.
@@ -3876,7 +3827,7 @@ namespace Mono.CSharp {
                                value.Release (ec);
 
                        // Restore context state. 
-                       ig.MarkLabel (ec.LoopEnd);
+                       ec.MarkLabel (ec.LoopEnd);
 
                        //
                        // Restore the previous context
@@ -3907,7 +3858,7 @@ namespace Mono.CSharp {
                {
                        if (!prepared) {
                                prepared = true;
-                               resume_point = ec.ig.DefineLabel ();
+                               resume_point = ec.DefineLabel ();
                        }
                        return resume_point;
                }
@@ -3935,47 +3886,45 @@ namespace Mono.CSharp {
 
                protected sealed override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        EmitPreTryBody (ec);
 
                        if (resume_points != null) {
-                               IntConstant.EmitInt (ig, (int) Iterator.State.Running);
-                               ig.Emit (OpCodes.Stloc, iter.CurrentPC);
+                               ec.EmitInt ((int) Iterator.State.Running);
+                               ec.Emit (OpCodes.Stloc, iter.CurrentPC);
                        }
 
-                       ig.BeginExceptionBlock ();
+                       ec.BeginExceptionBlock ();
 
                        if (resume_points != null) {
-                               ig.MarkLabel (resume_point);
+                               ec.MarkLabel (resume_point);
 
                                // For normal control flow, we want to fall-through the Switch
                                // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above
-                               ig.Emit (OpCodes.Ldloc, iter.CurrentPC);
-                               IntConstant.EmitInt (ig, first_resume_pc);
-                               ig.Emit (OpCodes.Sub);
+                               ec.Emit (OpCodes.Ldloc, iter.CurrentPC);
+                               ec.EmitInt (first_resume_pc);
+                               ec.Emit (OpCodes.Sub);
 
                                Label [] labels = new Label [resume_points.Count];
                                for (int i = 0; i < resume_points.Count; ++i)
                                        labels [i] = ((ResumableStatement) resume_points [i]).PrepareForEmit (ec);
-                               ig.Emit (OpCodes.Switch, labels);
+                               ec.Emit (OpCodes.Switch, labels);
                        }
 
                        EmitTryBody (ec);
 
-                       ig.BeginFinallyBlock ();
+                       ec.BeginFinallyBlock ();
 
-                       Label start_finally = ec.ig.DefineLabel ();
+                       Label start_finally = ec.DefineLabel ();
                        if (resume_points != null) {
-                               ig.Emit (OpCodes.Ldloc, iter.SkipFinally);
-                               ig.Emit (OpCodes.Brfalse_S, start_finally);
-                               ig.Emit (OpCodes.Endfinally);
+                               ec.Emit (OpCodes.Ldloc, iter.SkipFinally);
+                               ec.Emit (OpCodes.Brfalse_S, start_finally);
+                               ec.Emit (OpCodes.Endfinally);
                        }
 
-                       ig.MarkLabel (start_finally);
+                       ec.MarkLabel (start_finally);
                        EmitFinallyBody (ec);
 
-                       ig.EndExceptionBlock ();
+                       ec.EndExceptionBlock ();
                }
 
                public void SomeCodeFollows ()
@@ -4013,7 +3962,7 @@ namespace Mono.CSharp {
                {
                        if (!prepared_for_dispose) {
                                prepared_for_dispose = true;
-                               dispose_try_block = ec.ig.DefineLabel ();
+                               dispose_try_block = ec.DefineLabel ();
                        }
                        return dispose_try_block;
                }
@@ -4025,17 +3974,15 @@ namespace Mono.CSharp {
 
                        emitted_dispose = true;
 
-                       ILGenerator ig = ec.ig;
-
-                       Label end_of_try = ig.DefineLabel ();
+                       Label end_of_try = ec.DefineLabel ();
 
                        // Ensure that the only way we can get into this code is through a dispatcher
                        if (have_dispatcher)
-                               ig.Emit (OpCodes.Br, end);
+                               ec.Emit (OpCodes.Br, end);
 
-                       ig.BeginExceptionBlock ();
+                       ec.BeginExceptionBlock ();
 
-                       ig.MarkLabel (dispose_try_block);
+                       ec.MarkLabel (dispose_try_block);
 
                        Label [] labels = null;
                        for (int i = 0; i < resume_points.Count; ++i) {
@@ -4060,10 +4007,10 @@ namespace Mono.CSharp {
 
                                if (emit_dispatcher) {
                                        //SymbolWriter.StartIteratorDispatcher (ec.ig);
-                                       ig.Emit (OpCodes.Ldloc, iterator.CurrentPC);
-                                       IntConstant.EmitInt (ig, first_resume_pc);
-                                       ig.Emit (OpCodes.Sub);
-                                       ig.Emit (OpCodes.Switch, labels);
+                                       ec.Emit (OpCodes.Ldloc, iterator.CurrentPC);
+                                       ec.EmitInt (first_resume_pc);
+                                       ec.Emit (OpCodes.Sub);
+                                       ec.Emit (OpCodes.Switch, labels);
                                        //SymbolWriter.EndIteratorDispatcher (ec.ig);
                                }
 
@@ -4071,13 +4018,13 @@ namespace Mono.CSharp {
                                        s.EmitForDispose (ec, iterator, end_of_try, emit_dispatcher);
                        }
 
-                       ig.MarkLabel (end_of_try);
+                       ec.MarkLabel (end_of_try);
 
-                       ig.BeginFinallyBlock ();
+                       ec.BeginFinallyBlock ();
 
                        EmitFinallyBody (ec);
 
-                       ig.EndExceptionBlock ();
+                       ec.EndExceptionBlock ();
                }
        }
 
@@ -4114,7 +4061,7 @@ namespace Mono.CSharp {
 
                        // Avoid creating libraries that reference the internal
                        // mcs NullType:
-                       Type t = expr.Type;
+                       TypeSpec t = expr.Type;
                        if (t == TypeManager.null_type)
                                t = TypeManager.object_type;
                        
@@ -4122,7 +4069,7 @@ namespace Mono.CSharp {
                        temp.Resolve (ec);
 
                        if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) {
-                               Type monitor_type = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Monitor", MemberKind.Class, true);
+                               TypeSpec monitor_type = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Monitor", MemberKind.Class, true);
                                TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod (
                                        monitor_type, "Enter", loc, TypeManager.object_type);
                                TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod (
@@ -4134,11 +4081,9 @@ namespace Mono.CSharp {
                
                protected override void EmitPreTryBody (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        temp.EmitAssign (ec, expr);
                        temp.Emit (ec);
-                       ig.Emit (OpCodes.Call, (MethodInfo) TypeManager.void_monitor_enter_object.MetaInfo);
+                       ec.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
                }
 
                protected override void EmitTryBody (EmitContext ec)
@@ -4149,16 +4094,9 @@ namespace Mono.CSharp {
                protected override void EmitFinallyBody (EmitContext ec)
                {
                        temp.Emit (ec);
-                       ec.ig.Emit (OpCodes.Call, (MethodInfo) TypeManager.void_monitor_exit_object.MetaInfo);
+                       ec.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-                       temp.MutateHoistedGenericType (storey);
-                       Statement.MutateHoistedGenericType (storey);
-               }
-               
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Lock target = (Lock) t;
@@ -4171,10 +4109,11 @@ namespace Mono.CSharp {
        public class Unchecked : Statement {
                public Block Block;
                
-               public Unchecked (Block b)
+               public Unchecked (Block b, Location loc)
                {
                        Block = b;
                        b.Unchecked = true;
+                       this.loc = loc;
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4189,11 +4128,6 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unchecked target = (Unchecked) t;
@@ -4205,10 +4139,11 @@ namespace Mono.CSharp {
        public class Checked : Statement {
                public Block Block;
                
-               public Checked (Block b)
+               public Checked (Block b, Location loc)
                {
                        Block = b;
                        b.Unchecked = false;
+                       this.loc = loc;
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4223,11 +4158,6 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Checked target = (Checked) t;
@@ -4239,11 +4169,11 @@ namespace Mono.CSharp {
        public class Unsafe : Statement {
                public Block Block;
 
-               public Unsafe (Block b)
+               public Unsafe (Block b, Location loc)
                {
                        Block = b;
                        Block.Unsafe = true;
-                       loc = b.StartLocation;
+                       this.loc = loc;
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4260,11 +4190,6 @@ namespace Mono.CSharp {
                        Block.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unsafe target = (Unsafe) t;
@@ -4276,11 +4201,11 @@ namespace Mono.CSharp {
        // 
        // Fixed statement
        //
-       class Fixed : Statement {
+       public class Fixed : Statement {
                Expression type;
                List<KeyValuePair<LocalInfo, Expression>> declarators;
                Statement statement;
-               Type expr_type;
+               TypeSpec expr_type;
                Emitter[] data;
                bool has_ret;
 
@@ -4315,8 +4240,8 @@ namespace Mono.CSharp {
 
                        public override void EmitExit (EmitContext ec)
                        {
-                               ec.ig.Emit (OpCodes.Ldc_I4_0);
-                               ec.ig.Emit (OpCodes.Conv_U);
+                               ec.Emit (OpCodes.Ldc_I4_0);
+                               ec.Emit (OpCodes.Conv_U);
                                vi.EmitAssign (ec);
                        }
                }
@@ -4353,19 +4278,19 @@ namespace Mono.CSharp {
 
                                // TODO: Should use Binary::Add
                                pinned_string.Emit (ec);
-                               ec.ig.Emit (OpCodes.Conv_I);
+                               ec.Emit (OpCodes.Conv_I);
 
-                               PropertyExpr pe = new PropertyExpr (pinned_string.VariableType, TypeManager.int_get_offset_to_string_data, pinned_string.Location);
+                               PropertyExpr pe = new PropertyExpr (TypeManager.int_get_offset_to_string_data, pinned_string.Location);
                                //pe.InstanceExpression = pinned_string;
                                pe.Resolve (new ResolveContext (ec.MemberContext)).Emit (ec);
 
-                               ec.ig.Emit (OpCodes.Add);
+                               ec.Emit (OpCodes.Add);
                                vi.EmitAssign (ec);
                        }
 
                        public override void EmitExit (EmitContext ec)
                        {
-                               ec.ig.Emit (OpCodes.Ldnull);
+                               ec.Emit (OpCodes.Ldnull);
                                pinned_string.EmitAssign (ec);
                        }
                }
@@ -4441,7 +4366,7 @@ namespace Mono.CSharp {
                                // Case 2: Array
                                //
                                if (e.Type.IsArray){
-                                       Type array_type = TypeManager.GetElementType (e.Type);
+                                       TypeSpec array_type = TypeManager.GetElementType (e.Type);
                                        
                                        //
                                        // Provided that array_type is unmanaged,
@@ -4467,7 +4392,7 @@ namespace Mono.CSharp {
                                                new Binary (Binary.Operator.Equality, e, new NullLiteral (loc), loc),
                                                new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc), loc), loc)),
                                                        new NullPointer (loc),
-                                                       converted);
+                                                       converted, loc);
 
                                        converted = converted.Resolve (ec);                                     
 
@@ -4536,12 +4461,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       // Fixed statement cannot be used inside anonymous methods or lambdas
-                       throw new NotSupportedException ();
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Fixed target = (Fixed) t;
@@ -4563,7 +4482,7 @@ namespace Mono.CSharp {
                public Block  VarBlock;
 
                Expression type_expr;
-               Type type;
+               TypeSpec type;
                
                public Catch (Expression type, string name, Block block, Block var_block, Location l)
                {
@@ -4574,7 +4493,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public Type CatchType {
+               public TypeSpec CatchType {
                        get {
                                return type;
                        }
@@ -4588,12 +4507,10 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        if (CatchType != null)
-                               ig.BeginCatchBlock (CatchType);
+                               ec.BeginCatchBlock (CatchType);
                        else
-                               ig.BeginCatchBlock (TypeManager.object_type);
+                               ec.BeginCatchBlock (TypeManager.object_type);
 
                        if (VarBlock != null)
                                VarBlock.Emit (ec);
@@ -4605,7 +4522,7 @@ namespace Mono.CSharp {
                                
                                // Only to make verifier happy
                                if (TypeManager.IsGenericParameter (lvr.Type))
-                                       ig.Emit (OpCodes.Unbox_Any, lvr.Type);
+                                       ec.Emit (OpCodes.Unbox_Any, lvr.Type);
 
                                Expression source;
                                if (lvr.IsHoisted) {
@@ -4619,7 +4536,7 @@ namespace Mono.CSharp {
 
                                lvr.EmitAssign (ec, source, false, false);
                        } else
-                               ig.Emit (OpCodes.Pop);
+                               ec.Emit (OpCodes.Pop);
 
                        Block.Emit (ec);
                }
@@ -4653,15 +4570,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       if (type != null)
-                               type = storey.MutateType (type);
-                       if (VarBlock != null)
-                               VarBlock.MutateHoistedGenericType (storey);
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Catch target = (Catch) t;
@@ -4722,12 +4630,6 @@ namespace Mono.CSharp {
                        fini.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       stmt.MutateHoistedGenericType (storey);
-                       fini.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        TryFinally target = (TryFinally) t;
@@ -4768,7 +4670,7 @@ namespace Mono.CSharp {
                        if (!Block.Resolve (ec))
                                ok = false;
 
-                       Type[] prev_catches = new Type [Specific.Count];
+                       TypeSpec[] prev_catches = new TypeSpec [Specific.Count];
                        int last_index = 0;
                        foreach (Catch c in Specific){
                                ec.CurrentBranching.CreateSibling (c.Block, FlowBranching.SiblingType.Catch);
@@ -4786,7 +4688,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               Type resolved_type = c.CatchType;
+                               TypeSpec resolved_type = c.CatchType;
                                for (int ii = 0; ii < last_index; ++ii) {
                                        if (resolved_type == prev_catches [ii] || TypeManager.IsSubclassOf (resolved_type, prev_catches [ii])) {
                                                ec.Report.Error (160, c.loc,
@@ -4831,10 +4733,8 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        if (!inside_try_finally)
-                               ig.BeginExceptionBlock ();
+                               ec.BeginExceptionBlock ();
 
                        Block.Emit (ec);
 
@@ -4845,19 +4745,7 @@ namespace Mono.CSharp {
                                General.Emit (ec);
 
                        if (!inside_try_finally)
-                               ig.EndExceptionBlock ();
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-
-                       if (General != null)
-                               General.MutateHoistedGenericType (storey);
-                       if (Specific != null) {
-                               foreach (Catch c in Specific)
-                                       c.MutateHoistedGenericType (storey);
-                       }
+                               ec.EndExceptionBlock ();
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -4876,54 +4764,87 @@ namespace Mono.CSharp {
        }
 
        // FIXME: Why is it almost exact copy of Using ??
-       public class UsingTemporary : ExceptionStatement {
-               TemporaryVariable local_copy;
-               public Statement Statement;
+       public class UsingTemporary : ExceptionStatement
+       {
+               protected TemporaryVariable local_copy;
+               Statement statement;
                Expression expr;
-               Type expr_type;
+               protected Statement dispose_call;
 
                public UsingTemporary (Expression expr, Statement stmt, Location l)
                {
                        this.expr = expr;
-                       Statement = stmt;
+                       statement = stmt;
                        loc = l;
                }
 
-               public override bool Resolve (BlockContext ec)
+               #region Properties
+               public Expression Expression {
+                       get {
+                               return expr;
+                       }
+               }
+
+               public Statement Statement {
+                       get {
+                               return statement;
+                       }
+               }
+
+               #endregion
+
+               protected virtual bool DoResolve (BlockContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return false;
 
-                       expr_type = expr.Type;
-
-                       if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type) &&
+                       if (!expr.Type.ImplementsInterface (TypeManager.idisposable_type) &&
                                Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
-                               if (!TypeManager.IsDynamicType (expr_type)) {
+                               if (expr.Type != InternalType.Dynamic) {
                                        Using.Error_IsNotConvertibleToIDisposable (ec, expr);
                                        return false;
                                }
 
                                expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.idisposable_type, loc);
-                               expr_type = expr.Type;
                        }
 
+                       var expr_type = expr.Type;
+
                        local_copy = new TemporaryVariable (expr_type, loc);
                        local_copy.Resolve (ec);
 
+                       if (TypeManager.void_dispose_void == null) {
+                               TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
+                                       TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes);
+                       }
+
+                       var dispose_mg = MethodGroupExpr.CreatePredefined (TypeManager.void_dispose_void, TypeManager.idisposable_type, loc);
+                       dispose_mg.InstanceExpression = TypeManager.IsNullableType (expr_type) ?
+                               new Cast (new TypeExpression (TypeManager.idisposable_type, loc), local_copy, loc).Resolve (ec) :
+                               local_copy;
+
+                       dispose_call = new StatementExpression (new Invocation (dispose_mg, null));
+
+                       // Add conditional call when disposing possible null variable
+                       if (!expr_type.IsStruct || TypeManager.IsNullableType (expr_type))
+                               dispose_call = new If (new Binary (Binary.Operator.Inequality, local_copy, new NullLiteral (loc), loc), dispose_call, loc);
+
+                       return dispose_call.Resolve (ec);
+               }
+
+               public override bool Resolve (BlockContext ec)
+               {
+                       bool ok = DoResolve (ec);
+
                        ec.StartFlowBranching (this);
 
-                       bool ok = Statement.Resolve (ec);
+                       ok &= statement.Resolve (ec);
 
                        ec.EndFlowBranching ();
 
                        ok &= base.Resolve (ec);
 
-                       if (TypeManager.void_dispose_void == null) {
-                               TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
-                                       TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes);
-                       }
-
                        return ok;
                }
 
@@ -4934,56 +4855,12 @@ namespace Mono.CSharp {
 
                protected override void EmitTryBody (EmitContext ec)
                {
-                       Statement.Emit (ec);
+                       statement.Emit (ec);
                }
 
                protected override void EmitFinallyBody (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       if (!TypeManager.IsStruct (expr_type)) {
-                               Label skip = ig.DefineLabel ();
-                               local_copy.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, skip);
-                               local_copy.Emit (ec);
-                               ig.Emit (OpCodes.Callvirt, (MethodInfo) TypeManager.void_dispose_void.MetaInfo);
-                               ig.MarkLabel (skip);
-                               return;
-                       }
-
-                       Expression ml = Expression.MemberLookup (RootContext.ToplevelTypes.Compiler,
-                               ec.CurrentType, TypeManager.idisposable_type, expr_type,
-                               "Dispose", Location.Null);
-
-                       if (!(ml is MethodGroupExpr)) {
-                               local_copy.Emit (ec);
-                               ig.Emit (OpCodes.Box, expr_type);
-                               ig.Emit (OpCodes.Callvirt, (MethodInfo) TypeManager.void_dispose_void.MetaInfo);
-                               return;
-                       }
-
-                       MethodSpec mi = null;
-
-                       foreach (var mk in ((MethodGroupExpr) ml).Methods) {
-                               if (mk.Parameters.IsEmpty) {
-                                       mi = mk;
-                                       break;
-                               }
-                       }
-
-                       if (mi == null) {
-                               ec.Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
-                               return;
-                       }
-
-                       local_copy.AddressOf (ec, AddressOp.Load);
-                       ig.Emit (OpCodes.Call, (MethodInfo) mi.MetaInfo);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr_type = storey.MutateType (expr_type);
-                       local_copy.MutateHoistedGenericType (storey);
-                       Statement.MutateHoistedGenericType (storey);
+                       dispose_call.Emit (ec);
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -4991,7 +4868,7 @@ namespace Mono.CSharp {
                        UsingTemporary target = (UsingTemporary) t;
 
                        target.expr = expr.Clone (clonectx);
-                       target.Statement = Statement.Clone (clonectx);
+                       target.statement = statement.Clone (clonectx);
                }
        }
 
@@ -5033,26 +4910,18 @@ namespace Mono.CSharp {
 
                protected override void EmitFinallyBody (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label skip = ig.DefineLabel ();
+                       Label skip = ec.DefineLabel ();
 
                        bool emit_null_check = !TypeManager.IsValueType (var.Type);
                        if (emit_null_check) {
                                var.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, skip);
+                               ec.Emit (OpCodes.Brfalse, skip);
                        }
 
-                       Invocation.EmitCall (ec, false, var, TypeManager.void_dispose_void, null, loc);
+                       Invocation.EmitCall (ec, var, TypeManager.void_dispose_void, null, loc);
 
                        if (emit_null_check)
-                               ig.MarkLabel (skip);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       assign.MutateHoistedGenericType (storey);
-                       var.MutateHoistedGenericType (storey);
-                       stmt.MutateHoistedGenericType (storey);
+                               ec.MarkLabel (skip);
                }
 
                public override bool Resolve (BlockContext ec)
@@ -5070,7 +4939,7 @@ namespace Mono.CSharp {
 
                        if (TypeManager.void_dispose_void == null) {
                                TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
-                                       TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes);
+                                       TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes);
                        }
 
                        return ok;
@@ -5083,14 +4952,13 @@ namespace Mono.CSharp {
                        if (assign == null)
                                return false;
 
-                       if (assign.Type == TypeManager.idisposable_type ||
-                               TypeManager.ImplementsInterface (assign.Type, TypeManager.idisposable_type)) {
+                       if (assign.Type == TypeManager.idisposable_type || assign.Type.ImplementsInterface (TypeManager.idisposable_type)) {
                                return true;
                        }
 
                        Expression e = Convert.ImplicitConversionStandard (ec, assign, TypeManager.idisposable_type, var.Location);
                        if (e == null) {
-                               if (TypeManager.IsDynamicType (assign.Type)) {
+                               if (assign.Type == InternalType.Dynamic) {
                                        e = Convert.ImplicitConversionRequired (ec, assign, TypeManager.idisposable_type, loc);
                                        var = new TemporaryVariable (e.Type, loc);
                                        assign = new SimpleAssign (var, e, loc).ResolveStatement (ec);
@@ -5200,7 +5068,7 @@ namespace Mono.CSharp {
                                        list.Add (new Argument (counter [i]));
                                }
 
-                               access = new ElementAccess (copy, list).Resolve (ec);
+                               access = new ElementAccess (copy, list, loc).Resolve (ec);
                                if (access == null)
                                        return false;
 
@@ -5243,8 +5111,6 @@ namespace Mono.CSharp {
 
                        protected override void DoEmit (EmitContext ec)
                        {
-                               ILGenerator ig = ec.ig;
-
                                copy.EmitAssign (ec, for_each.expr);
 
                                int rank = length_exprs.Length;
@@ -5252,8 +5118,8 @@ namespace Mono.CSharp {
                                Label[] loop = new Label [rank];
 
                                for (int i = 0; i < rank; i++) {
-                                       test [i] = ig.DefineLabel ();
-                                       loop [i] = ig.DefineLabel ();
+                                       test [i] = ec.DefineLabel ();
+                                       loop [i] = ec.DefineLabel ();
 
                                        if (lengths != null)
                                                lengths [i].EmitAssign (ec, length_exprs [i]);
@@ -5263,20 +5129,20 @@ namespace Mono.CSharp {
                                for (int i = 0; i < rank; i++) {
                                        counter [i].EmitAssign (ec, zero);
 
-                                       ig.Emit (OpCodes.Br, test [i]);
-                                       ig.MarkLabel (loop [i]);
+                                       ec.Emit (OpCodes.Br, test [i]);
+                                       ec.MarkLabel (loop [i]);
                                }
 
                                ((IAssignMethod) for_each.variable).EmitAssign (ec, conv, false, false);
 
                                statement.Emit (ec);
 
-                               ig.MarkLabel (ec.LoopBegin);
+                               ec.MarkLabel (ec.LoopBegin);
 
                                for (int i = rank - 1; i >= 0; i--){
                                        counter [i].EmitIncrement (ec);
 
-                                       ig.MarkLabel (test [i]);
+                                       ec.MarkLabel (test [i]);
                                        counter [i].Emit (ec);
 
                                        if (lengths != null)
@@ -5284,38 +5150,23 @@ namespace Mono.CSharp {
                                        else
                                                length_exprs [i].Emit (ec);
 
-                                       ig.Emit (OpCodes.Blt, loop [i]);
+                                       ec.Emit (OpCodes.Blt, loop [i]);
                                }
 
-                               ig.MarkLabel (ec.LoopEnd);
-                       }
-
-                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-                       {
-                               for_each.expr.MutateHoistedGenericType (storey);
-
-                               copy.MutateHoistedGenericType (storey);
-                               conv.MutateHoistedGenericType (storey);
-                               statement.MutateHoistedGenericType (storey);
-
-                               for (int i = 0; i < counter.Length; i++) {
-                                       counter [i].MutateHoistedGenericType (storey);
-                                       if (lengths != null)
-                                               lengths [i].MutateHoistedGenericType (storey);
-                               }
+                               ec.MarkLabel (ec.LoopEnd);
                        }
                }
 
-               sealed class CollectionForeach : Statement
+               sealed class CollectionForeach : Statement, MethodGroupExpr.IErrorHandler
                {
-                       class CollectionForeachStatement : Statement
+                       class Body : Statement
                        {
-                               Type type;
+                               TypeSpec type;
                                Expression variable, current, conv;
                                Statement statement;
                                Assign assign;
 
-                               public CollectionForeachStatement (Type type, Expression variable,
+                               public Body (TypeSpec type, Expression variable,
                                                                   Expression current, Statement statement,
                                                                   Location loc)
                                {
@@ -5356,28 +5207,61 @@ namespace Mono.CSharp {
                                        assign.EmitStatement (ec);
                                        statement.Emit (ec);
                                }
+                       }
+
+                       class Dispose : UsingTemporary
+                       {
+                               LocalTemporary dispose;
+
+                               public Dispose (TemporaryVariable variable, LocalTemporary dispose, Expression expr, Statement statement, Location loc)
+                                       : base (expr, statement, loc)
+                               {
+                                       base.local_copy = variable;
+                                       this.dispose = dispose;
+                               }
+
+                               protected override bool DoResolve (BlockContext ec)
+                               {
+                                       if (TypeManager.void_dispose_void == null) {
+                                               TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
+                                                       TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes);
+                                       }
+
+                                       Expression dispose_var = (Expression) dispose ?? local_copy;
+
+                                       var dispose_mg = MethodGroupExpr.CreatePredefined (TypeManager.void_dispose_void, TypeManager.idisposable_type, loc);
+                                       dispose_mg.InstanceExpression = dispose_var;
+
+                                       dispose_call = new StatementExpression (new Invocation (dispose_mg, null));
+
+                                       if (!dispose_var.Type.IsStruct)
+                                               dispose_call = new If (new Binary (Binary.Operator.Inequality, dispose_var, new NullLiteral (loc), loc), dispose_call, loc);
+
+                                       return dispose_call.Resolve (ec);
+                               }
 
-                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                               protected override void EmitFinallyBody (EmitContext ec)
                                {
-                                       assign.MutateHoistedGenericType (storey);
-                                       statement.MutateHoistedGenericType (storey);
+                                       Label call_dispose = ec.DefineLabel ();
+                                       if (dispose != null) {
+                                               local_copy.Emit (ec, false);
+                                               ec.Emit (OpCodes.Isinst, dispose.Type);
+                                               dispose.Store (ec);
+                                       }
+
+                                       base.EmitFinallyBody (ec);
+
+                                       if (dispose != null) {
+                                               ec.MarkLabel (call_dispose);
+                                               dispose.Release (ec);
+                                       }
                                }
                        }
 
                        Expression variable, expr;
                        Statement statement;
-
-                       TemporaryVariable enumerator;
-                       Expression init;
-                       Statement loop;
-                       Statement wrapper;
-
-                       MethodGroupExpr get_enumerator;
-                       PropertyExpr get_current;
-                       MethodSpec move_next;
                        Expression var_type;
-                       Type enumerator_type;
-                       bool enumerator_found;
+                       ExpressionStatement init;
 
                        public CollectionForeach (Expression var_type, Expression var,
                                                  Expression expr, Statement stmt, Location l)
@@ -5394,452 +5278,215 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
-                       bool GetEnumeratorFilter (ResolveContext ec, MethodSpec mi)
+                       void Error_WrongEnumerator (ResolveContext rc, MethodSpec enumerator)
                        {
-                               Type return_type = mi.ReturnType;
+                               rc.Report.SymbolRelatedToPreviousError (enumerator);
+                               rc.Report.Error (202, loc,
+                                       "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property",
+                                               enumerator.ReturnType.GetSignatureForError (), enumerator.GetSignatureForError ());
+                       }
 
+                       MethodGroupExpr ResolveGetEnumerator (ResolveContext rc)
+                       {
                                //
-                               // Ok, we can access it, now make sure that we can do something
-                               // with this `GetEnumerator'
+                               // Option 1: Try to match by name GetEnumerator first
                                //
-
-                               if (return_type == TypeManager.ienumerator_type ||
-                                       TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type)) {
-                                       //
-                                       // If it is not an interface, lets try to find the methods ourselves.
-                                       // For example, if we have:
-                                       // public class Foo : IEnumerator { public bool MoveNext () {} public int Current { get {}}}
-                                       // We can avoid the iface call. This is a runtime perf boost.
-                                       // even bigger if we have a ValueType, because we avoid the cost
-                                       // of boxing.
-                                       //
-                                       // We have to make sure that both methods exist for us to take
-                                       // this path. If one of the methods does not exist, we will just
-                                       // use the interface. Sadly, this complex if statement is the only
-                                       // way I could do this without a goto
-                                       //
-
-                                       if (TypeManager.bool_movenext_void == null) {
-                                               TypeManager.bool_movenext_void = TypeManager.GetPredefinedMethod (
-                                                       TypeManager.ienumerator_type, "MoveNext", loc, Type.EmptyTypes);
+                               var mexpr = Expression.MemberLookup (rc.Compiler, rc.CurrentType, null, expr.Type, "GetEnumerator", -1,
+                                       MemberKind.All, BindingRestriction.DefaultMemberLookup | BindingRestriction.AccessibleOnly, loc);
+
+                               var mg = mexpr as MethodGroupExpr;
+                               if (mg != null) {
+                                       mg.InstanceExpression = expr;
+                                       mg.CustomErrorHandler = this;
+                                       Arguments args = new Arguments (0);
+                                       mg = mg.OverloadResolve (rc, ref args, false, loc);
+
+                                       if (mg != null && args.Count == 0 && !mg.BestCandidate.IsStatic && mg.BestCandidate.IsPublic) {
+                                               return mg;
                                        }
+                               }
 
-                                       if (TypeManager.ienumerator_getcurrent == null) {
-                                               TypeManager.ienumerator_getcurrent = TypeManager.GetPredefinedProperty (
-                                                       TypeManager.ienumerator_type, "Current", loc, TypeManager.object_type);
-                                       }
+                               //
+                               // Option 2: Try to match using IEnumerable interfaces with preference of generic version
+                               //
+                               TypeSpec iface_candidate = null;
+                               for (TypeSpec t = expr.Type; t != null && t != TypeManager.object_type; t = t.BaseType) {
+                                       var ifaces = t.Interfaces;
+                                       if (ifaces != null) {
+                                               foreach (var iface in ifaces) {
+                                                       if (TypeManager.generic_ienumerable_type != null && iface.MemberDefinition == TypeManager.generic_ienumerable_type.MemberDefinition) {
+                                                               if (iface_candidate != null && iface_candidate != TypeManager.ienumerable_type) {
+                                                                       rc.Report.SymbolRelatedToPreviousError (expr.Type);
+                                                                       rc.Report.Error(1640, loc,
+                                                                               "foreach statement cannot operate on variables of type `{0}' because it contains multiple implementation of `{1}'. Try casting to a specific implementation",
+                                                                               expr.Type.GetSignatureForError (), TypeManager.generic_ienumerable_type.GetSignatureForError ());
+
+                                                                       return null;
+                                                               }
+
+                                                               iface_candidate = iface;
+                                                               continue;
+                                                       }
 
-                                       //
-                                       // Prefer a generic enumerator over a non-generic one.
-                                       //
-                                       if (return_type.IsInterface && TypeManager.IsGenericType (return_type)) {
-                                               enumerator_type = return_type;
-                                               if (!FetchGetCurrent (ec, return_type))
-                                                       get_current = new PropertyExpr (
-                                                               ec.CurrentType, TypeManager.ienumerator_getcurrent, loc);
-                                               if (!FetchMoveNext (return_type))
-                                                       move_next = TypeManager.bool_movenext_void;
-                                               return true;
+                                                       if (iface == TypeManager.ienumerable_type && iface_candidate == null) {
+                                                               iface_candidate = iface;
+                                                       }
+                                               }
                                        }
+                               }
 
-                                       if (return_type.IsInterface ||
-                                           !FetchMoveNext (return_type) ||
-                                           !FetchGetCurrent (ec, return_type)) {
-                                               enumerator_type = return_type;
-                                               move_next = TypeManager.bool_movenext_void;
-                                               get_current = new PropertyExpr (
-                                                       ec.CurrentType, TypeManager.ienumerator_getcurrent, loc);
-                                               return true;
-                                       }
-                               } else {
-                                       //
-                                       // Ok, so they dont return an IEnumerable, we will have to
-                                       // find if they support the GetEnumerator pattern.
-                                       //
+                               if (iface_candidate == null) {
+                                       rc.Report.Error (1579, loc,
+                                               "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `{1}' or is not accessible",
+                                               expr.Type.GetSignatureForError (), "GetEnumerator");
 
-                                       if (TypeManager.HasElementType (return_type) || !FetchMoveNext (return_type) || !FetchGetCurrent (ec, return_type)) {
-                                               ec.Report.Error (202, loc, "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property",
-                                                       TypeManager.CSharpName (return_type), TypeManager.CSharpSignature (mi));
-                                               return false;
-                                       }
+                                       return null;
                                }
 
-                               enumerator_type = return_type;
+                               var method = TypeManager.GetPredefinedMethod (iface_candidate, 
+                                       MemberFilter.Method ("GetEnumerator", 0, ParametersCompiled.EmptyReadOnlyParameters, null), loc);
 
-                               return true;
+                               if (method == null)
+                                       return null;
+
+                               mg = MethodGroupExpr.CreatePredefined (method, expr.Type, loc);
+                               mg.InstanceExpression = expr;
+                               return mg;
                        }
 
-                       //
-                       // Retrieves a `public bool MoveNext ()' method from the Type `t'
-                       //
-                       bool FetchMoveNext (Type t)
+                       MethodGroupExpr ResolveMoveNext (ResolveContext rc, MethodSpec enumerator)
                        {
-                               MemberInfo[] move_next_list = TypeManager.MemberLookup (null, null, t,
-                                       MemberTypes.Method,
-                                       BindingFlags.Public | BindingFlags.Instance,
-                                       "MoveNext", null);
-
-                               if (move_next_list == null)
-                                       return false;
+                               var ms = MemberCache.FindMember (enumerator.ReturnType,
+                                       MemberFilter.Method ("MoveNext", 0, ParametersCompiled.EmptyReadOnlyParameters, TypeManager.bool_type),
+                                       BindingRestriction.InstanceOnly) as MethodSpec;
 
-                               foreach (MemberInfo m in move_next_list){
-                                       MethodInfo mi = (MethodInfo) m;
-                               
-                                       if ((TypeManager.GetParameterData (mi).Count == 0) &&
-                                           TypeManager.TypeToCoreType (mi.ReturnType) == TypeManager.bool_type) {
-                                               move_next = Import.CreateMethod (mi);
-                                               return true;
-                                       }
+                               if (ms == null || !ms.IsPublic) {
+                                       Error_WrongEnumerator (rc, enumerator);
+                                       return null;
                                }
 
-                               return false;
-                       }
-               
-                       //
-                       // Retrieves a `public T get_Current ()' method from the Type `t'
-                       //
-                       bool FetchGetCurrent (ResolveContext ec, Type t)
-                       {
-                               PropertyExpr pe = Expression.MemberLookup (ec.Compiler,
-                                       ec.CurrentType, t, "Current", MemberTypes.Property,
-                                       Expression.AllBindingFlags, loc) as PropertyExpr;
-                               if (pe == null)
-                                       return false;
-
-                               get_current = pe;
-                               return true;
+                               return MethodGroupExpr.CreatePredefined (ms, enumerator.ReturnType, loc);
                        }
 
-                       void Error_Enumerator (BlockContext ec)
+                       PropertySpec ResolveCurrent (ResolveContext rc, MethodSpec enumerator)
                        {
-                               if (enumerator_found) {
-                                       return;
+                               var ps = MemberCache.FindMember (enumerator.ReturnType,
+                                       MemberFilter.Property ("Current", null),
+                                       BindingRestriction.InstanceOnly) as PropertySpec;
+
+                               if (ps == null || !ps.IsPublic) {
+                                       Error_WrongEnumerator (rc, enumerator);
+                                       return null;
                                }
 
-                           ec.Report.Error (1579, loc,
-                                       "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `GetEnumerator' or is not accessible",
-                                       TypeManager.CSharpName (expr.Type));
+                               return ps;
                        }
 
-                       bool IsOverride (MethodSpec ms)
+                       public override bool Resolve (BlockContext ec)
                        {
-                               MethodInfo m = (MethodInfo) ms.MetaInfo;
-                               m = (MethodInfo) TypeManager.DropGenericMethodArguments (m);
-
-                               if (!m.IsVirtual || ((m.Attributes & MethodAttributes.NewSlot) != 0))
-                                       return false;
-                               if (m is MethodBuilder)
-                                       return true;
-
-                               MethodInfo base_method = m.GetBaseDefinition ();
-                               return base_method != m;
-                       }
+                               bool is_dynamic = expr.Type == InternalType.Dynamic;
+                               if (is_dynamic)
+                                       expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc);
 
-                       bool TryType (ResolveContext ec, Type t)
-                       {
-                               MethodGroupExpr mg = Expression.MemberLookup (ec.Compiler,
-                                       ec.CurrentType, t, "GetEnumerator", MemberTypes.Method,
-                                       Expression.AllBindingFlags, loc) as MethodGroupExpr;
-                               if (mg == null)
+                               var get_enumerator_mg = ResolveGetEnumerator (ec);
+                               if (get_enumerator_mg == null) {
                                        return false;
-
-                               MethodSpec result = null;
-                               MethodSpec tmp_move_next = null;
-                               PropertyExpr tmp_get_cur = null;
-                               Type tmp_enumerator_type = enumerator_type;
-                               foreach (var mi in mg.Methods) {
-                                       if (!mi.Parameters.IsEmpty)
-                                               continue;
-                       
-                                       // Check whether GetEnumerator is public
-                                       if ((mi.MetaInfo.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
-                                               continue;
-
-                                       if (IsOverride (mi))
-                                               continue;
-
-                                       enumerator_found = true;
-
-                                       if (!GetEnumeratorFilter (ec, mi))
-                                               continue;
-
-                                       if (result != null) {
-                                               if (TypeManager.IsGenericType (result.ReturnType)) {
-                                                       if (!TypeManager.IsGenericType (mi.ReturnType))
-                                                               continue;
-
-                                                       MethodBase mb = TypeManager.DropGenericMethodArguments (mi);
-                                                       ec.Report.SymbolRelatedToPreviousError (t);
-                                                       ec.Report.Error(1640, loc, "foreach statement cannot operate on variables of type `{0}' " +
-                                                                    "because it contains multiple implementation of `{1}'. Try casting to a specific implementation",
-                                                                    TypeManager.CSharpName (t), TypeManager.CSharpSignature (mb));
-                                                       return false;
-                                               }
-
-                                               // Always prefer generics enumerators
-                                               if (!TypeManager.IsGenericType (mi.ReturnType)) {
-                                                       if (TypeManager.ImplementsInterface (mi.DeclaringType, result.DeclaringType) ||
-                                                           TypeManager.ImplementsInterface (result.DeclaringType, mi.DeclaringType))
-                                                               continue;
-
-                                                       ec.Report.SymbolRelatedToPreviousError (result.MetaInfo);
-                                                       ec.Report.SymbolRelatedToPreviousError (mi.MetaInfo);
-                                                       ec.Report.Warning (278, 2, loc, "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'",
-                                                                       TypeManager.CSharpName (t), "enumerable", TypeManager.CSharpSignature (result.MetaInfo), TypeManager.CSharpSignature (mi.MetaInfo));
-                                                       return false;
-                                               }
-                                       }
-                                       result = mi;
-                                       tmp_move_next = move_next;
-                                       tmp_get_cur = get_current;
-                                       tmp_enumerator_type = enumerator_type;
-                                       if (mi.DeclaringType == t)
-                                               break;
                                }
 
-                               if (result != null) {
-                                       move_next = tmp_move_next;
-                                       get_current = tmp_get_cur;
-                                       enumerator_type = tmp_enumerator_type;
-                                       var mi = new [] { result };
-                                       get_enumerator = new MethodGroupExpr (mi, enumerator_type, loc);
-
-                                       if (t != expr.Type) {
-                                               expr = Convert.ExplicitConversion (
-                                                       ec, expr, t, loc);
-                                               if (expr == null)
-                                                       throw new InternalErrorException ();
-                                       }
-
-                                       get_enumerator.InstanceExpression = expr;
-                                       get_enumerator.IsBase = t != expr.Type;
+                               var get_enumerator = get_enumerator_mg.BestCandidate;
+                               var enumerator = new TemporaryVariable (get_enumerator.ReturnType, loc);
+                               enumerator.Resolve (ec);
 
-                                       return true;
+                               // Prepare bool MoveNext ()
+                               var move_next_mg = ResolveMoveNext (ec, get_enumerator);
+                               if (move_next_mg == null) {
+                                       return false;
                                }
 
-                               return false;
-                       }
-
-                       bool ProbeCollectionType (ResolveContext ec, Type t)
-                       {
-                               int errors = ec.Report.Errors;
-                               for (Type tt = t; tt != null && tt != TypeManager.object_type;){
-                                       if (TryType (ec, tt))
-                                               return true;
-                                       tt = tt.BaseType;
-                               }
+                               move_next_mg.InstanceExpression = enumerator;
 
-                               if (ec.Report.Errors > errors)
+                               // Prepare ~T~ Current { get; }
+                               var current_prop = ResolveCurrent (ec, get_enumerator);
+                               if (current_prop == null) {
                                        return false;
-
-                               //
-                               // Now try to find the method in the interfaces
-                               //
-                               Type [] ifaces = TypeManager.GetInterfaces (t);
-                               foreach (Type i in ifaces){
-                                       if (TryType (ec, i))
-                                               return true;
                                }
 
-                               return false;
-                       }
-
-                       public override bool Resolve (BlockContext ec)
-                       {
-                               enumerator_type = TypeManager.ienumerator_type;
-
-                               bool is_dynamic = TypeManager.IsDynamicType (expr.Type);
-                               if (is_dynamic)
-                                       expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc);
-                               
-                               if (!ProbeCollectionType (ec, expr.Type)) {
-                                       Error_Enumerator (ec);
+                               var current_pe = new PropertyExpr (current_prop, loc) { InstanceExpression = enumerator }.Resolve (ec);
+                               if (current_pe == null)
                                        return false;
-                               }
 
                                VarExpr ve = var_type as VarExpr;
                                if (ve != null) {
                                        // Infer implicitly typed local variable from foreach enumerable type
-                                       var_type = new TypeExpression (
-                                               is_dynamic ? InternalType.Dynamic : get_current.PropertyInfo.PropertyType,
-                                               var_type.Location);
+                                       var_type = new TypeExpression (current_pe.Type, var_type.Location);
                                }
 
                                var_type = var_type.ResolveAsTypeTerminal (ec, false);
                                if (var_type == null)
                                        return false;
-                                                               
-                               enumerator = new TemporaryVariable (enumerator_type, loc);
-                               enumerator.Resolve (ec);
-
-                               init = new Invocation (get_enumerator, null);
-                               init = init.Resolve (ec);
-                               if (init == null)
-                                       return false;
-
-                               Expression move_next_expr;
-                               {
-                                       var mi = new [] { move_next };
-                                       MethodGroupExpr mg = new MethodGroupExpr (mi, var_type.Type, loc);
-                                       mg.InstanceExpression = enumerator;
-
-                                       move_next_expr = new Invocation (mg, null);
-                               }
-
-                               get_current.InstanceExpression = enumerator;
 
-                               Statement block = new CollectionForeachStatement (
-                                       var_type.Type, variable, get_current, statement, loc);
+                               var init = new Invocation (get_enumerator_mg, null);
+                               init.Resolve (ec);
 
-                               loop = new While (new BooleanExpression (move_next_expr), block, loc);
+                               statement = new While (new BooleanExpression (new Invocation (move_next_mg, null)),
+                                       new Body (var_type.Type, variable, current_pe, statement, loc), loc);
 
+                               var enum_type = enumerator.Type;
 
-                               bool implements_idisposable = TypeManager.ImplementsInterface (enumerator_type, TypeManager.idisposable_type);
-                               if (implements_idisposable || !enumerator_type.IsSealed) {
-                                       wrapper = new DisposableWrapper (this, implements_idisposable);
+                               //
+                               // Add Dispose method call when enumerator can be IDisposable
+                               //
+                               if (!enumerator.Type.ImplementsInterface (TypeManager.idisposable_type)) {
+                                       if (!enum_type.IsSealed && !TypeManager.IsValueType (enum_type)) {
+                                               //
+                                               // Runtime Dispose check
+                                               //
+                                               var tv = new LocalTemporary (TypeManager.idisposable_type);
+                                               statement = new Dispose (enumerator, tv, init, statement, loc);
+                                       } else {
+                                               //
+                                               // No Dispose call needed
+                                               //
+                                               this.init = new SimpleAssign (enumerator, init);
+                                               this.init.Resolve (ec);
+                                       }
                                } else {
-                                       wrapper = new NonDisposableWrapper (this);
+                                       //
+                                       // Static Dispose check
+                                       //
+                                       statement = new Dispose (enumerator, null, init, statement, loc);
                                }
 
-                               return wrapper.Resolve (ec);
+                               return statement.Resolve (ec);
                        }
 
                        protected override void DoEmit (EmitContext ec)
                        {
-                               wrapper.Emit (ec);
-                       }
-
-                       class NonDisposableWrapper : Statement {
-                               CollectionForeach parent;
-
-                               internal NonDisposableWrapper (CollectionForeach parent)
-                               {
-                                       this.parent = parent;
-                               }
-
-                               protected override void CloneTo (CloneContext clonectx, Statement target)
-                               {
-                                       throw new NotSupportedException ();
-                               }
+                               if (init != null)
+                                       init.EmitStatement (ec);
 
-                               public override bool Resolve (BlockContext ec)
-                               {
-                                       return parent.ResolveLoop (ec);
-                               }
-
-                               protected override void DoEmit (EmitContext ec)
-                               {
-                                       parent.EmitLoopInit (ec);
-                                       parent.EmitLoopBody (ec);
-                               }
-
-                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-                               {
-                                       throw new NotSupportedException ();
-                               }
+                               statement.Emit (ec);
                        }
 
-                       sealed class DisposableWrapper : ExceptionStatement
-                       {
-                               CollectionForeach parent;
-                               bool implements_idisposable;
-
-                               internal DisposableWrapper (CollectionForeach parent, bool implements)
-                               {
-                                       this.parent = parent;
-                                       this.implements_idisposable = implements;
-                               }
-
-                               protected override void CloneTo (CloneContext clonectx, Statement target)
-                               {
-                                       throw new NotSupportedException ();
-                               }
-
-                               public override bool Resolve (BlockContext ec)
-                               {
-                                       bool ok = true;
-
-                                       ec.StartFlowBranching (this);
-
-                                       if (!parent.ResolveLoop (ec))
-                                               ok = false;
-
-                                       ec.EndFlowBranching ();
-
-                                       ok &= base.Resolve (ec);
-
-                                       if (TypeManager.void_dispose_void == null) {
-                                               TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
-                                                       TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes);
-                                       }
-                                       return ok;
-                               }
+                       #region IErrorHandler Members
 
-                               protected override void EmitPreTryBody (EmitContext ec)
-                               {
-                                       parent.EmitLoopInit (ec);
-                               }
-
-                               protected override void EmitTryBody (EmitContext ec)
-                               {
-                                       parent.EmitLoopBody (ec);
-                               }
-
-                               protected override void EmitFinallyBody (EmitContext ec)
-                               {
-                                       Expression instance = parent.enumerator;
-                                       if (!TypeManager.IsValueType (parent.enumerator_type)) {
-                                               ILGenerator ig = ec.ig;
-
-                                               parent.enumerator.Emit (ec);
-
-                                               Label call_dispose = ig.DefineLabel ();
-
-                                               if (!implements_idisposable) {
-                                                       ec.ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
-                                                       LocalTemporary temp = new LocalTemporary (TypeManager.idisposable_type);
-                                                       temp.Store (ec);
-                                                       temp.Emit (ec);
-                                                       instance = temp;
-                                               }
-                                               
-                                               ig.Emit (OpCodes.Brtrue_S, call_dispose);
-
-                                               // using 'endfinally' to empty the evaluation stack
-                                               ig.Emit (OpCodes.Endfinally);
-                                               ig.MarkLabel (call_dispose);
-                                       }
-
-                                       Invocation.EmitCall (ec, false, instance, TypeManager.void_dispose_void, null, loc);
-                               }
-
-                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-                               {
-                                       throw new NotSupportedException ();
-                               }
-                       }
-
-                       bool ResolveLoop (BlockContext ec)
+                       bool MethodGroupExpr.IErrorHandler.AmbiguousCall (ResolveContext ec, MethodGroupExpr mg, MethodSpec ambiguous)
                        {
-                               return loop.Resolve (ec);
-                       }
+                               ec.Report.SymbolRelatedToPreviousError (mg.BestCandidate);
+                               ec.Report.Warning (278, 2, loc,
+                                       "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'",
+                                       mg.DeclaringType.GetSignatureForError (), "enumerable",
+                                       mg.BestCandidate.GetSignatureForError (), ambiguous.GetSignatureForError ());
 
-                       void EmitLoopInit (EmitContext ec)
-                       {
-                               enumerator.EmitAssign (ec, init);
+                               return true;
                        }
 
-                       void EmitLoopBody (EmitContext ec)
+                       bool MethodGroupExpr.IErrorHandler.NoExactMatch (ResolveContext ec, MethodSpec method)
                        {
-                               loop.Emit (ec);
+                               return false;
                        }
 
-                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-                       {
-                               enumerator_type = storey.MutateType (enumerator_type);
-                               init.MutateHoistedGenericType (storey);
-                               loop.MutateHoistedGenericType (storey);
-                       }
+                       #endregion
                }
 
                Expression type;
@@ -5874,8 +5521,8 @@ namespace Mono.CSharp {
 
                        if (expr.Type == TypeManager.string_type) {
                                statement = new ArrayForeach (this, 1);
-                       } else if (expr.Type.IsArray) {
-                               statement = new ArrayForeach (this, expr.Type.GetArrayRank ());
+                       } else if (expr.Type is ArrayContainer) {
+                               statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank);
                        } else {
                                if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
                                        ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
@@ -5891,11 +5538,9 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
-                       ec.LoopBegin = ig.DefineLabel ();
-                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.LoopBegin = ec.DefineLabel ();
+                       ec.LoopEnd = ec.DefineLabel ();
 
                        statement.Emit (ec);
 
@@ -5912,10 +5557,5 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                        target.statement = statement.Clone (clonectx);
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       statement.MutateHoistedGenericType (storey);
-               }
        }
 }