Fix the monotouch build
[mono.git] / mcs / mcs / statement.cs
index 38a7529f89242fb61d8e95671044b6ca6bc12fc9..51a975d549f59797a6eeff5bfbe67ab96fdd1cc1 100644 (file)
@@ -632,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
        {
@@ -659,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) {
@@ -1392,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;
@@ -1445,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; }
@@ -1465,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)
@@ -1638,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) {
@@ -1653,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;
                                }
                        }
@@ -1672,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);
@@ -1723,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);
                }
 
@@ -1766,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;
                                }
                        }
 
                                }
                        }
 
@@ -1802,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)
@@ -2024,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;
                        }
 
                        //
                        }
 
                        //
@@ -2132,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);
                        }
                }
 
                        }
                }
 
@@ -2172,7 +2238,7 @@ namespace Mono.CSharp {
 
                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)
@@ -2181,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);
@@ -2354,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;
                }
 
@@ -2464,9 +2528,8 @@ namespace Mono.CSharp {
                        }
                }
 
                        }
                }
 
-               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;
@@ -2491,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; }
                }
@@ -2504,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)
                {
@@ -2547,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)
@@ -2643,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;
@@ -2658,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.
@@ -2725,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) {
@@ -3689,7 +3764,7 @@ 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;
 
                                if (get_item == null)
                                        return;
 
@@ -4034,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)
@@ -4063,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)
@@ -4092,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)
@@ -4124,7 +4201,7 @@ 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;
@@ -4203,7 +4280,7 @@ namespace Mono.CSharp {
                                pinned_string.Emit (ec);
                                ec.Emit (OpCodes.Conv_I);
 
                                pinned_string.Emit (ec);
                                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);
 
@@ -4315,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);                                     
 
@@ -4687,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;
-               TypeSpec 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 (!expr_type.ImplementsInterface (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 (expr_type != InternalType.Dynamic) {
+                               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, TypeSpec.EmptyTypes);
-                       }
-
                        return ok;
                }
 
                        return ok;
                }
 
@@ -4745,34 +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)
                {
-                       if (!TypeManager.IsStruct (expr_type)) {
-                               Label skip = ec.DefineLabel ();
-                               local_copy.Emit (ec);
-                               ec.Emit (OpCodes.Brfalse, skip);
-                               local_copy.Emit (ec);
-                               ec.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               ec.MarkLabel (skip);
-                               return;
-                       }
-
-                       MethodSpec ms = MemberCache.FindMember (expr_type,
-                               MemberFilter.Method ("Dispose", 0, ParametersCompiled.EmptyReadOnlyParameters, TypeManager.void_type),
-                               BindingRestriction.InstanceOnly) as MethodSpec;
-
-                       if (ms == null) {
-                               local_copy.Emit (ec);
-                               ec.Emit (OpCodes.Box, expr_type);
-                               ec.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               return;
-                       }
-
-                       local_copy.AddressOf (ec, AddressOp.Load);
-                       ec.Emit (OpCodes.Call, ms);
+                       dispose_call.Emit (ec);
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -4780,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);
                }
        }
 
                }
        }
 
@@ -4830,7 +4918,7 @@ namespace Mono.CSharp {
                                ec.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)
                                ec.MarkLabel (skip);
 
                        if (emit_null_check)
                                ec.MarkLabel (skip);
@@ -4980,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;
 
@@ -5069,16 +5157,16 @@ namespace Mono.CSharp {
                        }
                }
 
                        }
                }
 
-               sealed class CollectionForeach : Statement
+               sealed class CollectionForeach : Statement, MethodGroupExpr.IErrorHandler
                {
                {
-                       class CollectionForeachStatement : Statement
+                       class Body : Statement
                        {
                                TypeSpec type;
                                Expression variable, current, conv;
                                Statement statement;
                                Assign assign;
 
                        {
                                TypeSpec type;
                                Expression variable, current, conv;
                                Statement statement;
                                Assign assign;
 
-                               public CollectionForeachStatement (TypeSpec type, Expression variable,
+                               public Body (TypeSpec type, Expression variable,
                                                                   Expression current, Statement statement,
                                                                   Location loc)
                                {
                                                                   Expression current, Statement statement,
                                                                   Location loc)
                                {
@@ -5121,20 +5209,59 @@ namespace Mono.CSharp {
                                }
                        }
 
                                }
                        }
 
-                       Expression variable, expr;
-                       Statement statement;
+                       class Dispose : UsingTemporary
+                       {
+                               LocalTemporary dispose;
+
+                               public Dispose (TemporaryVariable variable, LocalTemporary dispose, Expression expr, Statement statement, Location loc)
+                                       : base (expr, statement, loc)
+                               {
+                                       base.local_copy = variable;
+                                       this.dispose = dispose;
+                               }
+
+                               protected override bool DoResolve (BlockContext ec)
+                               {
+                                       if (TypeManager.void_dispose_void == null) {
+                                               TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
+                                                       TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes);
+                                       }
+
+                                       Expression dispose_var = (Expression) dispose ?? local_copy;
+
+                                       var dispose_mg = MethodGroupExpr.CreatePredefined (TypeManager.void_dispose_void, TypeManager.idisposable_type, loc);
+                                       dispose_mg.InstanceExpression = dispose_var;
+
+                                       dispose_call = new StatementExpression (new Invocation (dispose_mg, null));
 
 
-                       TemporaryVariable enumerator;
-                       Expression init;
-                       Statement loop;
-                       Statement wrapper;
+                                       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);
+                                       }
+                               }
+                       }
 
 
-                       MethodGroupExpr get_enumerator;
-                       PropertyExpr get_current;
-                       MethodSpec move_next;
+                       Expression variable, expr;
+                       Statement statement;
                        Expression var_type;
                        Expression var_type;
-                       TypeSpec 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)
@@ -5151,405 +5278,215 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
                                throw new NotImplementedException ();
                        }
 
-                       bool GetEnumeratorFilter (ResolveContext ec, MethodSpec mi)
+                       void Error_WrongEnumerator (ResolveContext rc, MethodSpec enumerator)
                        {
                        {
-                               TypeSpec 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 ||
-                                       return_type.ImplementsInterface (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, TypeSpec.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 (TypeSpec t)
+                       MethodGroupExpr ResolveMoveNext (ResolveContext rc, MethodSpec enumerator)
                        {
                        {
-                               move_next = MemberCache.FindMember (t,
+                               var ms = MemberCache.FindMember (enumerator.ReturnType,
                                        MemberFilter.Method ("MoveNext", 0, ParametersCompiled.EmptyReadOnlyParameters, TypeManager.bool_type),
                                        BindingRestriction.InstanceOnly) as MethodSpec;
 
                                        MemberFilter.Method ("MoveNext", 0, ParametersCompiled.EmptyReadOnlyParameters, TypeManager.bool_type),
                                        BindingRestriction.InstanceOnly) as MethodSpec;
 
-                               return move_next != null && (move_next.Modifiers & Modifiers.PUBLIC) != 0;
-                       }
-               
-                       //
-                       // Retrieves a `public T get_Current ()' method from the Type `t'
-                       //
-                       bool FetchGetCurrent (ResolveContext ec, TypeSpec t)
-                       {
-                               PropertyExpr pe = Expression.MemberLookup (ec.Compiler,
-                                       ec.CurrentType, t, "Current", 0, MemberKind.Property,
-                                       BindingRestriction.AccessibleOnly, loc) as PropertyExpr;
-                               if (pe == null)
-                                       return false;
+                               if (ms == null || !ms.IsPublic) {
+                                       Error_WrongEnumerator (rc, enumerator);
+                                       return null;
+                               }
 
 
-                               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 TryType (ResolveContext ec, TypeSpec t)
+                       public override bool Resolve (BlockContext ec)
                        {
                        {
-                               var mg = Expression.MemberLookup (ec.Compiler, ec.CurrentType, null, t, "GetEnumerator", 0,
-                                       MemberKind.Method, BindingRestriction.NoOverrides | BindingRestriction.InstanceOnly, loc) as MethodGroupExpr;
+                               bool is_dynamic = expr.Type == InternalType.Dynamic;
+                               if (is_dynamic)
+                                       expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc);
 
 
-                               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;
-                               TypeSpec tmp_enumerator_type = enumerator_type;
-                               foreach (MethodSpec mi in mg.Methods) {
-                                       if (!mi.Parameters.IsEmpty)
-                                               continue;
-                       
-                                       // Check whether GetEnumerator is public
-                                       if ((mi.Modifiers & Modifiers.AccessibilityMask) != Modifiers.PUBLIC)
-                                               continue;
-
-                                       enumerator_found = true;
-
-                                       if (!GetEnumeratorFilter (ec, mi))
-                                               continue;
-
-                                       if (result != null) {
-                                               if (TypeManager.IsGenericType (result.ReturnType)) {
-                                                       if (!TypeManager.IsGenericType (mi.ReturnType))
-                                                               continue;
-
-                                                       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.generic_ienumerable_type.GetSignatureForError ());
-                                                       return false;
-                                               }
-
-                                               // Always prefer generics enumerators
-                                               if (!TypeManager.IsGenericType (mi.ReturnType)) {
-                                                       if (mi.DeclaringType.ImplementsInterface (result.DeclaringType) ||
-                                                               result.DeclaringType.ImplementsInterface (mi.DeclaringType))
-                                                               continue;
-
-                                                       ec.Report.SymbolRelatedToPreviousError (result);
-                                                       ec.Report.SymbolRelatedToPreviousError (mi);
-                                                       ec.Report.Warning (278, 2, loc, "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'",
-                                                                       TypeManager.CSharpName (t), "enumerable", result.GetSignatureForError (), mi.GetSignatureForError ());
-                                                       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;
-                                       get_enumerator = new MethodGroupExpr (result, 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, TypeSpec t)
-                       {
-                               int errors = ec.Report.Errors;
-                               for (TypeSpec 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
-                               //
-                               for (TypeSpec tt = t; tt != null && tt != TypeManager.object_type; ) {
-                                       if (tt.Interfaces != null) {
-                                               foreach (TypeSpec i in tt.Interfaces) {
-                                                       if (TryType (ec, i))
-                                                               return true;
-                                               }
-                                       }
-                                       tt = tt.BaseType;
                                }
 
                                }
 
-                               return false;
-                       }
-
-                       public override bool Resolve (BlockContext ec)
-                       {
-                               enumerator_type = TypeManager.ienumerator_type;
-
-                               bool is_dynamic = expr.Type == InternalType.Dynamic;
-                               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.Type,
-                                               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 List<MemberSpec> (1) { 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 = enumerator_type.ImplementsInterface (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);
-                       }
-
-                       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);
-                               }
+                               if (init != null)
+                                       init.EmitStatement (ec);
 
 
-                               protected override void DoEmit (EmitContext ec)
-                               {
-                                       parent.EmitLoopInit (ec);
-                                       parent.EmitLoopBody (ec);
-                               }
+                               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, TypeSpec.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)) {
-
-                                               parent.enumerator.Emit (ec);
-
-                                               Label call_dispose = ec.DefineLabel ();
-
-                                               if (!implements_idisposable) {
-                                                       ec.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
-                                                       LocalTemporary temp = new LocalTemporary (TypeManager.idisposable_type);
-                                                       temp.Store (ec);
-                                                       temp.Emit (ec);
-                                                       instance = temp;
-                                               }
-                                               
-                                               ec.Emit (OpCodes.Brtrue_S, call_dispose);
+                       #region IErrorHandler Members
 
 
-                                               // using 'endfinally' to empty the evaluation stack
-                                               ec.Emit (OpCodes.Endfinally);
-                                               ec.MarkLabel (call_dispose);
-                                       }
-
-                                       Invocation.EmitCall (ec, false, instance, TypeManager.void_dispose_void, null, loc);
-                               }
-                       }
-
-                       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;
                        }
                        }
+
+                       #endregion
                }
 
                Expression type;
                }
 
                Expression type;