Fix the monotouch build
[mono.git] / mcs / mcs / statement.cs
index 12bd6b6977dee2cb219ee6bb34f6c54440036f05..51a975d549f59797a6eeff5bfbe67ab96fdd1cc1 100644 (file)
@@ -92,8 +92,6 @@ namespace Mono.CSharp {
 
                        return Clone (clonectx);
                }
 
                        return Clone (clonectx);
                }
-
-               public abstract void MutateHoistedGenericType (AnonymousMethodStorey storey);
        }
 
        public sealed class EmptyStatement : Statement
        }
 
        public sealed class EmptyStatement : Statement
@@ -122,10 +120,6 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ();
                }
 
                        throw new NotSupportedException ();
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        // nothing needed.
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        // nothing needed.
@@ -155,14 +149,6 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
                        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;
                public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
@@ -221,8 +207,7 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       Label false_target = ig.DefineLabel ();
+                       Label false_target = ec.DefineLabel ();
                        Label end;
 
                        //
                        Label end;
 
                        //
@@ -248,19 +233,19 @@ namespace Mono.CSharp {
                        if (FalseStatement != null){
                                bool branch_emitted = false;
                                
                        if (FalseStatement != null){
                                bool branch_emitted = false;
                                
-                               end = ig.DefineLabel ();
+                               end = ec.DefineLabel ();
                                if (!is_true_ret){
                                if (!is_true_ret){
-                                       ig.Emit (OpCodes.Br, end);
+                                       ec.Emit (OpCodes.Br, end);
                                        branch_emitted = true;
                                }
 
                                        branch_emitted = true;
                                }
 
-                               ig.MarkLabel (false_target);
+                               ec.MarkLabel (false_target);
                                FalseStatement.Emit (ec);
 
                                if (branch_emitted)
                                FalseStatement.Emit (ec);
 
                                if (branch_emitted)
-                                       ig.MarkLabel (end);
+                                       ec.MarkLabel (end);
                        } else {
                        } else {
-                               ig.MarkLabel (false_target);
+                               ec.MarkLabel (false_target);
                        }
                }
 
                        }
                }
 
@@ -318,17 +303,16 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
                
                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;
                        
                        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);
                        EmbeddedStatement.Emit (ec);
-                       ig.MarkLabel (ec.LoopBegin);
+                       ec.MarkLabel (ec.LoopBegin);
 
                        //
                        // Dead code elimination
 
                        //
                        // Dead code elimination
@@ -338,22 +322,16 @@ namespace Mono.CSharp {
 
                                expr.EmitSideEffect (ec);
                                if (res)
 
                                expr.EmitSideEffect (ec);
                                if (res)
-                                       ec.ig.Emit (OpCodes.Br, loop); 
+                                       ec.Emit (OpCodes.Br, loop); 
                        } else
                                expr.EmitBranchable (ec, loop, true);
                        
                        } else
                                expr.EmitBranchable (ec, loop, true);
                        
-                       ig.MarkLabel (ec.LoopEnd);
+                       ec.MarkLabel (ec.LoopEnd);
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
 
 
                        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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Do target = (Do) t;
@@ -422,42 +400,41 @@ namespace Mono.CSharp {
                                return;
                        }
 
                                return;
                        }
 
-                       ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
                        
                        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
 
                        //
                        // 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);
                                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.
                                //
                                        
                                //
                                // 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 {
                        } 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);
                        
 
                                Statement.Emit (ec);
                        
-                               ig.MarkLabel (ec.LoopBegin);
+                               ec.MarkLabel (ec.LoopBegin);
                                ec.Mark (loc);
 
                                expr.EmitBranchable (ec, while_loop, true);
                                
                                ec.Mark (loc);
 
                                expr.EmitBranchable (ec, while_loop, true);
                                
-                               ig.MarkLabel (ec.LoopEnd);
+                               ec.MarkLabel (ec.LoopEnd);
                        }       
 
                        ec.LoopBegin = old_begin;
                        }       
 
                        ec.LoopBegin = old_begin;
@@ -476,12 +453,6 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                        target.Statement = Statement.Clone (clonectx);
                }
                        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 {
        }
 
        public class For : Statement {
@@ -573,23 +544,22 @@ namespace Mono.CSharp {
                                return;
                        }
 
                                return;
                        }
 
-                       ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
                        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);
 
                        Statement.Emit (ec);
 
-                       ig.MarkLabel (ec.LoopBegin);
+                       ec.MarkLabel (ec.LoopBegin);
                        Increment.Emit (ec);
 
                        Increment.Emit (ec);
 
-                       ig.MarkLabel (test);
+                       ec.MarkLabel (test);
                        //
                        // If test is null, there is no test, and we are just
                        // an infinite loop
                        //
                        // If test is null, there is no test, and we are just
                        // an infinite loop
@@ -602,31 +572,19 @@ namespace Mono.CSharp {
                                //
                                if (Test is Constant) {
                                        Test.EmitSideEffect (ec);
                                //
                                if (Test is Constant) {
                                        Test.EmitSideEffect (ec);
-                                       ig.Emit (OpCodes.Br, loop);
+                                       ec.Emit (OpCodes.Br, loop);
                                } else {
                                        Test.EmitBranchable (ec, loop, true);
                                }
                                
                        } else
                                } 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;
                }
 
 
                        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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        For target = (For) t;
@@ -661,11 +619,6 @@ namespace Mono.CSharp {
                        expr.EmitStatement (ec);
                }
 
                        expr.EmitStatement (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       expr.MutateHoistedGenericType (storey);
-               }
-
                public override string ToString ()
                {
                        return "StatementExpression (" + expr + ")";
                public override string ToString ()
                {
                        return "StatementExpression (" + expr + ")";
@@ -679,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
        {
        // A 'return' or a 'yield break'
        public abstract class ExitStatement : Statement
        {
@@ -706,14 +708,23 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the return statement
        /// </summary>
        /// <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;
                }
                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) {
                protected override bool DoResolve (BlockContext ec)
                {
                        if (Expr == null) {
@@ -768,19 +779,13 @@ namespace Mono.CSharp {
                                Expr.Emit (ec);
 
                                if (unwind_protect)
                                Expr.Emit (ec);
 
                                if (unwind_protect)
-                                       ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
+                                       ec.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
                        }
 
                        if (unwind_protect)
                        }
 
                        if (unwind_protect)
-                               ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+                               ec.Emit (OpCodes.Leave, ec.ReturnLabel);
                        else
                        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)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -830,11 +835,7 @@ namespace Mono.CSharp {
                        if (label == null)
                                throw new InternalErrorException ("goto emitted before target resolved");
                        Label l = label.LabelTarget (ec);
                        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);
                }
        }
 
                }
        }
 
@@ -843,7 +844,6 @@ namespace Mono.CSharp {
                bool defined;
                bool referenced;
                Label label;
                bool defined;
                bool referenced;
                Label label;
-               ILGenerator ig;
 
                FlowBranching.UsageVector vectors;
                
 
                FlowBranching.UsageVector vectors;
                
@@ -857,10 +857,9 @@ namespace Mono.CSharp {
                {
                        if (defined)
                                return label;
                {
                        if (defined)
                                return label;
-                       ig = ec.ig;
-                       label = ec.ig.DefineLabel ();
-                       defined = true;
 
 
+                       label = ec.DefineLabel ();
+                       defined = true;
                        return label;
                }
 
                        return label;
                }
 
@@ -901,14 +900,8 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       if (ig != null && ig != ec.ig)
-                               throw new InternalErrorException ("cannot happen");
                        LabelTarget (ec);
                        LabelTarget (ec);
-                       ec.ig.MarkLabel (label);
-               }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
+                       ec.MarkLabel (label);
                }
 
                public void AddReference ()
                }
 
                public void AddReference ()
@@ -952,11 +945,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                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);
                }
        }
 
                }
        }
 
@@ -992,7 +981,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
                                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);
                        Constant res = c.TryReduce (ec, type, c.Location);
                        if (res == null) {
                                c.Error_ValueCannotBeConverted (ec, loc, type, true);
@@ -1019,12 +1008,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                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)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1068,20 +1052,14 @@ namespace Mono.CSharp {
                protected override void DoEmit (EmitContext ec)
                {
                        if (expr == null)
                protected override void DoEmit (EmitContext ec)
                {
                        if (expr == null)
-                               ec.ig.Emit (OpCodes.Rethrow);
+                               ec.Emit (OpCodes.Rethrow);
                        else {
                                expr.Emit (ec);
 
                        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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Throw target = (Throw) t;
@@ -1109,13 +1087,9 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                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
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        // nothing needed
@@ -1140,11 +1114,7 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                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)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1171,7 +1141,7 @@ namespace Mono.CSharp {
        public class LocalInfo : IKnownVariable, ILocalVariable {
                public readonly FullNamedExpression Type;
 
        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;
                public readonly string Name;
                public readonly Location Location;
                public readonly Block Block;
@@ -1208,9 +1178,9 @@ namespace Mono.CSharp {
                        Location = l;
                }
 
                        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;
                }
                        Block = block;
                        Location = l;
                }
@@ -1221,23 +1191,23 @@ namespace Mono.CSharp {
                                return;
 
                        if (builder == null) {
                                return;
 
                        if (builder == null) {
-                               builder = ec.ig.DeclareLocal (TypeManager.TypeToReflectionType (VariableType), Pinned);
+                               builder = ec.DeclareLocal (VariableType, Pinned);
                        }
                }
 
                public void Emit (EmitContext ec)
                {
                        }
                }
 
                public void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldloc, builder);
+                       ec.Emit (OpCodes.Ldloc, builder);
                }
 
                public void EmitAssign (EmitContext ec)
                {
                }
 
                public void EmitAssign (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Stloc, builder);
+                       ec.Emit (OpCodes.Stloc, builder);
                }
 
                public void EmitAddressOf (EmitContext ec)
                {
                }
 
                public void EmitAddressOf (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldloca, builder);
+                       ec.Emit (OpCodes.Ldloca, builder);
                }
 
                public void EmitSymbolInfo (EmitContext ec)
                }
 
                public void EmitSymbolInfo (EmitContext ec)
@@ -1288,10 +1258,7 @@ namespace Mono.CSharp {
                                
                        VariableType = texpr.Type;
 
                                
                        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;
                        }
                                FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType, ec.Report);
                                return false;
                        }
@@ -1483,6 +1450,8 @@ namespace Mono.CSharp {
 
                List<ToplevelBlock> anonymous_children;
 
 
                List<ToplevelBlock> anonymous_children;
 
+               int? resolving_init_idx;
+
                protected static int id;
 
                int this_id;
                protected static int id;
 
                int this_id;
@@ -1536,13 +1505,7 @@ namespace Mono.CSharp {
                        statements = new List<Statement> (4);
                }
 
                        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; }
 
                public int ID {
                        get { return this_id; }
@@ -1556,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)
                void AddChild (Block b)
                {
                        if (children == null)
@@ -1729,7 +1702,7 @@ namespace Mono.CSharp {
                        return false;
                }
 
                        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) {
                {
                        LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
@@ -1744,13 +1717,13 @@ namespace Mono.CSharp {
                        }
 
                        if (block != null) {
                        }
 
                        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");
                                                Error_AlreadyDeclared (loc, name);
                                        else
                                                Error_AlreadyDeclared (loc, name, "parent or current");
+
                                        return false;
                                }
                        }
                                        return false;
                                }
                        }
@@ -1763,16 +1736,6 @@ namespace Mono.CSharp {
                        if (!CheckParentConflictName (Toplevel, name, l))
                                return null;
 
                        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);
                        IKnownVariable kvi = Explicit.GetKnownVariable (name);
                        if (kvi != null) {
                                Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
@@ -1814,9 +1777,9 @@ namespace Mono.CSharp {
                                "A local variable named `{0}' is already defined in this scope", name);
                }
                                        
                                "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);
                }
 
                                name, conflict);
                }
 
@@ -1857,9 +1820,8 @@ namespace Mono.CSharp {
                {
                        LocalInfo ret;
                        for (Block b = this; b != null; b = b.Parent) {
                {
                        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;
                                }
                        }
 
                                }
                        }
 
@@ -1893,7 +1855,18 @@ namespace Mono.CSharp {
                        if (scope_initializers == null)
                                scope_initializers = new List<Statement> ();
 
                        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)
                }
                
                public void AddStatement (Statement s)
@@ -1947,7 +1920,7 @@ namespace Mono.CSharp {
                        foreach (var de in variables) {
                                string name = de.Key;
                                LocalInfo vi = de.Value;
                        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)
 
                                if (variable_type == null) {
                                        if (vi.Type is VarExpr)
@@ -1965,7 +1938,7 @@ namespace Mono.CSharp {
                                // which in turn causes the 'must be constant' error to be triggered.
                                constants.Remove (name);
 
                                // 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;
                                }
                                        Const.Error_InvalidConstantType (variable_type, loc, ec.Report);
                                        continue;
                                }
@@ -2115,8 +2088,11 @@ namespace Mono.CSharp {
                        // Compiler generated scope statements
                        //
                        if (scope_initializers != null) {
                        // 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;
                        }
 
                        //
                        }
 
                        //
@@ -2223,8 +2199,7 @@ namespace Mono.CSharp {
                protected override void DoEmit (EmitContext ec)
                {
                        for (int ix = 0; ix < statements.Count; ix++){
                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);
                        }
                }
 
                        }
                }
 
@@ -2242,14 +2217,14 @@ namespace Mono.CSharp {
 
                protected void EmitScopeInitializers (EmitContext ec)
                {
 
                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);
                        }
 
 
                        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)
                }
 
                protected virtual void EmitSymbolInfo (EmitContext ec)
@@ -2261,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 ()
                {
                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)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -2299,7 +2247,7 @@ namespace Mono.CSharp {
 
                        clonectx.AddBlockMap (this, target);
 
 
                        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);
                        target.Explicit = (ExplicitBlock) clonectx.LookupBlock (Explicit);
                        if (Parent != null)
                                target.Parent = clonectx.RemapBlockCopy (Parent);
@@ -2392,7 +2340,7 @@ namespace Mono.CSharp {
                                //
                                // Creates anonymous method storey for this block
                                //
                                //
                                // 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;
                        }
 
                        return am_storey;
@@ -2432,14 +2380,21 @@ namespace Mono.CSharp {
                                                while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey)
                                                        parent = parent.Parent.Explicit;
 
                                                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.DefineType ();
-                               am_storey.ResolveType ();
+                               am_storey.ResolveTypeParameters ();
                                am_storey.Define ();
                                am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
 
                                am_storey.Define ();
                                am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
 
@@ -2448,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) {
                                        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)
 
                                                                // Stop propagation inside same top block
                                                                if (b.Toplevel == Toplevel)
@@ -2465,15 +2420,13 @@ namespace Mono.CSharp {
                        base.EmitMeta (ec);
                }
 
                        base.EmitMeta (ec);
                }
 
-               internal IKnownVariable GetKnownVariable (string name)
+               public IKnownVariable GetKnownVariable (string name)
                {
                        if (known_variables == null)
                                return null;
 
                        IKnownVariable kw;
                {
                        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;
                }
 
                        return kw;
                }
 
@@ -2509,7 +2462,7 @@ namespace Mono.CSharp {
                        get { return Block.Parameters [Index]; }
                }
 
                        get { return Block.Parameters [Index]; }
                }
 
-               public Type ParameterType {
+               public TypeSpec ParameterType {
                        get { return Block.Parameters.Types [Index]; }
                }
 
                        get { return Block.Parameters.Types [Index]; }
                }
 
@@ -2573,18 +2526,10 @@ namespace Mono.CSharp {
                                block.EmitScopeInitializers (ec);
                                child.Emit (ec);
                        }
                                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;
                protected ParametersCompiled parameters;
-               ToplevelParameterInfo[] parameter_info;
+               protected ToplevelParameterInfo[] parameter_info;
                LocalInfo this_variable;
                bool resolved;
                bool unreachable;
                LocalInfo this_variable;
                bool resolved;
                bool unreachable;
@@ -2609,10 +2554,6 @@ namespace Mono.CSharp {
                        get { return compiler.Report; }
                }
 
                        get { return compiler.Report; }
                }
 
-               public GenericMethod GenericMethod {
-                       get { return generic; }
-               }
-
                public ToplevelBlock Container {
                        get { return Parent == null ? null : Parent.Toplevel; }
                }
                public ToplevelBlock Container {
                        get { return Parent == null ? null : Parent.Toplevel; }
                }
@@ -2622,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)
                {
                public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) :
                        this (ctx, null, (Flags) 0, parameters, start)
                {
@@ -2665,10 +2600,11 @@ namespace Mono.CSharp {
                        ToplevelBlock target = (ToplevelBlock) t;
                        base.CloneTo (clonectx, t);
 
                        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)
                }
 
                public bool CheckError158 (string name, Location loc)
@@ -2761,6 +2697,9 @@ namespace Mono.CSharp {
                public Expression GetParameterReference (string name, Location loc)
                {
                        for (ToplevelBlock t = this; t != null; t = t.Container) {
                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;
                                Expression expr = t.GetParameterReferenceExpression (name, loc);
                                if (expr != null)
                                        return expr;
@@ -2776,6 +2715,21 @@ namespace Mono.CSharp {
                                null : new ParameterReference (parameter_info [idx], loc);
                }
 
                                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.
                // <summary>
                //   Returns the "this" instance variable of this block.
                //   See AddThisVariable() for more information.
@@ -2791,7 +2745,7 @@ namespace Mono.CSharp {
                //   analysis code to ensure that it's been fully initialized before control
                //   leaves the constructor.
                // </summary>
                //   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);
                {
                        if (this_variable == null) {
                                this_variable = new LocalInfo (ds, this, l);
@@ -2843,15 +2797,18 @@ namespace Mono.CSharp {
 
                                        unreachable = top_level.End ();
                                }
 
                                        unreachable = top_level.End ();
                                }
-                       } catch (Exception) {
-#if PRODUCTION
+                       } catch (Exception e) {
+                               if (e is CompletionResult || rc.Report.IsDisabled)
+                                       throw;
+
                                if (rc.CurrentBlock != null) {
                                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 {
                                } 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) {
                        }
 
                        if (rc.ReturnType != TypeManager.void_type && !unreachable) {
@@ -2933,18 +2890,18 @@ namespace Mono.CSharp {
                        EmitMeta (ec);
 
                        if (ec.HasReturnLabel)
                        EmitMeta (ec);
 
                        if (ec.HasReturnLabel)
-                               ec.ReturnLabel = ec.ig.DefineLabel ();
+                               ec.ReturnLabel = ec.DefineLabel ();
 
                        base.Emit (ec);
 
                        ec.Mark (EndLocation);
 
                        if (ec.HasReturnLabel)
 
                        base.Emit (ec);
 
                        ec.Mark (EndLocation);
 
                        if (ec.HasReturnLabel)
-                               ec.ig.MarkLabel (ec.ReturnLabel);
+                               ec.MarkLabel (ec.ReturnLabel);
 
                        if (ec.return_value != null) {
 
                        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
                        } else {
                                //
                                // If `HasReturnLabel' is set, then we already emitted a
@@ -2961,8 +2918,8 @@ namespace Mono.CSharp {
 
                                if (ec.HasReturnLabel || !unreachable) {
                                        if (ec.ReturnType != TypeManager.void_type)
 
                                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);
                                }
                        }
 
                                }
                        }
 
@@ -2979,8 +2936,6 @@ namespace Mono.CSharp {
 
                public override void EmitMeta (EmitContext ec)
                {
 
                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)
                        // Avoid declaring an IL variable for this_variable since it is not accessed
                        // from the generated IL
                        if (this_variable != null)
@@ -3038,7 +2993,7 @@ namespace Mono.CSharp {
                public Label GetILLabel (EmitContext ec)
                {
                        if (!il_label_set){
                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;
                                il_label_set = true;
                        }
                        return il_label;
@@ -3047,7 +3002,7 @@ namespace Mono.CSharp {
                public Label GetILLabelCode (EmitContext ec)
                {
                        if (!il_label_code_set){
                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;
                                il_label_code_set = true;
                        }
                        return il_label_code;
@@ -3057,7 +3012,7 @@ namespace Mono.CSharp {
                // Resolves the expression, reduces it to a literal if possible
                // and then converts it to the requested type.
                //
                // 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);
 
                {       
                        Expression e = label.Resolve (ec);
 
@@ -3088,7 +3043,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
                        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)
                {
                        string label;
                        if (converted == null)
@@ -3142,7 +3097,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   The governing switch type
                /// </summary>
                /// <summary>
                ///   The governing switch type
                /// </summary>
-               public Type SwitchType;
+               public TypeSpec SwitchType;
 
                //
                // Computed
 
                //
                // Computed
@@ -3172,7 +3127,7 @@ namespace Mono.CSharp {
                // The types allowed to be implicitly cast from
                // on the governing type
                //
                // 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)
                {
 
                public Switch (Expression e, List<SwitchSection> sects, Location l)
                {
@@ -3201,7 +3156,7 @@ namespace Mono.CSharp {
                //
                Expression SwitchGoverningType (ResolveContext ec, Expression expr)
                {
                //
                Expression SwitchGoverningType (ResolveContext ec, Expression expr)
                {
-                       Type t = expr.Type;
+                       TypeSpec t = expr.Type;
 
                        if (t == TypeManager.byte_type ||
                            t == TypeManager.sbyte_type ||
 
                        if (t == TypeManager.byte_type ||
                            t == TypeManager.sbyte_type ||
@@ -3218,7 +3173,7 @@ namespace Mono.CSharp {
                                return expr;
 
                        if (allowed_types == null){
                                return expr;
 
                        if (allowed_types == null){
-                               allowed_types = new Type [] {
+                               allowed_types = new TypeSpec [] {
                                        TypeManager.sbyte_type,
                                        TypeManager.byte_type,
                                        TypeManager.short_type,
                                        TypeManager.sbyte_type,
                                        TypeManager.byte_type,
                                        TypeManager.short_type,
@@ -3239,7 +3194,7 @@ namespace Mono.CSharp {
                        // conversions, we have to report an error
                        //
                        Expression converted = null;
                        // 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);
                                Expression e;
                                
                                e = Convert.ImplicitUserConversion (ec, expr, tt, loc);
@@ -3306,50 +3261,50 @@ namespace Mono.CSharp {
                        return !error;
                }
 
                        return !error;
                }
 
-               void EmitObjectInteger (ILGenerator ig, object k)
+               void EmitObjectInteger (EmitContext ec, object k)
                {
                        if (k is int)
                {
                        if (k is int)
-                               IntConstant.EmitInt (ig, (int) k);
+                               ec.EmitInt ((int) k);
                        else if (k is Constant) {
                        else if (k is Constant) {
-                               EmitObjectInteger (ig, ((Constant) k).GetValue ());
+                               EmitObjectInteger (ec, ((Constant) k).GetValue ());
                        } 
                        else if (k is uint)
                        } 
                        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)
                                {
                        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
                                }
                                else
-                                       LongConstant.EmitLong (ig, (long) k);
+                                       ec.EmitLong ((long) k);
                        }
                        else if (k is ulong)
                        {
                                ulong ul = (ulong) k;
                                if (ul < (1L<<32))
                                {
                        }
                        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
                                {
                                }
                                else
                                {
-                                       LongConstant.EmitLong (ig, unchecked ((long) ul));
+                                       ec.EmitLong (unchecked ((long) ul));
                                }
                        }
                        else if (k is char)
                                }
                        }
                        else if (k is char)
-                               IntConstant.EmitInt (ig, (int) ((char) k));
+                               ec.EmitInt ((int) ((char) k));
                        else if (k is sbyte)
                        else if (k is sbyte)
-                               IntConstant.EmitInt (ig, (int) ((sbyte) k));
+                               ec.EmitInt ((int) ((sbyte) k));
                        else if (k is byte)
                        else if (k is byte)
-                               IntConstant.EmitInt (ig, (int) ((byte) k));
+                               ec.EmitInt ((int) ((byte) k));
                        else if (k is short)
                        else if (k is short)
-                               IntConstant.EmitInt (ig, (int) ((short) k));
+                               ec.EmitInt ((int) ((short) k));
                        else if (k is ushort)
                        else if (k is ushort)
-                               IntConstant.EmitInt (ig, (int) ((ushort) k));
+                               ec.EmitInt ((int) ((ushort) k));
                        else if (k is bool)
                        else if (k is bool)
-                               IntConstant.EmitInt (ig, ((bool) k) ? 1 : 0);
+                               ec.EmitInt (((bool) k) ? 1 : 0);
                        else
                                throw new Exception ("Unhandled case");
                }
                        else
                                throw new Exception ("Unhandled case");
                }
@@ -3458,25 +3413,24 @@ namespace Mono.CSharp {
                        key_blocks.Sort ();
 
                        // okay now we can start...
                        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
 
                        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))
                        
                        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]);
                        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) {
                                if (kb.Length <= 2)
                                {
                                        foreach (object key in kb.element_keys) {
@@ -3485,8 +3439,8 @@ namespace Mono.CSharp {
                                                        val.EmitBranchable (ec, sl.GetILLabel (ec), false);
                                                } else {
                                                        val.Emit (ec);
                                                        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));
                                                }
                                        }
                                }
                                                }
                                        }
                                }
@@ -3501,20 +3455,20 @@ namespace Mono.CSharp {
 
                                                // check block range (could be > 2^31)
                                                val.Emit (ec);
 
                                                // 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);
                                                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)
                                                {
 
                                                // 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
                                        {
                                        }
                                        else
                                        {
@@ -3523,13 +3477,13 @@ namespace Mono.CSharp {
                                                int first = (int) kb.first;
                                                if (first > 0)
                                                {
                                                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)
                                                {
                                                }
                                                else if (first < 0)
                                                {
-                                                       IntConstant.EmitInt (ig, -first);
-                                                       ig.Emit (OpCodes.Add);
+                                                       ec.EmitInt (-first);
+                                                       ec.Emit (OpCodes.Add);
                                                }
                                        }
 
                                                }
                                        }
 
@@ -3550,12 +3504,12 @@ namespace Mono.CSharp {
                                                        switch_labels [iJump] = lbl_default;
                                        }
                                        // emit the switch opcode
                                                        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)
                                }
 
                                // 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,
                        }
 
                        // TODO: find the default case and emit it here,
@@ -3564,7 +3518,7 @@ namespace Mono.CSharp {
 
                        // the last default just goes to the end
                        if (element_keys.Length > 0)
 
                        // 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;
 
                        // now emit the code for the sections
                        bool found_default = false;
@@ -3572,27 +3526,27 @@ namespace Mono.CSharp {
                        foreach (SwitchSection ss in Sections) {
                                foreach (SwitchLabel sl in ss.Labels) {
                                        if (sl.Converted == SwitchLabel.NullStringCase) {
                        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) {
                                        } else if (sl.Label == null) {
-                                               ig.MarkLabel (lbl_default);
+                                               ec.MarkLabel (lbl_default);
                                                found_default = true;
                                                if (!has_null_case)
                                                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) {
                                }
                                ss.Block.Emit (ec);
                        }
                        
                        if (!found_default) {
-                               ig.MarkLabel (lbl_default);
+                               ec.MarkLabel (lbl_default);
                                if (!has_null_case) {
                                if (!has_null_case) {
-                                       ig.MarkLabel (null_target);
+                                       ec.MarkLabel (null_target);
                                }
                        }
                        
                                }
                        }
                        
-                       ig.MarkLabel (lbl_end);
+                       ec.MarkLabel (lbl_end);
                }
 
                SwitchSection FindSection (SwitchLabel label)
                }
 
                SwitchSection FindSection (SwitchLabel label)
@@ -3607,12 +3561,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
                        return null;
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       foreach (SwitchSection ss in Sections)
-                               ss.Block.MutateHoistedGenericType (storey);
-               }
-
                public static void Reset ()
                {
                        unique_counter = 0;
                public static void Reset ()
                {
                        unique_counter = 0;
@@ -3736,12 +3684,13 @@ namespace Mono.CSharp {
                                string_dictionary_type = new MemberAccess (system_collections_generic, "Hashtable", loc);
                        }
 
                                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;
                                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;
 
                        var init = new List<Expression> ();
                        int counter = 0;
@@ -3781,8 +3730,7 @@ namespace Mono.CSharp {
 
                void DoEmitStringSwitch (LocalTemporary value, EmitContext ec)
                {
 
                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
 
                        //
                        // Skip initialization when value is null
@@ -3794,7 +3742,7 @@ namespace Mono.CSharp {
                        //
                        switch_cache_field.EmitBranchable (ec, l_initialized, true);
                        string_dictionary.EmitStatement (ec);
                        //
                        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);
 
 
                        LocalTemporary string_switch_variable = new LocalTemporary (TypeManager.int32_type);
 
@@ -3816,13 +3764,13 @@ namespace Mono.CSharp {
                                Arguments get_value_args = new Arguments (1);
                                get_value_args.Add (new Argument (value));
 
                                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);
                                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);
 
                                ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable,
                                        new Cast (new TypeExpression (TypeManager.int32_type, loc), get_item_object, loc)).Resolve (rc);
@@ -3837,10 +3785,8 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
                
                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
 
                        // Store variable for comparission purposes
                        // TODO: Don't duplicate non-captured VariableReference
@@ -3848,7 +3794,7 @@ namespace Mono.CSharp {
                        if (HaveUnwrap) {
                                value = new LocalTemporary (SwitchType);
                                unwrap.EmitCheck (ec);
                        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) {
                                new_expr.Emit (ec);
                                value.Store (ec);
                        } else if (!is_constant) {
@@ -3864,7 +3810,7 @@ namespace Mono.CSharp {
                        Label old_end = ec.LoopEnd;
                        Switch old_switch = ec.Switch;
                        
                        Label old_end = ec.LoopEnd;
                        Switch old_switch = ec.Switch;
                        
-                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.LoopEnd = ec.DefineLabel ();
                        ec.Switch = this;
 
                        // Emit Code.
                        ec.Switch = this;
 
                        // Emit Code.
@@ -3881,7 +3827,7 @@ namespace Mono.CSharp {
                                value.Release (ec);
 
                        // Restore context state. 
                                value.Release (ec);
 
                        // Restore context state. 
-                       ig.MarkLabel (ec.LoopEnd);
+                       ec.MarkLabel (ec.LoopEnd);
 
                        //
                        // Restore the previous context
 
                        //
                        // Restore the previous context
@@ -3912,7 +3858,7 @@ namespace Mono.CSharp {
                {
                        if (!prepared) {
                                prepared = true;
                {
                        if (!prepared) {
                                prepared = true;
-                               resume_point = ec.ig.DefineLabel ();
+                               resume_point = ec.DefineLabel ();
                        }
                        return resume_point;
                }
                        }
                        return resume_point;
                }
@@ -3940,47 +3886,45 @@ namespace Mono.CSharp {
 
                protected sealed override void DoEmit (EmitContext ec)
                {
 
                protected sealed override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        EmitPreTryBody (ec);
 
                        if (resume_points != null) {
                        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) {
 
                        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
 
                                // 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);
 
                                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);
 
                        }
 
                        EmitTryBody (ec);
 
-                       ig.BeginFinallyBlock ();
+                       ec.BeginFinallyBlock ();
 
 
-                       Label start_finally = ec.ig.DefineLabel ();
+                       Label start_finally = ec.DefineLabel ();
                        if (resume_points != null) {
                        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);
 
                        EmitFinallyBody (ec);
 
-                       ig.EndExceptionBlock ();
+                       ec.EndExceptionBlock ();
                }
 
                public void SomeCodeFollows ()
                }
 
                public void SomeCodeFollows ()
@@ -4018,7 +3962,7 @@ namespace Mono.CSharp {
                {
                        if (!prepared_for_dispose) {
                                prepared_for_dispose = true;
                {
                        if (!prepared_for_dispose) {
                                prepared_for_dispose = true;
-                               dispose_try_block = ec.ig.DefineLabel ();
+                               dispose_try_block = ec.DefineLabel ();
                        }
                        return dispose_try_block;
                }
                        }
                        return dispose_try_block;
                }
@@ -4030,17 +3974,15 @@ namespace Mono.CSharp {
 
                        emitted_dispose = true;
 
 
                        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)
 
                        // 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) {
 
                        Label [] labels = null;
                        for (int i = 0; i < resume_points.Count; ++i) {
@@ -4065,10 +4007,10 @@ namespace Mono.CSharp {
 
                                if (emit_dispatcher) {
                                        //SymbolWriter.StartIteratorDispatcher (ec.ig);
 
                                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);
                                }
 
                                        //SymbolWriter.EndIteratorDispatcher (ec.ig);
                                }
 
@@ -4076,13 +4018,13 @@ namespace Mono.CSharp {
                                        s.EmitForDispose (ec, iterator, end_of_try, emit_dispatcher);
                        }
 
                                        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);
 
 
                        EmitFinallyBody (ec);
 
-                       ig.EndExceptionBlock ();
+                       ec.EndExceptionBlock ();
                }
        }
 
                }
        }
 
@@ -4119,7 +4061,7 @@ namespace Mono.CSharp {
 
                        // Avoid creating libraries that reference the internal
                        // mcs NullType:
 
                        // 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;
                        
                        if (t == TypeManager.null_type)
                                t = TypeManager.object_type;
                        
@@ -4127,7 +4069,7 @@ namespace Mono.CSharp {
                        temp.Resolve (ec);
 
                        if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) {
                        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 (
                                TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod (
                                        monitor_type, "Enter", loc, TypeManager.object_type);
                                TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod (
@@ -4139,11 +4081,9 @@ namespace Mono.CSharp {
                
                protected override void EmitPreTryBody (EmitContext ec)
                {
                
                protected override void EmitPreTryBody (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        temp.EmitAssign (ec, expr);
                        temp.Emit (ec);
                        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)
                }
 
                protected override void EmitTryBody (EmitContext ec)
@@ -4154,16 +4094,9 @@ namespace Mono.CSharp {
                protected override void EmitFinallyBody (EmitContext ec)
                {
                        temp.Emit (ec);
                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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Lock target = (Lock) t;
@@ -4176,10 +4109,11 @@ namespace Mono.CSharp {
        public class Unchecked : Statement {
                public Block Block;
                
        public class Unchecked : Statement {
                public Block Block;
                
-               public Unchecked (Block b)
+               public Unchecked (Block b, Location loc)
                {
                        Block = b;
                        b.Unchecked = true;
                {
                        Block = b;
                        b.Unchecked = true;
+                       this.loc = loc;
                }
 
                public override bool Resolve (BlockContext ec)
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4194,11 +4128,6 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
                                Block.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unchecked target = (Unchecked) t;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unchecked target = (Unchecked) t;
@@ -4210,10 +4139,11 @@ namespace Mono.CSharp {
        public class Checked : Statement {
                public Block Block;
                
        public class Checked : Statement {
                public Block Block;
                
-               public Checked (Block b)
+               public Checked (Block b, Location loc)
                {
                        Block = b;
                        b.Unchecked = false;
                {
                        Block = b;
                        b.Unchecked = false;
+                       this.loc = loc;
                }
 
                public override bool Resolve (BlockContext ec)
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4228,11 +4158,6 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
                                Block.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Checked target = (Checked) t;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Checked target = (Checked) t;
@@ -4244,11 +4169,11 @@ namespace Mono.CSharp {
        public class Unsafe : Statement {
                public Block Block;
 
        public class Unsafe : Statement {
                public Block Block;
 
-               public Unsafe (Block b)
+               public Unsafe (Block b, Location loc)
                {
                        Block = b;
                        Block.Unsafe = true;
                {
                        Block = b;
                        Block.Unsafe = true;
-                       loc = b.StartLocation;
+                       this.loc = loc;
                }
 
                public override bool Resolve (BlockContext ec)
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4265,11 +4190,6 @@ namespace Mono.CSharp {
                        Block.Emit (ec);
                }
 
                        Block.Emit (ec);
                }
 
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       Block.MutateHoistedGenericType (storey);
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unsafe target = (Unsafe) t;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unsafe target = (Unsafe) t;
@@ -4281,11 +4201,11 @@ namespace Mono.CSharp {
        // 
        // Fixed statement
        //
        // 
        // Fixed statement
        //
-       class Fixed : Statement {
+       public class Fixed : Statement {
                Expression type;
                List<KeyValuePair<LocalInfo, Expression>> declarators;
                Statement statement;
                Expression type;
                List<KeyValuePair<LocalInfo, Expression>> declarators;
                Statement statement;
-               Type expr_type;
+               TypeSpec expr_type;
                Emitter[] data;
                bool has_ret;
 
                Emitter[] data;
                bool has_ret;
 
@@ -4320,8 +4240,8 @@ namespace Mono.CSharp {
 
                        public override void EmitExit (EmitContext ec)
                        {
 
                        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);
                        }
                }
                                vi.EmitAssign (ec);
                        }
                }
@@ -4358,19 +4278,19 @@ namespace Mono.CSharp {
 
                                // TODO: Should use Binary::Add
                                pinned_string.Emit (ec);
 
                                // 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);
 
                                //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)
                        {
                                vi.EmitAssign (ec);
                        }
 
                        public override void EmitExit (EmitContext ec)
                        {
-                               ec.ig.Emit (OpCodes.Ldnull);
+                               ec.Emit (OpCodes.Ldnull);
                                pinned_string.EmitAssign (ec);
                        }
                }
                                pinned_string.EmitAssign (ec);
                        }
                }
@@ -4446,7 +4366,7 @@ namespace Mono.CSharp {
                                // Case 2: Array
                                //
                                if (e.Type.IsArray){
                                // 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,
                                        
                                        //
                                        // Provided that array_type is unmanaged,
@@ -4472,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),
                                                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);                                     
 
 
                                        converted = converted.Resolve (ec);                                     
 
@@ -4541,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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Fixed target = (Fixed) t;
@@ -4568,7 +4482,7 @@ namespace Mono.CSharp {
                public Block  VarBlock;
 
                Expression type_expr;
                public Block  VarBlock;
 
                Expression type_expr;
-               Type type;
+               TypeSpec type;
                
                public Catch (Expression type, string name, Block block, Block var_block, Location l)
                {
                
                public Catch (Expression type, string name, Block block, Block var_block, Location l)
                {
@@ -4579,7 +4493,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
                        loc = l;
                }
 
-               public Type CatchType {
+               public TypeSpec CatchType {
                        get {
                                return type;
                        }
                        get {
                                return type;
                        }
@@ -4593,12 +4507,10 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        if (CatchType != null)
                        if (CatchType != null)
-                               ig.BeginCatchBlock (CatchType);
+                               ec.BeginCatchBlock (CatchType);
                        else
                        else
-                               ig.BeginCatchBlock (TypeManager.object_type);
+                               ec.BeginCatchBlock (TypeManager.object_type);
 
                        if (VarBlock != null)
                                VarBlock.Emit (ec);
 
                        if (VarBlock != null)
                                VarBlock.Emit (ec);
@@ -4610,7 +4522,7 @@ namespace Mono.CSharp {
                                
                                // Only to make verifier happy
                                if (TypeManager.IsGenericParameter (lvr.Type))
                                
                                // 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) {
 
                                Expression source;
                                if (lvr.IsHoisted) {
@@ -4624,7 +4536,7 @@ namespace Mono.CSharp {
 
                                lvr.EmitAssign (ec, source, false, false);
                        } else
 
                                lvr.EmitAssign (ec, source, false, false);
                        } else
-                               ig.Emit (OpCodes.Pop);
+                               ec.Emit (OpCodes.Pop);
 
                        Block.Emit (ec);
                }
 
                        Block.Emit (ec);
                }
@@ -4658,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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Catch target = (Catch) t;
@@ -4727,12 +4630,6 @@ namespace Mono.CSharp {
                        fini.Emit (ec);
                }
 
                        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;
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        TryFinally target = (TryFinally) t;
@@ -4773,7 +4670,7 @@ namespace Mono.CSharp {
                        if (!Block.Resolve (ec))
                                ok = false;
 
                        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);
                        int last_index = 0;
                        foreach (Catch c in Specific){
                                ec.CurrentBranching.CreateSibling (c.Block, FlowBranching.SiblingType.Catch);
@@ -4791,7 +4688,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
                                        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,
                                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,
@@ -4836,10 +4733,8 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        if (!inside_try_finally)
                        if (!inside_try_finally)
-                               ig.BeginExceptionBlock ();
+                               ec.BeginExceptionBlock ();
 
                        Block.Emit (ec);
 
 
                        Block.Emit (ec);
 
@@ -4850,19 +4745,7 @@ namespace Mono.CSharp {
                                General.Emit (ec);
 
                        if (!inside_try_finally)
                                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)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -4881,54 +4764,87 @@ namespace Mono.CSharp {
        }
 
        // FIXME: Why is it almost exact copy of Using ??
        }
 
        // 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;
                Expression expr;
-               Type expr_type;
+               protected Statement dispose_call;
 
                public UsingTemporary (Expression expr, Statement stmt, Location l)
                {
                        this.expr = expr;
 
                public UsingTemporary (Expression expr, Statement stmt, Location l)
                {
                        this.expr = expr;
-                       Statement = stmt;
+                       statement = stmt;
                        loc = l;
                }
 
                        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 = 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) {
                                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);
                                        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);
 
                        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);
 
                        ec.StartFlowBranching (this);
 
-                       bool ok = Statement.Resolve (ec);
+                       ok &= statement.Resolve (ec);
 
                        ec.EndFlowBranching ();
 
                        ok &= base.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;
                }
 
                        return ok;
                }
 
@@ -4939,56 +4855,12 @@ namespace Mono.CSharp {
 
                protected override void EmitTryBody (EmitContext ec)
                {
 
                protected override void EmitTryBody (EmitContext ec)
                {
-                       Statement.Emit (ec);
+                       statement.Emit (ec);
                }
 
                protected override void EmitFinallyBody (EmitContext 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)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -4996,7 +4868,7 @@ namespace Mono.CSharp {
                        UsingTemporary target = (UsingTemporary) t;
 
                        target.expr = expr.Clone (clonectx);
                        UsingTemporary target = (UsingTemporary) t;
 
                        target.expr = expr.Clone (clonectx);
-                       target.Statement = Statement.Clone (clonectx);
+                       target.statement = statement.Clone (clonectx);
                }
        }
 
                }
        }
 
@@ -5038,26 +4910,18 @@ namespace Mono.CSharp {
 
                protected override void EmitFinallyBody (EmitContext ec)
                {
 
                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);
 
                        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)
 
                        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)
                }
 
                public override bool Resolve (BlockContext ec)
@@ -5075,7 +4939,7 @@ namespace Mono.CSharp {
 
                        if (TypeManager.void_dispose_void == null) {
                                TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
 
                        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;
                        }
 
                        return ok;
@@ -5088,14 +4952,13 @@ namespace Mono.CSharp {
                        if (assign == null)
                                return false;
 
                        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) {
                                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);
                                        e = Convert.ImplicitConversionRequired (ec, assign, TypeManager.idisposable_type, loc);
                                        var = new TemporaryVariable (e.Type, loc);
                                        assign = new SimpleAssign (var, e, loc).ResolveStatement (ec);
@@ -5205,7 +5068,7 @@ namespace Mono.CSharp {
                                        list.Add (new Argument (counter [i]));
                                }
 
                                        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;
 
                                if (access == null)
                                        return false;
 
@@ -5248,8 +5111,6 @@ namespace Mono.CSharp {
 
                        protected override void DoEmit (EmitContext ec)
                        {
 
                        protected override void DoEmit (EmitContext ec)
                        {
-                               ILGenerator ig = ec.ig;
-
                                copy.EmitAssign (ec, for_each.expr);
 
                                int rank = length_exprs.Length;
                                copy.EmitAssign (ec, for_each.expr);
 
                                int rank = length_exprs.Length;
@@ -5257,8 +5118,8 @@ namespace Mono.CSharp {
                                Label[] loop = new Label [rank];
 
                                for (int i = 0; i < rank; i++) {
                                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]);
 
                                        if (lengths != null)
                                                lengths [i].EmitAssign (ec, length_exprs [i]);
@@ -5268,20 +5129,20 @@ namespace Mono.CSharp {
                                for (int i = 0; i < rank; i++) {
                                        counter [i].EmitAssign (ec, zero);
 
                                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);
 
                                }
 
                                ((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);
 
 
                                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)
                                        counter [i].Emit (ec);
 
                                        if (lengths != null)
@@ -5289,38 +5150,23 @@ namespace Mono.CSharp {
                                        else
                                                length_exprs [i].Emit (ec);
 
                                        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;
 
                                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)
                                {
                                                                   Expression current, Statement statement,
                                                                   Location loc)
                                {
@@ -5361,28 +5207,61 @@ namespace Mono.CSharp {
                                        assign.EmitStatement (ec);
                                        statement.Emit (ec);
                                }
                                        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;
+                               }
 
 
-                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                               protected override bool DoResolve (BlockContext ec)
                                {
                                {
-                                       assign.MutateHoistedGenericType (storey);
-                                       statement.MutateHoistedGenericType (storey);
+                                       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);
+                               }
+
+                               protected override void EmitFinallyBody (EmitContext ec)
+                               {
+                                       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;
                                }
                        }
 
                        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;
                        Expression var_type;
-                       Type enumerator_type;
-                       bool enumerator_found;
+                       ExpressionStatement init;
 
                        public CollectionForeach (Expression var_type, Expression var,
                                                  Expression expr, Statement stmt, Location l)
 
                        public CollectionForeach (Expression var_type, Expression var,
                                                  Expression expr, Statement stmt, Location l)
@@ -5399,452 +5278,215 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
                                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;
                                        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;
                                        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;
                                        return false;
-                               }
 
                                VarExpr ve = var_type as VarExpr;
                                if (ve != null) {
                                        // Infer implicitly typed local variable from foreach enumerable type
 
                                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;
                                }
 
                                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;
+                               var init = new Invocation (get_enumerator_mg, null);
+                               init.Resolve (ec);
 
 
-                               Statement block = new CollectionForeachStatement (
-                                       var_type.Type, variable, get_current, statement, loc);
+                               statement = new While (new BooleanExpression (new Invocation (move_next_mg, null)),
+                                       new Body (var_type.Type, variable, current_pe, statement, loc), loc);
 
 
-                               loop = new While (new BooleanExpression (move_next_expr), block, 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 {
                                } 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)
                        {
                        }
 
                        protected override void DoEmit (EmitContext ec)
                        {
-                               wrapper.Emit (ec);
-                       }
+                               if (init != null)
+                                       init.EmitStatement (ec);
 
 
-                       class NonDisposableWrapper : Statement {
-                               CollectionForeach parent;
-
-                               internal NonDisposableWrapper (CollectionForeach parent)
-                               {
-                                       this.parent = parent;
-                               }
-
-                               protected override void CloneTo (CloneContext clonectx, Statement target)
-                               {
-                                       throw new NotSupportedException ();
-                               }
-
-                               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;
-                               }
-
-                               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);
-                                       }
+                       #region IErrorHandler Members
 
 
-                                       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;
                }
 
                Expression type;
@@ -5879,8 +5521,8 @@ namespace Mono.CSharp {
 
                        if (expr.Type == TypeManager.string_type) {
                                statement = new ArrayForeach (this, 1);
 
                        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}'",
                        } else {
                                if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
                                        ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
@@ -5896,11 +5538,9 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-
                        Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
                        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);
 
 
                        statement.Emit (ec);
 
@@ -5917,10 +5557,5 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                        target.statement = statement.Clone (clonectx);
                }
                        target.expr = expr.Clone (clonectx);
                        target.statement = statement.Clone (clonectx);
                }
-
-               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
-               {
-                       statement.MutateHoistedGenericType (storey);
-               }
        }
 }
        }
 }