2008-09-17 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / expression.cs
index dd377611ec1335077400decda324eab6a97b2b62..b3a88cccca53b401678513fbbfe2904bc8d030a2 100644 (file)
@@ -3,7 +3,7 @@
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
-//   Marek Safar (marek.safar@seznam.cz)
+//   Marek Safar (marek.safar@gmail.com)
 //
 // Copyright 2001, 2002, 2003 Ximian, Inc.
 // Copyright 2003-2008 Novell, Inc.
@@ -54,6 +54,11 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall ("Call", args);
                }
 
+               protected override void CloneTo (CloneContext context, Expression target)
+               {
+                       // Nothing to clone
+               }
+               
                public override Expression DoResolve (EmitContext ec)
                {
                        //
@@ -67,31 +72,17 @@ namespace Mono.CSharp {
                        mg.EmitCall (ec, arguments);
                }
 
-               [Obsolete ("It may not be compatible with expression trees")]
-               static public UserOperatorCall MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
-                                                        Expression e, Location loc)
-               {
-                       ArrayList args;
-                       
-                       args = new ArrayList (1);
-                       Argument a = new Argument (e, Argument.AType.Expression);
-
-                        // We need to resolve the arguments before sending them in !
-                        if (!a.Resolve (ec, loc))
-                                return null;
-
-                        args.Add (a);
-                       mg = mg.OverloadResolve (ec, ref args, false, loc);
-
-                       if (mg == null)
-                               return null;
-
-                       return new UserOperatorCall (mg, args, null, loc);
-               }
-
                public MethodGroupExpr Method {
                        get { return mg; }
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (Argument a in arguments)
+                               a.Expr.MutateHoistedGenericType (storey);
+
+                       mg.MutateHoistedGenericType (storey);
+               }
        }
 
        public class ParenthesizedExpression : Expression
@@ -156,6 +147,9 @@ namespace Mono.CSharp {
                // </summary>
                Constant TryReduceConstant (EmitContext ec, Constant e)
                {
+                       if (e is EmptyConstantCast)
+                               return TryReduceConstant (ec, ((EmptyConstantCast) e).child);
+                       
                        if (e is SideEffectConstant) {
                                Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
                                return r == null ? null : new SideEffectConstant (r, e, r.Location);
@@ -449,13 +443,6 @@ namespace Mono.CSharp {
                public override Expression DoResolve (EmitContext ec)
                {
                        if (Oper == Operator.AddressOf) {
-                               Expr = Expr.DoResolveLValue (ec, new EmptyExpression ());
-
-                               if (Expr == null || Expr.eclass != ExprClass.Variable){
-                                       Error (211, "Cannot take the address of the given expression");
-                                       return null;
-                               }
-
                                return ResolveAddressOf (ec);
                        }
 
@@ -594,10 +581,20 @@ namespace Mono.CSharp {
                        throw new NotImplementedException (oper.ToString ());
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       type = storey.MutateType (type);
+                       Expr.MutateHoistedGenericType (storey);
+               }
+
                Expression ResolveAddressOf (EmitContext ec)
                {
-                       if (!ec.InUnsafe) {
+                       if (!ec.InUnsafe)
                                UnsafeError (loc);
+
+                       Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
+                       if (Expr == null || Expr.eclass != ExprClass.Variable) {
+                               Error (211, "Cannot take the address of the given expression");
                                return null;
                        }
 
@@ -605,40 +602,35 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       IVariable variable = Expr as IVariable;
-                       bool is_fixed = variable != null && variable.VerifyFixed ();
+                       IVariableReference vr = Expr as IVariableReference;
+                       bool is_fixed;
+                       if (vr != null) {
+                               VariableInfo vi = vr.VariableInfo;
+                               if (vi != null) {
+                                       if (vi.LocalInfo != null)
+                                               vi.LocalInfo.Used = true;
 
-                       if (!ec.InFixedInitializer && !is_fixed) {
-                               Error (212, "You can only take the address of unfixed expression inside " +
-                                          "of a fixed statement initializer");
-                               return null;
-                       }
+                                       //
+                                       // A variable is considered definitely assigned if you take its address.
+                                       //
+                                       vi.SetAssigned (ec);
+                               }
 
-                       if (ec.InFixedInitializer && is_fixed) {
-                               Error (213, "You cannot use the fixed statement to take the address of an already fixed expression");
-                               return null;
-                       }
+                               is_fixed = vr.IsFixedVariable;
+                               vr.SetHasAddressTaken ();
 
-                       LocalVariableReference lr = Expr as LocalVariableReference;
-                       if (lr != null) {
-                               if (lr.local_info.IsCaptured) {
-                                       AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
-                                       return null;
+                               if (vr.IsHoisted) {
+                                       AnonymousMethodExpression.Error_AddressOfCapturedVar (vr, loc);
                                }
-                               lr.local_info.AddressTaken = true;
-                               lr.local_info.Used = true;
-                       }
-
-                       ParameterReference pr = Expr as ParameterReference;
-                       if ((pr != null) && pr.Parameter.IsCaptured) {
-                               AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
-                               return null;
+                       } else {
+                               //
+                               // A pointer-indirection is always fixed
+                               //
+                               is_fixed = Expr is Indirection;
                        }
 
-                       // According to the specs, a variable is considered definitely assigned if you take
-                       // its address.
-                       if ((variable != null) && (variable.VariableInfo != null)) {
-                               variable.VariableInfo.SetAssigned (ec);
+                       if (!is_fixed && !ec.InFixedInitializer) {
+                               Error (212, "You can only take the address of unfixed expression inside of a fixed statement initializer");
                        }
 
                        type = TypeManager.GetPointerType (Expr.Type);
@@ -762,7 +754,7 @@ namespace Mono.CSharp {
        // after semantic analysis (this is so we can take the address
        // of an indirection).
        //
-       public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
                Expression expr;
                LocalTemporary temporary;
                bool prepared;
@@ -779,6 +771,12 @@ namespace Mono.CSharp {
                        return null;
                }
                
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       Indirection target = (Indirection) t;
+                       target.expr = expr.Clone (clonectx);
+               }               
+               
                public override void Emit (EmitContext ec)
                {
                        if (!prepared)
@@ -845,29 +843,20 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if (expr.Type == TypeManager.void_ptr_type) {
+                               Error (242, "The operation in question is undefined on void pointers");
+                               return null;
+                       }
+
                        type = TypeManager.GetElementType (expr.Type);
                        eclass = ExprClass.Variable;
                        return this;
                }
-               
+
                public override string ToString ()
                {
                        return "*(" + expr + ")";
                }
-
-               #region IVariable Members
-
-               public VariableInfo VariableInfo {
-                       get { return null; }
-               }
-
-               public bool VerifyFixed ()
-               {
-                       // A pointer-indirection is always fixed.
-                       return true;
-               }
-
-               #endregion
        }
        
        /// <summary>
@@ -947,12 +936,12 @@ namespace Mono.CSharp {
 
                Expression ResolveOperator (EmitContext ec)
                {
-                       Type expr_type = expr.Type;
+                       type = expr.Type;
 
                        //
                        // Step 1: Perform Operator Overload location
                        //
-                       Expression mg;
+                       MethodGroupExpr mg;
                        string op_name;
                        
                        if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
@@ -960,17 +949,24 @@ namespace Mono.CSharp {
                        else
                                op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
 
-                       mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+                       mg = MemberLookup (ec.ContainerType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
 
                        if (mg != null) {
-                               method = UserOperatorCall.MakeSimpleCall (
-                                       ec, (MethodGroupExpr) mg, expr, loc);
+                               ArrayList args = new ArrayList (1);
+                               args.Add (new Argument (expr, Argument.AType.Expression));
+                               mg = mg.OverloadResolve (ec, ref args, false, loc);
+                               if (mg == null)
+                                       return null;
 
-                               type = method.Type;
-                       } else if (!IsIncrementableNumber (expr_type)) {
+                               method = new UserOperatorCall (mg, args, null, loc);
+                               Convert.ImplicitConversionRequired (ec, method, type, loc);
+                               return this;
+                       }
+
+                       if (!IsIncrementableNumber (type)) {
                                Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
-                                      TypeManager.CSharpName (expr_type) + "'");
-                                  return null;
+                                          TypeManager.CSharpName (type) + "'");
+                               return null;
                        }
 
                        //
@@ -978,20 +974,10 @@ namespace Mono.CSharp {
                        // should be an expression that is classified as a variable,
                        // a property access or an indexer access
                        //
-                       type = expr_type;
-                       if (expr.eclass == ExprClass.Variable){
-                               LocalVariableReference var = expr as LocalVariableReference;
-                               if ((var != null) && var.IsReadOnly) {
-                                       Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
-                                       return null;
-                               }
-                       } else if (expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess){
-                               expr = expr.ResolveLValue (ec, this, Location);
-                               if (expr == null)
-                                       return null;
+                       if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
+                               expr = expr.ResolveLValue (ec, expr, Location);
                        } else {
                                Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
-                               return null;
                        }
 
                        return this;
@@ -1043,8 +1029,10 @@ namespace Mono.CSharp {
                                
                                if (n == 0)
                                        ig.Emit (OpCodes.Sizeof, et);
-                               else
+                               else {
                                        IntConstant.EmitInt (ig, n);
+                                       ig.Emit (OpCodes.Conv_I);
+                               }
                        } else 
                                ig.Emit (OpCodes.Ldc_I4_1);
 
@@ -1154,6 +1142,11 @@ namespace Mono.CSharp {
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return null;
+
+                       if ((probe_type_expr.Type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                               Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type",
+                                       OperatorName);
+                       }
                        
                        if (expr.Type.IsPointer || probe_type_expr.Type.IsPointer) {
                                Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type",
@@ -1170,6 +1163,12 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+                       probe_type_expr.MutateHoistedGenericType (storey);
+               }
+
                protected abstract string OperatorName { get; }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -1247,14 +1246,14 @@ namespace Mono.CSharp {
                        Type d = expr.Type;
                        bool d_is_nullable = false;
 
-                       if (expr is Constant) {
-                               //
-                               // If E is a method group or the null literal, of if the type of E is a reference
-                               // type or a nullable type and the value of E is null, the result is false
-                               //
-                               if (expr.IsNull)
-                                       return CreateConstantResult (false);
-                       } else if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
+                       //
+                       // If E is a method group or the null literal, or if the type of E is a reference
+                       // type or a nullable type and the value of E is null, the result is false
+                       //
+                       if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
+                               return CreateConstantResult (false);
+
+                       if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
                                d = TypeManager.GetTypeArguments (d) [0];
                                d_is_nullable = true;
                        }
@@ -1326,10 +1325,12 @@ namespace Mono.CSharp {
                                        return CreateConstantResult (false);
 
                                if (constraints.IsValueType && !d.IsValueType)
-                                       return CreateConstantResult (false);
+                                       return CreateConstantResult (TypeManager.IsEqual (d, t));
                        }
 
-                       expr = new BoxedCast (expr, d);
+                       if (!TypeManager.IsReferenceType (expr.Type))
+                               expr = new BoxedCast (expr, d);
+
                        return this;
 #else
                        return null;
@@ -1376,13 +1377,6 @@ namespace Mono.CSharp {
 #endif
                }
 
-               static void Error_CannotConvertType (Type source, Type target, Location loc)
-               {
-                       Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
-                               TypeManager.CSharpName (source),
-                               TypeManager.CSharpName (target));
-               }
-               
                public override Expression DoResolve (EmitContext ec)
                {
                        if (resolved_type == null) {
@@ -1396,38 +1390,19 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                        Type etype = expr.Type;
 
-                       if (type.IsValueType && !TypeManager.IsNullableType (type)) {
-                               Report.Error (77, loc, "The `as' operator cannot be used with a non-nullable value type `{0}'",
-                                             TypeManager.CSharpName (type));
-                               return null;
-                       
-                       }
-
-#if GMCS_SOURCE
-                       //
-                       // If the type is a type parameter, ensure
-                       // that it is constrained by a class
-                       //
-                       TypeParameterExpr tpe = probe_type_expr as TypeParameterExpr;
-                       if (tpe != null){
-                               GenericConstraints constraints = tpe.TypeParameter.GenericConstraints;
-                               bool error = false;
-                               
-                               if (constraints == null)
-                                       error = true;
-                               else {
-                                       if (!constraints.HasClassConstraint)
-                                               if ((constraints.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == 0)
-                                                       error = true;
-                               }
-                               if (error){
+                       if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) {
+                               if (probe_type_expr is TypeParameterExpr) {
                                        Report.Error (413, loc,
-                                                     "The as operator requires that the `{0}' type parameter be constrained by a class",
-                                                     probe_type_expr.GetSignatureForError ());
-                                       return null;
+                                               "The `as' operator cannot be used with a non-reference type parameter `{0}'",
+                                               probe_type_expr.GetSignatureForError ());
+                               } else {
+                                       Report.Error (77, loc,
+                                               "The `as' operator cannot be used with a non-nullable value type `{0}'",
+                                               TypeManager.CSharpName (type));
                                }
+                               return null;
                        }
-#endif
+
                        if (expr.IsNull && TypeManager.IsNullableType (type)) {
                                return Nullable.LiftedNull.CreateFromExpression (this);
                        }
@@ -1454,7 +1429,9 @@ namespace Mono.CSharp {
                                return this;
                        }
 
-                       Error_CannotConvertType (etype, type, loc);
+                       Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
+                               TypeManager.CSharpName (etype), TypeManager.CSharpName (type));
+
                        return null;
                }
 
@@ -1462,9 +1439,9 @@ namespace Mono.CSharp {
                        get { return "as"; }
                }
        
-               public override bool GetAttributableValue (Type value_type, out object value)
+               public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
                {
-                       return expr.GetAttributableValue (value_type, out value);
+                       return expr.GetAttributableValue (ec, value_type, out value);
                }
        }
        
@@ -1488,9 +1465,6 @@ namespace Mono.CSharp {
                        this.target_type = cast_type;
                        this.expr = expr;
                        this.loc = loc;
-
-                       if (target_type == TypeManager.system_void_expr)
-                               Error_VoidInvalidInTheContext (loc);
                }
 
                public Expression TargetType {
@@ -1583,23 +1557,24 @@ namespace Mono.CSharp {
 
                        type = texpr.Type;
 
-                       if (type == TypeManager.void_type) {
-                               Error_VoidInvalidInTheContext (loc);
-                               return null;
+                       if ((type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                               Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type");
                        }
 
-                       if (TypeManager.IsGenericParameter (type)) {
-                               GenericConstraints constraints = TypeManager.GetTypeParameterConstraints(type);
-                               if (constraints != null && constraints.IsReferenceType)
-                                       return new EmptyConstantCast (new NullLiteral (Location), type);
-                       } else {
-                               Constant c = New.Constantify (type);
-                               if (c != null)
-                                       return c;
+                       if (type.IsPointer)
+                               return new NullLiteral (Location).ConvertImplicitly (type);
+
+                       if (TypeManager.IsReferenceType (type)) {
+                               return new EmptyConstantCast (new NullLiteral (Location), type);
 
-                               if (!TypeManager.IsValueType (type))
-                                       return new EmptyConstantCast (new NullLiteral (Location), type);
+                               // TODO: ET needs
+                               // return ReducedExpression.Create (new NullLiteral (Location), this);
                        }
+
+                       Constant c = New.Constantify (type);
+                       if (c != null)
+                               return c;
+
                        eclass = ExprClass.Variable;
                        return this;
                }
@@ -1612,6 +1587,11 @@ namespace Mono.CSharp {
                        ec.ig.Emit(OpCodes.Initobj, type);
                        temp_storage.Emit(ec);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       type = storey.MutateType (type);
+               }
                
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
@@ -1662,21 +1642,26 @@ namespace Mono.CSharp {
                        {
                                b.type = ReturnType;
 
-                               if (left != null)
-                                       b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
+                               b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
+                               b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
 
-                               if (right != null)
-                                       b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
+                               //
+                               // A user operators does not support multiple user conversions, but decimal type
+                               // is considered to be predefined type therefore we apply predefined operators rules
+                               // and then look for decimal user-operator implementation
+                               //
+                               if (left == TypeManager.decimal_type)
+                                       return b.ResolveUserOperator (ec, b.left.Type, b.right.Type);
 
                                return b;
                        }
 
-                       public bool IsPrimitiveApplicable (Type type)
+                       public bool IsPrimitiveApplicable (Type ltype, Type rtype)
                        {
                                //
                                // We are dealing with primitive types only
                                //
-                               return left == type;
+                               return left == ltype && ltype == rtype;
                        }
 
                        public virtual bool IsApplicable (EmitContext ec, Expression lexpr, Expression rexpr)
@@ -1689,7 +1674,7 @@ namespace Mono.CSharp {
                                        Convert.ImplicitConversionExists (ec, rexpr, right);
                        }
 
-                       public PredefinedOperator ResolveBetterOperator (EmitContext ec, Expression lexpr, Expression rexpr, PredefinedOperator best_operator)
+                       public PredefinedOperator ResolveBetterOperator (EmitContext ec, PredefinedOperator best_operator)
                        {
                                int result = 0;
                                if (left != null && best_operator.left != null) {
@@ -1699,7 +1684,7 @@ namespace Mono.CSharp {
                                //
                                // When second arguments are same as the first one, the result is same
                                //
-                               if (left != right || best_operator.left != best_operator.right) {
+                               if (right != null && (left != right || best_operator.left != best_operator.right)) {
                                        result |= MethodGroupExpr.BetterTypeConversion (ec, best_operator.right, right);
                                }
 
@@ -1781,6 +1766,11 @@ namespace Mono.CSharp {
                        {
                        }
 
+                       public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask, Type retType)
+                               : base (ltype, rtype, op_mask, retType)
+                       {
+                       }
+
                        public PredefinedPointerOperator (Type type, Operator op_mask, Type return_type)
                                : base (type, op_mask, return_type)
                        {
@@ -1809,12 +1799,17 @@ namespace Mono.CSharp {
 
                        public override Expression ConvertResult (EmitContext ec, Binary b)
                        {
-                               base.ConvertResult (ec, b);
+                               if (left != null) {
+                                       b.left = EmptyCast.Create (b.left, left);
+                               } else if (right != null) {
+                                       b.right = EmptyCast.Create (b.right, right);
+                               }
 
                                Type r_type = ReturnType;
                                if (r_type == null) {
-                                       r_type = b.left.Type;
-                                       if (r_type == null)
+                                       if (left == null)
+                                               r_type = b.left.Type;
+                                       else 
                                                r_type = b.right.Type;
                                }
 
@@ -1962,18 +1957,12 @@ namespace Mono.CSharp {
                        return s;
                }
 
-               static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
+               public static void Error_OperatorCannotBeApplied (Expression left, Expression right, Operator oper, Location loc)
                {
-                       Error_OperatorCannotBeApplied (loc, name, TypeManager.CSharpName (l), TypeManager.CSharpName (r));
+                       new Binary (oper, left, right).Error_OperatorCannotBeApplied (left, right);
                }
 
-               public static void Error_OperatorCannotBeApplied (Location loc, string name, string left, string right)
-               {
-                       Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'",
-                               name, left, right);
-               }
-               
-               protected void Error_OperatorCannotBeApplied (Expression left, Expression right)
+               public static void Error_OperatorCannotBeApplied (Expression left, Expression right, string oper, Location loc)
                {
                        string l, r;
                        // TODO: This should be handled as Type of method group in CSharpName
@@ -1987,7 +1976,13 @@ namespace Mono.CSharp {
                        else
                                r = TypeManager.CSharpName (right.Type);
 
-                       Error_OperatorCannotBeApplied (Location, OperName (oper), l, r);
+                       Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'",
+                               oper, l, r);
+               }
+               
+               protected void Error_OperatorCannotBeApplied (Expression left, Expression right)
+               {
+                       Error_OperatorCannotBeApplied (left, right, OperName (oper), loc);
                }
 
                static string GetOperatorMetadataName (Operator op)
@@ -2168,8 +2163,8 @@ namespace Mono.CSharp {
 
                static bool IsUnsigned (Type t)
                {
-                       while (t.IsPointer)
-                               t = TypeManager.GetElementType (t);
+                       if (t.IsPointer)
+                               return true;
 
                        return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
                                t == TypeManager.ushort_type || t == TypeManager.byte_type);
@@ -2332,10 +2327,10 @@ namespace Mono.CSharp {
                        // T* operator + (long y,  T *x);
                        // T* operator + (ulong y, T *x);
                        //
-                       temp.Add (new PredefinedPointerOperator (TypeManager.int32_type, null, Operator.AdditionMask));
-                       temp.Add (new PredefinedPointerOperator (TypeManager.uint32_type, null, Operator.AdditionMask));
-                       temp.Add (new PredefinedPointerOperator (TypeManager.int64_type, null, Operator.AdditionMask));
-                       temp.Add (new PredefinedPointerOperator (TypeManager.uint64_type, null, Operator.AdditionMask));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.int32_type, null, Operator.AdditionMask, null));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.uint32_type, null, Operator.AdditionMask, null));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.int64_type, null, Operator.AdditionMask, null));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.uint64_type, null, Operator.AdditionMask, null));
 
                        //
                        // long operator - (T* x, T *y)
@@ -2356,6 +2351,7 @@ namespace Mono.CSharp {
                        temp.Add (new PredefinedOperator (TypeManager.uint64_type, Operator.ArithmeticMask | Operator.BitwiseMask));
                        temp.Add (new PredefinedOperator (TypeManager.float_type, Operator.ArithmeticMask));
                        temp.Add (new PredefinedOperator (TypeManager.double_type, Operator.ArithmeticMask));
+                       temp.Add (new PredefinedOperator (TypeManager.decimal_type, Operator.ArithmeticMask));
 
                        temp.Add (new PredefinedOperator (TypeManager.int32_type, Operator.ComparisonMask, bool_type));
                        temp.Add (new PredefinedOperator (TypeManager.uint32_type, Operator.ComparisonMask, bool_type));
@@ -2363,6 +2359,7 @@ namespace Mono.CSharp {
                        temp.Add (new PredefinedOperator (TypeManager.uint64_type, Operator.ComparisonMask, bool_type));
                        temp.Add (new PredefinedOperator (TypeManager.float_type, Operator.ComparisonMask, bool_type));
                        temp.Add (new PredefinedOperator (TypeManager.double_type, Operator.ComparisonMask, bool_type));
+                       temp.Add (new PredefinedOperator (TypeManager.decimal_type, Operator.ComparisonMask, bool_type));
 
                        temp.Add (new PredefinedOperator (TypeManager.string_type, Operator.EqualityMask, bool_type));
 
@@ -2543,13 +2540,14 @@ namespace Mono.CSharp {
                                                return null;
                                        }
 
-                                       if (rc != null) {
-                                               right = left;
-                                               lc = rc;
-                                       }
-
+                                       //
                                        // The result is a constant with side-effect
-                                       return new SideEffectConstant (lc, right, loc);
+                                       //
+                                       Constant side_effect = rc == null ?
+                                               new SideEffectConstant (lc, right, loc) :
+                                               new SideEffectConstant (rc, left, loc);
+
+                                       return ReducedExpression.Create (side_effect, this);
                                }
                        }
 
@@ -2585,6 +2583,12 @@ namespace Mono.CSharp {
                        return expr;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       left.MutateHoistedGenericType (storey);
+                       right.MutateHoistedGenericType (storey);
+               }
+
                //
                // D operator + (D x, D y)
                // D operator - (D x, D y)
@@ -2676,6 +2680,23 @@ namespace Mono.CSharp {
                        Expression ltemp = left;
                        Expression rtemp = right;
                        Type underlying_type;
+                       Expression expr;
+                       
+                       if ((oper & Operator.ComparisonMask | Operator.BitwiseMask) != 0) {
+                               if (renum) {
+                                       expr = Convert.ImplicitConversion (ec, left, rtype, loc);
+                                       if (expr != null) {
+                                               left = expr;
+                                               ltype = expr.Type;
+                                       }
+                               } else if (lenum) {
+                                       expr = Convert.ImplicitConversion (ec, right, ltype, loc);
+                                       if (expr != null) {
+                                               right = expr;
+                                               rtype = expr.Type;
+                                       }
+                               }
+                       }                       
 
                        if (TypeManager.IsEqual (ltype, rtype)) {
                                underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
@@ -2690,29 +2711,43 @@ namespace Mono.CSharp {
                                else
                                        right = EmptyCast.Create (right, underlying_type);
                        } else if (lenum) {
+                               underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
+
                                if (oper != Operator.Subtraction && oper != Operator.Addition) {
                                        Constant c = right as Constant;
                                        if (c == null || !c.IsDefaultValue)
                                                return null;
+                               } else {
+                                       if (!Convert.ImplicitStandardConversionExists (right, underlying_type))
+                                               return null;
+
+                                       right = Convert.ImplicitConversionStandard (ec, right, underlying_type, right.Location);
                                }
 
-                               underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
                                if (left is Constant)
                                        left = ((Constant) left).ConvertExplicitly (false, underlying_type);
                                else
                                        left = EmptyCast.Create (left, underlying_type);
+
                        } else if (renum) {
+                               underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
+
                                if (oper != Operator.Addition) {
                                        Constant c = left as Constant;
                                        if (c == null || !c.IsDefaultValue)
                                                return null;
+                               } else {
+                                       if (!Convert.ImplicitStandardConversionExists (left, underlying_type))
+                                               return null;
+
+                                       left = Convert.ImplicitConversionStandard (ec, left, underlying_type, left.Location);
                                }
 
-                               underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
                                if (right is Constant)
                                        right = ((Constant) right).ConvertExplicitly (false, underlying_type);
                                else
                                        right = EmptyCast.Create (right, underlying_type);
+
                        } else {
                                return null;
                        }
@@ -2741,7 +2776,7 @@ namespace Mono.CSharp {
                                        res_type = ltype;
                        }
                        
-                       Expression expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
+                       expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
                        if (!is_compound || expr == null)
                                return expr;
 
@@ -2922,6 +2957,7 @@ namespace Mono.CSharp {
                {
                        PredefinedOperator best_operator = null;
                        Type l = left.Type;
+                       Type r = right.Type;
                        Operator oper_mask = oper & ~Operator.ValuesOnlyMask;
 
                        foreach (PredefinedOperator po in operators) {
@@ -2929,7 +2965,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (primitives_only) {
-                                       if (!po.IsPrimitiveApplicable (l))
+                                       if (!po.IsPrimitiveApplicable (l, r))
                                                continue;
                                } else {
                                        if (!po.IsApplicable (ec, left, right))
@@ -2944,7 +2980,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               best_operator = po.ResolveBetterOperator (ec, left, right, best_operator);
+                               best_operator = po.ResolveBetterOperator (ec, best_operator);
 
                                if (best_operator == null) {
                                        Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
@@ -3120,7 +3156,7 @@ namespace Mono.CSharp {
                                WarnUselessComparison (type);
                }
 
-               private bool IsValueOutOfRange (long value, Type type)
+               static bool IsValueOutOfRange (long value, Type type)
                {
                        if (IsTypeUnsigned (type) && value < 0)
                                return true;
@@ -3261,7 +3297,8 @@ namespace Mono.CSharp {
                        right.Emit (ec);
 
                        Type t = left.Type;
-                       bool is_unsigned = IsUnsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
+                       bool is_float = IsFloat (t);
+                       bool is_unsigned = is_float || IsUnsigned (t);
                        
                        switch (oper){
                        case Operator.Equality:
@@ -3280,7 +3317,7 @@ namespace Mono.CSharp {
 
                        case Operator.LessThan:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Blt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Blt, target);
@@ -3293,7 +3330,7 @@ namespace Mono.CSharp {
 
                        case Operator.GreaterThan:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Bgt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bgt, target);
@@ -3306,7 +3343,7 @@ namespace Mono.CSharp {
 
                        case Operator.LessThanOrEqual:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Ble_Un, target);
                                        else
                                                ig.Emit (OpCodes.Ble, target);
@@ -3320,7 +3357,7 @@ namespace Mono.CSharp {
 
                        case Operator.GreaterThanOrEqual:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Bge_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bge, target);
@@ -3609,6 +3646,12 @@ namespace Mono.CSharp {
                        if (concat != null)
                                concat.Emit (ec);
                }
+               
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (Argument a in arguments)
+                               a.Expr.MutateHoistedGenericType (storey);
+               }               
        }
 
        //
@@ -3629,7 +3672,7 @@ namespace Mono.CSharp {
                {
                        MethodInfo method = (MethodInfo)mg;
                        type = TypeManager.TypeToCoreType (method.ReturnType);
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) {
                                Report.Error (217, loc,
                                        "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
@@ -3710,14 +3753,21 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        // It must be either array or fixed buffer
-                       Type element = TypeManager.HasElementType (op_type) ?
-                               element = TypeManager.GetElementType (op_type) :
-                               element = AttributeTester.GetFixedBuffer (((FieldExpr)left).FieldInfo).ElementType;
+                       Type element;
+                       if (TypeManager.HasElementType (op_type)) {
+                               element = TypeManager.GetElementType (op_type);
+                       } else {
+                               FieldExpr fe = left as FieldExpr;
+                               if (fe != null)
+                                       element = AttributeTester.GetFixedBuffer (fe.FieldInfo).ElementType;
+                               else
+                                       element = op_type;
+                       }
 
                        int size = GetTypeSize (element);
                        Type rtype = right.Type;
                        
-                       if (rtype.IsPointer){
+                       if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){
                                //
                                // handle (pointer - pointer)
                                //
@@ -3738,32 +3788,48 @@ namespace Mono.CSharp {
                                // handle + and - on (pointer op int)
                                //
                                left.Emit (ec);
-                               ig.Emit (OpCodes.Conv_I);
 
                                Constant right_const = right as Constant;
-                               if (right_const != null && size != 0) {
-                                       Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size, right.Location), right_const, loc);
-                                       if (ex == null)
+                               if (right_const != null) {
+                                       //
+                                       // Optimize 0-based arithmetic
+                                       //
+                                       if (right_const.IsDefaultValue)
                                                return;
-                                       ex.Emit (ec);
-                               } else {
-                                       right.Emit (ec);
-                                       if (size != 1){
-                                               if (size == 0)
-                                                       ig.Emit (OpCodes.Sizeof, element);
-                                               else 
-                                                       IntLiteral.EmitInt (ig, size);
-                                               if (rtype == TypeManager.int64_type)
-                                                       ig.Emit (OpCodes.Conv_I8);
-                                               else if (rtype == TypeManager.uint64_type)
-                                                       ig.Emit (OpCodes.Conv_U8);
-
-                                               Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype);
+
+                                       if (size != 0) {
+                                               right = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size, right.Location), right_const, loc);
+                                               if (right == null)
+                                                       return;
+                                       } else {
+                                               ig.Emit (OpCodes.Sizeof, element);
+                                               right = EmptyExpression.Null;
                                        }
                                }
-                               
-                               if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
+
+                               right.Emit (ec);
+                               if (rtype == TypeManager.sbyte_type || rtype == TypeManager.byte_type ||
+                                       rtype == TypeManager.short_type || rtype == TypeManager.ushort_type) {
+                                       ig.Emit (OpCodes.Conv_I);
+                               } else if (rtype == TypeManager.uint32_type) {
+                                       ig.Emit (OpCodes.Conv_U);
+                               }
+
+                               if (right_const == null && size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, element);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
+                                               ig.Emit (OpCodes.Conv_I8);
+
+                                       Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype);
+                               }
+
+                               if (rtype == TypeManager.int64_type)
                                        ig.Emit (OpCodes.Conv_I);
+                               else if (rtype == TypeManager.uint64_type)
+                                       ig.Emit (OpCodes.Conv_U);
 
                                Binary.EmitOperatorOpcode (ec, op, op_type);
                        }
@@ -3838,59 +3904,59 @@ namespace Mono.CSharp {
                                return null;
 
                        eclass = ExprClass.Value;
-                       if (true_expr.Type == false_expr.Type) {
-                               type = true_expr.Type;
-                               if (type == TypeManager.null_type) {
-                                       // TODO: probably will have to implement ConditionalConstant
-                                       // to call method without return constant as well
-                                       Report.Warning (-101, 1, loc, "Conditional expression will always return same value");
-                                       return true_expr;
-                               }
-                       } else {
-                               Expression conv;
-                               Type true_type = true_expr.Type;
-                               Type false_type = false_expr.Type;
+                       Type true_type = true_expr.Type;
+                       Type false_type = false_expr.Type;
+                       type = true_type;
 
-                               //
-                               // First, if an implicit conversion exists from true_expr
-                               // to false_expr, then the result type is of type false_expr.Type
-                               //
-                               conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
-                               if (conv != null){
+                       //
+                       // First, if an implicit conversion exists from true_expr
+                       // to false_expr, then the result type is of type false_expr.Type
+                       //
+                       if (!TypeManager.IsEqual (true_type, false_type)) {
+                               Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
+                               if (conv != null) {
                                        //
                                        // Check if both can convert implicitl to each other's type
                                        //
-                                       if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null){
+                                       if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) {
                                                Error (172,
-                                                      "Can not compute type of conditional expression " +
-                                                      "as `" + TypeManager.CSharpName (true_expr.Type) +
-                                                      "' and `" + TypeManager.CSharpName (false_expr.Type) +
-                                                      "' convert implicitly to each other");
+                                                          "Can not compute type of conditional expression " +
+                                                          "as `" + TypeManager.CSharpName (true_expr.Type) +
+                                                          "' and `" + TypeManager.CSharpName (false_expr.Type) +
+                                                          "' convert implicitly to each other");
                                                return null;
                                        }
                                        type = false_type;
                                        true_expr = conv;
-                               } else if ((conv = Convert.ImplicitConversion(ec, false_expr, true_type,loc))!= null){
-                                       type = true_type;
+                               } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) {
                                        false_expr = conv;
                                } else {
-                                       Report.Error (173, loc, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
+                                       Report.Error (173, loc,
+                                               "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
                                                true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
                                        return null;
                                }
-                       }
+                       }                       
 
                        // Dead code optimalization
-                       if (expr is BoolConstant){
-                               BoolConstant bc = (BoolConstant) expr;
-
-                               Report.Warning (429, 4, bc.Value ? false_expr.Location : true_expr.Location, "Unreachable expression code detected");
-                               return bc.Value ? true_expr : false_expr;
+                       Constant c = expr as Constant;
+                       if (c != null){
+                               bool is_false = c.IsDefaultValue;
+                               Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected");
+                               return ReducedExpression.Create (is_false ? false_expr : true_expr, this).Resolve (ec);
                        }
 
                        return this;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+                       true_expr.MutateHoistedGenericType (storey);
+                       false_expr.MutateHoistedGenericType (storey);
+                       type = storey.MutateType (type);
+               }
+
                public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
                {
                        return null;
@@ -3928,16 +3994,35 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation {
-               bool prepared;
+       public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference {
                LocalTemporary temp;
 
-               public abstract Variable Variable {
-                       get;
-               }
+               #region Abstract
+               public abstract HoistedVariable HoistedVariable { get; }
+               public abstract bool IsFixedVariable { get; }
+               public abstract bool IsRef { get; }
+               public abstract string Name { get; }
+               public abstract void SetHasAddressTaken ();
 
-               public abstract bool IsRef {
-                       get;
+               //
+               // Variable IL data, it has to be protected to encapsulate hoisted variables
+               //
+               protected abstract ILocalVariable Variable { get; }
+               
+               //
+               // Variable flow-analysis data
+               //
+               public abstract VariableInfo VariableInfo { get; }
+               #endregion
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       if (IsHoistedEmitRequired (ec)) {
+                               HoistedVariable.AddressOf (ec, mode);
+                               return;
+                       }
+
+                       Variable.EmitAddressOf (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -3958,16 +4043,18 @@ namespace Mono.CSharp {
                //
                public void EmitLoad (EmitContext ec)
                {
-                       Report.Debug (64, "VARIABLE EMIT LOAD", this, Variable, type, loc);
-                       if (!prepared)
-                               Variable.EmitInstance (ec);
                        Variable.Emit (ec);
                }
-               
+
                public void Emit (EmitContext ec, bool leave_copy)
                {
                        Report.Debug (64, "VARIABLE EMIT", this, Variable, type, IsRef, loc);
 
+                       if (IsHoistedEmitRequired (ec)) {
+                               HoistedVariable.Emit (ec, leave_copy);
+                               return;
+                       }
+
                        EmitLoad (ec);
 
                        if (IsRef) {
@@ -3981,7 +4068,7 @@ namespace Mono.CSharp {
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
 
-                               if (IsRef || Variable.NeedsTemporary) {
+                               if (IsRef) {
                                        temp = new LocalTemporary (Type);
                                        temp.Store (ec);
                                }
@@ -3994,13 +4081,9 @@ namespace Mono.CSharp {
                        Report.Debug (64, "VARIABLE EMIT ASSIGN", this, Variable, type, IsRef,
                                      source, loc);
 
-                       ILGenerator ig = ec.ig;
-                       prepared = prepare_for_load;
-
-                       Variable.EmitInstance (ec);
-                       if (prepare_for_load) {
-                               if (Variable.HasInstance)
-                                       ig.Emit (OpCodes.Dup);
+                       if (IsHoistedEmitRequired (ec)) {
+                               HoistedVariable.EmitAssign (ec, source, leave_copy, prepare_for_load);
+                               return;
                        }
 
                        if (IsRef)
@@ -4011,22 +4094,21 @@ namespace Mono.CSharp {
                        // HACK: variable is already emitted when source is an initializer 
                        if (source is NewInitialize) {
                                if (leave_copy) {
-                                       Variable.EmitInstance (ec);
                                        Variable.Emit (ec);
                                }
                                return;
                        }
 
                        if (leave_copy) {
-                               ig.Emit (OpCodes.Dup);
-                               if (IsRef || Variable.NeedsTemporary) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               if (IsRef) {
                                        temp = new LocalTemporary (Type);
                                        temp.Store (ec);
                                }
                        }
 
                        if (IsRef)
-                               StoreFromPtr (ig, type);
+                               StoreFromPtr (ec.ig, type);
                        else
                                Variable.EmitAssign (ec);
 
@@ -4035,28 +4117,38 @@ namespace Mono.CSharp {
                                temp.Release (ec);
                        }
                }
-               
-               public void AddressOf (EmitContext ec, AddressOp mode)
+
+               public bool IsHoisted {
+                       get { return HoistedVariable != null; }
+               }
+
+               protected virtual bool IsHoistedEmitRequired (EmitContext ec)
                {
-                       Variable.EmitInstance (ec);
-                       Variable.EmitAddressOf (ec);
+                       //
+                       // Default implementation return true when there is a hosted variable
+                       //
+                       return HoistedVariable != null;
+               }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       type = storey.MutateType (type);
                }
        }
 
        /// <summary>
        ///   Local variables
        /// </summary>
-       public class LocalVariableReference : VariableReference, IVariable {
-               public readonly string Name;
+       public class LocalVariableReference : VariableReference {
+               readonly string name;
                public Block Block;
                public LocalInfo local_info;
                bool is_readonly;
-               Variable variable;
 
                public LocalVariableReference (Block block, string name, Location l)
                {
                        Block = block;
-                       Name = name;
+                       this.name = name;
                        loc = l;
                        eclass = ExprClass.Variable;
                }
@@ -4073,10 +4165,21 @@ namespace Mono.CSharp {
                        this.is_readonly = is_readonly;
                }
 
-               public VariableInfo VariableInfo {
+               public override VariableInfo VariableInfo {
                        get { return local_info.VariableInfo; }
                }
 
+               public override HoistedVariable HoistedVariable {
+                       get { return local_info.HoistedVariableReference; }
+               }
+
+               //              
+               // A local variable is always fixed
+               //
+               public override bool IsFixedVariable {
+                       get { return true; }
+               }
+
                public override bool IsRef {
                        get { return false; }
                }
@@ -4085,6 +4188,10 @@ namespace Mono.CSharp {
                        get { return is_readonly; }
                }
 
+               public override string Name {
+                       get { return name; }
+               }
+
                public bool VerifyAssigned (EmitContext ec)
                {
                        VariableInfo variable_info = local_info.VariableInfo;
@@ -4100,6 +4207,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void SetHasAddressTaken ()
+               {
+                       local_info.AddressTaken = true;
+               }
+
                public override Expression CreateExpressionTree (EmitContext ec)
                {
                        ArrayList arg = new ArrayList (1);
@@ -4107,7 +4219,7 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall ("Constant", arg);
                }
 
-               protected Expression DoResolveBase (EmitContext ec)
+               Expression DoResolveBase (EmitContext ec)
                {
                        type = local_info.VariableType;
 
@@ -4115,24 +4227,19 @@ namespace Mono.CSharp {
                        if (e != null)
                                return e.Resolve (ec);
 
-                       if (!VerifyAssigned (ec))
-                               return null;
+                       VerifyAssigned (ec);
 
                        //
                        // If we are referencing a variable from the external block
                        // flag it for capturing
                        //
                        if (ec.MustCaptureVariable (local_info)) {
-                               if (local_info.AddressTaken){
-                                       AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
-                                       return null;
-                               }
+                               if (local_info.AddressTaken)
+                                       AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
 
-                               if (!ec.IsInProbingMode)
-                               {
-                                       ScopeInfo scope = local_info.Block.CreateScopeInfo ();
-                                       variable = scope.AddLocal (local_info);
-                                       type = variable.Type;
+                               if (ec.IsVariableCapturingRequired) {
+                                       AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec);
+                                       storey.CaptureLocalVariable (ec, local_info);
                                }
                        }
 
@@ -4180,25 +4287,19 @@ namespace Mono.CSharp {
                                        code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
                                } else if (right_side == EmptyExpression.LValueMemberOutAccess) {
                                        code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
+                               } else if (right_side == EmptyExpression.UnaryAddress) {
+                                       code = 459; msg = "Cannot take the address of {1} `{0}'";
                                } else {
                                        code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
                                }
                                Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
-                               return null;
-                       }
-
-                       if (VariableInfo != null)
+                       } else if (VariableInfo != null) {
                                VariableInfo.SetAssigned (ec);
+                       }
 
                        return DoResolveBase (ec);
                }
 
-               public bool VerifyFixed ()
-               {
-                       // A local Variable is always fixed.
-                       return true;
-               }
-
                public override int GetHashCode ()
                {
                        return Name.GetHashCode ();
@@ -4213,8 +4314,8 @@ namespace Mono.CSharp {
                        return Name == lvr.Name && Block == lvr.Block;
                }
 
-               public override Variable Variable {
-                       get { return variable != null ? variable : local_info.Variable; }
+               protected override ILocalVariable Variable {
+                       get { return local_info; }
                }
 
                public override string ToString ()
@@ -4236,49 +4337,51 @@ namespace Mono.CSharp {
        ///   This represents a reference to a parameter in the intermediate
        ///   representation.
        /// </summary>
-       public class ParameterReference : VariableReference, IVariable {
+       public class ParameterReference : VariableReference {
                readonly ToplevelParameterInfo pi;
                readonly ToplevelBlock referenced;
-               Variable variable;
 
-               public bool is_ref, is_out;
-
-               public bool IsOut {
-                       get { return is_out; }
+               public ParameterReference (ToplevelBlock referenced, ToplevelParameterInfo pi, Location loc)
+               {
+                       this.pi = pi;
+                       this.referenced = referenced;
+                       this.loc = loc;
                }
 
                public override bool IsRef {
-                       get { return is_ref; }
+                       get { return (pi.Parameter.ModFlags & Parameter.Modifier.ISBYREF) != 0; }
                }
 
-               public string Name {
-                       get { return Parameter.Name; }
+               bool HasOutModifier {
+                       get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; }
                }
 
-               public Parameter Parameter {
-                       get { return pi.Parameter; }
+               public override HoistedVariable HoistedVariable {
+                       get { return pi.Parameter.HoistedVariableReference; }
                }
 
-               public ParameterReference (ToplevelBlock referenced, ToplevelParameterInfo pi, Location loc)
-               {
-                       this.pi = pi;
-                       this.referenced = referenced;
-                       this.loc = loc;
-                       eclass = ExprClass.Variable;
+               //
+               // A ref or out parameter is classified as a moveable variable, even 
+               // if the argument given for the parameter is a fixed variable
+               //              
+               public override bool IsFixedVariable {
+                       get { return !IsRef; }
                }
 
-               public VariableInfo VariableInfo {
-                       get { return pi.VariableInfo; }
+               public override string Name {
+                       get { return Parameter.Name; }
                }
 
-               public override Variable Variable {
-                       get { return variable != null ? variable : Parameter.Variable; }
+               public Parameter Parameter {
+                       get { return pi.Parameter; }
                }
 
-               public bool VerifyFixed ()
-               {
-                       // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
-                       return Parameter.ModFlags == Parameter.Modifier.NONE;
+               public override VariableInfo VariableInfo {
+                       get { return pi.VariableInfo; }
+               }
+
+               protected override ILocalVariable Variable {
+                       get { return Parameter; }
                }
 
                public bool IsAssigned (EmitContext ec, Location loc)
@@ -4287,68 +4390,54 @@ namespace Mono.CSharp {
                        if (ec.IsInProbingMode)
                                return true;
                        
-                       if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsAssigned (VariableInfo))
+                       if (!ec.DoFlowAnalysis || !HasOutModifier || ec.CurrentBranching.IsAssigned (VariableInfo))
                                return true;
 
                        Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
                        return false;
                }
 
-               public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
+               public override void SetHasAddressTaken ()
                {
-                       if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsFieldAssigned (VariableInfo, field_name))
-                               return true;
-
-                       Report.Error (170, loc, "Use of possibly unassigned field `{0}'", field_name);
-                       return false;
+                       Parameter.HasAddressTaken = true;
                }
 
-               public void SetAssigned (EmitContext ec)
+               void SetAssigned (EmitContext ec)
                {
-                       if (is_out && ec.DoFlowAnalysis)
+                       if (HasOutModifier && ec.DoFlowAnalysis)
                                ec.CurrentBranching.SetAssigned (VariableInfo);
                }
 
-               public void SetFieldAssigned (EmitContext ec, string field_name)
+               bool DoResolveBase (EmitContext ec)
                {
-                       if (is_out && ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetFieldAssigned (VariableInfo, field_name);
-               }
-
-               protected bool DoResolveBase (EmitContext ec)
-               {
-                       Parameter par = Parameter;
-                       if (!par.Resolve (ec)) {
-                               //TODO:
-                       }
-
-                       type = par.ParameterType;
-                       Parameter.Modifier mod = par.ModFlags;
-                       is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
-                       is_out = (mod & Parameter.Modifier.OUT) == Parameter.Modifier.OUT;
+                       type = pi.ParameterType;
                        eclass = ExprClass.Variable;
 
-                       AnonymousContainer am = ec.CurrentAnonymousMethod;
+                       AnonymousExpression am = ec.CurrentAnonymousMethod;
                        if (am == null)
                                return true;
 
                        ToplevelBlock declared = pi.Block;
-                       if (is_ref && declared != referenced) {
-                               Report.Error (1628, Location,
-                                             "Cannot use ref or out parameter `{0}' inside an " +
-                                             "anonymous method block", par.Name);
-                               return false;
+                       if (declared != referenced) {
+                               if (IsRef) {
+                                       Report.Error (1628, loc,
+                                               "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
+                                               Name, am.ContainerType);
+                                       return false;
+                               }
+                       } else {
+                               if (!am.IsIterator)
+                                       return true;
                        }
 
-                       if (!am.IsIterator && declared == referenced)
-                               return true;
+                       if (ec.IsVariableCapturingRequired) {
+                               if (pi.Parameter.HasAddressTaken)
+                                       AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
 
-                       // Don't capture aruments when the probing is on
-                       if (!ec.IsInProbingMode) {
-                               ScopeInfo scope = declared.CreateScopeInfo ();
-                               variable = scope.AddParameter (par, pi.Index);
-                               type = variable.Type;
+                               AnonymousMethodStorey storey = declared.CreateAnonymousMethodStorey (ec);
+                               storey.CaptureParameter (ec, this);
                        }
+
                        return true;
                }
 
@@ -4365,9 +4454,17 @@ namespace Mono.CSharp {
 
                        return Name == pr.Name && referenced == pr.referenced;
                }
+               
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       // Nothing to clone
+               }
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
+                       if (IsHoistedEmitRequired (ec))
+                               return HoistedVariable.CreateExpressionTree (ec);
+
                        return Parameter.ExpressionTreeVariableReference ();
                }
 
@@ -4388,7 +4485,7 @@ namespace Mono.CSharp {
                        if (!DoResolveBase (ec))
                                return null;
 
-                       if (is_out && ec.DoFlowAnalysis &&
+                       if (HasOutModifier && ec.DoFlowAnalysis &&
                            (!ec.OmitStructFlowAnalysis || !VariableInfo.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
                                return null;
 
@@ -4420,11 +4517,6 @@ namespace Mono.CSharp {
                        } else
                                ig.Emit (OpCodes.Ldarg, x);
                }
-               
-               public override string ToString ()
-               {
-                       return "ParameterReference[" + Name + "]";
-               }
        }
        
        /// <summary>
@@ -4456,12 +4548,7 @@ namespace Mono.CSharp {
                }
 
                public Type Type {
-                       get {
-                               if (ArgType == AType.Ref || ArgType == AType.Out)
-                                       return TypeManager.GetReferenceType (Expr.Type);
-                               else
-                                       return Expr.Type;
-                       }
+                       get { return Expr.Type; }
                }
 
                public Parameter.Modifier Modifier
@@ -4485,7 +4572,7 @@ namespace Mono.CSharp {
                        if (Expr.eclass == ExprClass.MethodGroup)
                                return Expr.ExprClassName;
 
-                       return Expr.GetSignatureForError ();
+                       return TypeManager.CSharpName (Expr.Type);
                }               
 
                public bool ResolveMethodGroup (EmitContext ec)
@@ -4596,13 +4683,29 @@ namespace Mono.CSharp {
                                return CreateExpressionFactoryCall ("Quote", args);
                        }
 
-                       args = new ArrayList (Arguments == null ? 2 : Arguments.Count + 2);
+                       ExtensionMethodGroupExpr emg = mg as ExtensionMethodGroupExpr;
+
+                       int arg_count = Arguments == null ? 2 : Arguments.Count + 2;
+                       if (emg != null)
+                               ++arg_count;
+                       args = new ArrayList (arg_count);
+
                        if (mg.IsInstance)
                                args.Add (new Argument (mg.InstanceExpression.CreateExpressionTree (ec)));
                        else
                                args.Add (new Argument (new NullLiteral (loc)));
 
                        args.Add (new Argument (mg.CreateExpressionTree (ec)));
+
+                       //
+                       // Use extension argument when exists
+                       //
+                       if (emg != null) {
+                               Expression e = emg.ExtensionExpression.CreateExpressionTree (ec);
+                               if (e != null)
+                                       args.Add (new Argument (e));
+                       }
+
                        if (Arguments != null) {
                                foreach (Argument a in Arguments) {
                                        Expression e = a.Expr.CreateExpressionTree (ec);
@@ -4708,9 +4811,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (IsSpecialMethodInvocation (method)) {
-                               return null;
-                       }
+                       IsSpecialMethodInvocation (method, loc);
                        
                        if (mg.InstanceExpression != null)
                                mg.InstanceExpression.CheckMarshalByRefAccess (ec);
@@ -4724,7 +4825,7 @@ namespace Mono.CSharp {
                        return mg.OverloadResolve (ec, ref Arguments, false, loc);
                }
 
-               bool IsSpecialMethodInvocation (MethodBase method)
+               public static bool IsSpecialMethodInvocation (MethodBase method, Location loc)
                {
                        if (!TypeManager.IsSpecialMethod (method))
                                return false;
@@ -4785,11 +4886,8 @@ namespace Mono.CSharp {
 
                static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments)
                {
-                       ParameterData pd = TypeManager.GetParameterData (mb);
-
-                       if (arguments == null)
-                               return new Type [0];
-
+                       AParametersCollection pd = TypeManager.GetParameterData (mb);
+                       
                        Argument a = (Argument) arguments [pd.Count - 1];
                        Arglist list = (Arglist) a.Expr;
 
@@ -4799,7 +4897,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// This checks the ConditionalAttribute on the method 
                /// </summary>
-               public static bool IsMethodExcluded (MethodBase method)
+               public static bool IsMethodExcluded (MethodBase method, Location loc)
                {
                        if (method.IsConstructor)
                                return false;
@@ -4815,7 +4913,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       return AttributeTester.IsConditionalMethodExcluded (method);
+                       return AttributeTester.IsConditionalMethodExcluded (method, loc);
                }
 
                /// <remarks>
@@ -4872,7 +4970,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (IsMethodExcluded (method))
+                       if (IsMethodExcluded (method, loc))
                                return;
                        
                        bool is_static = method.IsStatic;
@@ -4974,7 +5072,7 @@ namespace Mono.CSharp {
                        else
                                ig.Emit (call_op, (ConstructorInfo) method);
                }
-               
+
                public override void Emit (EmitContext ec)
                {
                        mg.EmitCall (ec, Arguments);
@@ -4996,15 +5094,27 @@ namespace Mono.CSharp {
                        Invocation target = (Invocation) t;
 
                        if (Arguments != null) {
-                               target.Arguments = new ArrayList (Arguments.Count);
+                               target.Arguments = new ArrayList (Arguments.Count);
+                               foreach (Argument a in Arguments)
+                                       target.Arguments.Add (a.Clone (clonectx));
+                       }
+
+                       target.expr = expr.Clone (clonectx);
+               }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       mg.MutateHoistedGenericType (storey);
+                       if (Arguments != null) {
                                foreach (Argument a in Arguments)
-                                       target.Arguments.Add (a.Clone (clonectx));
+                                       a.Expr.MutateHoistedGenericType (storey);
                        }
-
-                       target.expr = expr.Clone (clonectx);
                }
        }
 
+       //
+       // It's either a cast or delegate invocation
+       //
        public class InvocationOrCast : ExpressionStatement
        {
                Expression expr;
@@ -5023,14 +5133,22 @@ namespace Mono.CSharp {
                }
 
                public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = ResolveCore (ec);
+                       if (e == null)
+                               return null;
+
+                       return e.Resolve (ec);
+               }
+
+               Expression ResolveCore (EmitContext ec)
                {
                        //
                        // First try to resolve it as a cast.
                        //
-                       TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
-                       if ((te != null) && (te.eclass == ExprClass.Type)) {
-                               Cast cast = new Cast (te, argument, loc);
-                               return cast.Resolve (ec);
+                       TypeExpr te = expr.ResolveAsBaseTerminal (ec, true);
+                       if (te != null) {
+                               return new Cast (te, argument, loc);
                        }
 
                        //
@@ -5044,11 +5162,15 @@ namespace Mono.CSharp {
                        //
                        // Ok, so it's a Cast.
                        //
-                       if (expr.eclass == ExprClass.Type) {
-                               Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
-                               return cast.Resolve (ec);
+                       if (expr.eclass == ExprClass.Type || expr.eclass == ExprClass.TypeParameter) {
+                               return new Cast (expr, argument, loc);
                        }
 
+                       if (expr.eclass == ExprClass.Namespace) {
+                               expr.Error_UnexpectedKind (null, "type", loc);
+                               return null;
+                       }                       
+
                        //
                        // It's a delegate invocation.
                        //
@@ -5057,45 +5179,24 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       ArrayList args = new ArrayList ();
+                       ArrayList args = new ArrayList (1);
                        args.Add (new Argument (argument, Argument.AType.Expression));
-                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
-                       return invocation.Resolve (ec);
+                       return new DelegateInvocation (expr, args, loc);
                }
 
                public override ExpressionStatement ResolveStatement (EmitContext ec)
                {
-                       //
-                       // First try to resolve it as a cast.
-                       //
-                       TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
-                       if ((te != null) && (te.eclass == ExprClass.Type)) {
-                               Error_InvalidExpressionStatement ();
+                       Expression e = ResolveCore (ec);
+                       if (e == null)
                                return null;
-                       }
 
-                       //
-                       // This can either be a type or a delegate invocation.
-                       // Let's just resolve it and see what we'll get.
-                       //
-                       expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
-                       if ((expr == null) || (expr.eclass == ExprClass.Type)) {
+                       ExpressionStatement s = e as ExpressionStatement;
+                       if (s == null) {
                                Error_InvalidExpressionStatement ();
                                return null;
                        }
 
-                       //
-                       // It's a delegate invocation.
-                       //
-                       if (!TypeManager.IsDelegateType (expr.Type)) {
-                               Error (149, "Method name expected");
-                               return null;
-                       }
-
-                       ArrayList args = new ArrayList ();
-                       args.Add (new Argument (argument, Argument.AType.Expression));
-                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
-                       return invocation.ResolveStatement (ec);
+                       return s.ResolveStatement (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -5121,7 +5222,7 @@ namespace Mono.CSharp {
        // This class is used to "disable" the code generation for the
        // temporary variable when initializing value types.
        //
-       class EmptyAddressOf : EmptyExpression, IMemoryLocation {
+       sealed class EmptyAddressOf : EmptyExpression, IMemoryLocation {
                public void AddressOf (EmitContext ec, AddressOp Mode)
                {
                        // nothing
@@ -5301,11 +5402,6 @@ namespace Mono.CSharp {
 
                        type = texpr.Type;
 
-                       if (type == TypeManager.void_type) {
-                               Error_VoidInvalidInTheContext (loc);
-                               return null;
-                       }
-
                        if (type.IsPointer) {
                                Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
                                        TypeManager.CSharpName (type));
@@ -5319,11 +5415,7 @@ namespace Mono.CSharp {
                        }
 
                        if (TypeManager.IsDelegateType (type)) {
-                               RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
-                               if (RequestedType != null)
-                                       if (!(RequestedType is DelegateCreation))
-                                               throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
-                               return RequestedType;
+                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
                        }
 
 #if GMCS_SOURCE
@@ -5517,7 +5609,12 @@ namespace Mono.CSharp {
                                 }
                                 return false;
                        } else {
-                               ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+                               ConstructorInfo ci = (ConstructorInfo) method;
+#if MS_COMPATIBLE
+                               if (TypeManager.IsGenericType (type))
+                                       ci = TypeBuilder.GetConstructor (type, ci);
+#endif
+                               ig.Emit (OpCodes.Newobj, ci);
                                return true;
                        }
                }
@@ -5597,6 +5694,19 @@ namespace Mono.CSharp {
                                }
                        }
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (method != null) {
+                               method.MutateHoistedGenericType (storey);
+                               if (Arguments != null) {
+                                       foreach (Argument a in Arguments)
+                                               a.Expr.MutateHoistedGenericType (storey);
+                               }
+                       }
+
+                       type = storey.MutateType (type);
+               }
        }
 
        /// <summary>
@@ -5640,7 +5750,7 @@ namespace Mono.CSharp {
                        this.rank = rank;
                        loc = l;
 
-                       arguments = new ArrayList ();
+                       arguments = new ArrayList (exprs.Count);
 
                        foreach (Expression e in exprs) {
                                arguments.Add (new Argument (e, Argument.AType.Expression));
@@ -5683,7 +5793,7 @@ namespace Mono.CSharp {
 
                                Constant c = a.Expr as Constant;
                                if (c != null) {
-                                       c = c.ImplicitConversionRequired (TypeManager.int32_type, a.Expr.Location);
+                                       c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Expr.Location);
                                }
 
                                if (c == null) {
@@ -5781,8 +5891,13 @@ namespace Mono.CSharp {
                        args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
                        args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
                        if (array_data != null) {
-                               foreach (Expression e in array_data)
+                               for (int i = 0; i < array_data.Count; ++i) {
+                                       Expression e = (Expression) array_data [i];
+                                       if (e == null)
+                                               e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc);
+
                                        args.Add (new Argument (e.CreateExpressionTree (ec)));
+                               }
                        }
 
                        return CreateExpressionFactoryCall ("NewArrayInit", args);
@@ -5866,6 +5981,11 @@ namespace Mono.CSharp {
                                Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
                                return false;
                        }
+
+                       if (requested_base_type is VarExpr) {
+                               Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer");
+                               return false;
+                       }
                        
                        StringBuilder array_qualifier = new StringBuilder (rank);
 
@@ -5903,11 +6023,6 @@ namespace Mono.CSharp {
 
                        if (!ResolveArrayType (ec))
                                return null;
-                       
-                       if ((array_element_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
-                               Report.Error (719, loc, "`{0}': array elements cannot be of static type",
-                                       TypeManager.CSharpName (array_element_type));
-                       }
 
                        //
                        // First step is to validate the initializers and fill
@@ -6101,6 +6216,21 @@ namespace Mono.CSharp {
                        return data;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       array_element_type = storey.MutateType (array_element_type);
+                       type = storey.MutateType (type);
+                       if (arguments != null) {
+                               foreach (Argument a in arguments)
+                                       a.Expr.MutateHoistedGenericType (storey);
+                       }
+                       
+                       if (array_data != null) {
+                               foreach (Expression e in array_data)
+                                       e.MutateHoistedGenericType (storey);
+                       }
+               }
+
                //
                // Emits the initializers for the array
                //
@@ -6257,11 +6387,11 @@ namespace Mono.CSharp {
                                first_emit_temp.Release (ec);
                }
 
-               public override bool GetAttributableValue (Type value_type, out object value)
+               public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
                {
                        if (arguments.Count != 1) {
                                // Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
-                               return base.GetAttributableValue (null, out value);
+                               return base.GetAttributableValue (ec, null, out value);
                        }
 
                        if (array_data == null) {
@@ -6271,7 +6401,7 @@ namespace Mono.CSharp {
                                        return true;
                                }
                                // Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
-                               return base.GetAttributableValue (null, out value);
+                               return base.GetAttributableValue (ec, null, out value);
                        }
                        
                        Array ret = Array.CreateInstance (array_element_type, array_data.Count);
@@ -6284,7 +6414,7 @@ namespace Mono.CSharp {
                                if (e == null) 
                                        continue;
 
-                               if (!e.GetAttributableValue (array_element_type, out element_value)) {
+                               if (!e.GetAttributableValue (ec, array_element_type, out element_value)) {
                                        value = null;
                                        return false;
                                }
@@ -6352,7 +6482,7 @@ namespace Mono.CSharp {
                        if (array_element_type == null || array_element_type == TypeManager.null_type ||
                                array_element_type == TypeManager.void_type || array_element_type == TypeManager.anonymous_method_type ||
                                arguments.Count != dimensions) {
-                               Report.Error (826, loc, "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
+                               Error_NoBestType ();
                                return null;
                        }
 
@@ -6368,6 +6498,12 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               void Error_NoBestType ()
+               {
+                       Report.Error (826, loc,
+                               "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
+               }
+
                //
                // Converts static initializer only
                //
@@ -6400,8 +6536,8 @@ namespace Mono.CSharp {
                                return element;
                        }
 
-                       element.Error_ValueCannotBeConverted (ec, element.Location, array_element_type, false);
-                       return element;
+                       Error_NoBestType ();
+                       return null;
                }
        }       
        
@@ -6414,24 +6550,53 @@ namespace Mono.CSharp {
                {
                }
 
+               public CompilerGeneratedThis (Type type, Location loc)
+                       : base (loc)
+               {
+                       this.type = type;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
-                       type = ec.ContainerType;
-                       variable = new SimpleThis (type);
+                       if (type == null)
+                               type = ec.ContainerType;
                        return this;
                }
+
+               public override HoistedVariable HoistedVariable {
+                       get { return null; }
+               }
        }
        
        /// <summary>
        ///   Represents the `this' construct
        /// </summary>
 
-       public class This : VariableReference, IVariable
+       public class This : VariableReference
        {
+               sealed class ThisVariable : ILocalVariable
+               {
+                       public static readonly ILocalVariable Instance = new ThisVariable ();
+
+                       public void Emit (EmitContext ec)
+                       {
+                               ec.ig.Emit (OpCodes.Ldarg_0);
+                       }
+
+                       public void EmitAssign (EmitContext ec)
+                       {
+                               throw new InvalidOperationException ();
+                       }
+
+                       public void EmitAddressOf (EmitContext ec)
+                       {
+                               ec.ig.Emit (OpCodes.Ldarg_0);
+                       }
+               }
+
                Block block;
                VariableInfo variable_info;
-               protected Variable variable;
                bool is_struct;
 
                public This (Block block, Location loc)
@@ -6445,25 +6610,63 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
-               public VariableInfo VariableInfo {
+               public override VariableInfo VariableInfo {
                        get { return variable_info; }
                }
 
-               public bool VerifyFixed ()
+               public override bool IsFixedVariable {
+                       get { return !TypeManager.IsValueType (type); }
+               }
+
+               protected override bool IsHoistedEmitRequired (EmitContext ec)
                {
-                       return !TypeManager.IsValueType (Type);
+                       //
+                       // Handle 'this' differently, it cannot be assigned hence
+                       // when we are not inside anonymous method we can emit direct access 
+                       //
+                       return ec.CurrentAnonymousMethod != null && base.IsHoistedEmitRequired (ec);
+               }
+
+               public override HoistedVariable HoistedVariable {
+                       get { return TopToplevelBlock.HoistedThisVariable; }
                }
 
                public override bool IsRef {
                        get { return is_struct; }
                }
 
-               public override Variable Variable {
-                       get { return variable; }
+               protected override ILocalVariable Variable {
+                       get { return ThisVariable.Instance; }
+               }
+
+               // TODO: Move to ToplevelBlock
+               ToplevelBlock TopToplevelBlock {
+                       get {
+                               ToplevelBlock tl = block.Toplevel;
+                               while (tl.Parent != null) tl = tl.Parent.Toplevel;
+                               return tl;
+                       }
+               }
+
+               public static bool IsThisAvailable (EmitContext ec)
+               {
+                       if (ec.IsStatic || ec.IsInFieldInitializer)
+                               return false;
+
+                       if (ec.CurrentAnonymousMethod == null)
+                               return true;
+
+                       if (ec.TypeContainer is Struct && ec.CurrentIterator == null)
+                               return false;
+
+                       return true;
                }
 
                public bool ResolveBase (EmitContext ec)
                {
+                       if (eclass != ExprClass.Invalid)
+                               return true;
+
                        eclass = ExprClass.Variable;
 
                        if (ec.TypeContainer.CurrentType != null)
@@ -6471,38 +6674,36 @@ namespace Mono.CSharp {
                        else
                                type = ec.ContainerType;
 
-                       is_struct = ec.TypeContainer is Struct;
-
-                       if (ec.IsStatic) {
-                               Error (26, "Keyword `this' is not valid in a static property, " +
-                                      "static method, or static field initializer");
-                               return false;
+                       if (!IsThisAvailable (ec)) {
+                               if (ec.IsStatic) {
+                                       Error (26, "Keyword `this' is not valid in a static property, static method, or static field initializer");
+                               } else {
+                                       Report.Error (1673, loc,
+                                               "Anonymous methods inside structs cannot access instance members of `this'. " +
+                                               "Consider copying `this' to a local variable outside the anonymous method and using the local instead");
+                               }
                        }
 
+                       is_struct = ec.TypeContainer is Struct;
+
                        if (block != null) {
                                if (block.Toplevel.ThisVariable != null)
                                        variable_info = block.Toplevel.ThisVariable.VariableInfo;
 
-                               AnonymousContainer am = ec.CurrentAnonymousMethod;
-                               if (is_struct && (am != null) && !am.IsIterator) {
-                                       Report.Error (1673, loc, "Anonymous methods inside structs " +
-                                                     "cannot access instance members of `this'. " +
-                                                     "Consider copying `this' to a local variable " +
-                                                     "outside the anonymous method and using the " +
-                                                     "local instead.");
-                               }
-
-                               RootScopeInfo host = block.Toplevel.RootScope;
-                               if ((host != null) && !ec.IsConstructor &&
-                                   (!is_struct || host.IsIterator)) {
-                                       variable = host.CaptureThis ();
-                                       type = variable.Type;
-                                       is_struct = false;
+                               AnonymousExpression am = ec.CurrentAnonymousMethod;
+                               if (am != null) {
+                                       //
+                                       // this is hoisted to very top level block
+                                       //
+                                       if (ec.IsVariableCapturingRequired) {
+                                               // TODO: it could be optimized
+                                               AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec);
+                                               if (HoistedVariable == null) {
+                                                       TopToplevelBlock.HoistedThisVariable = scope.CaptureThis (ec, this);
+                                               }
+                                       }
                                }
                        }
-
-                       if (variable == null)
-                               variable = new SimpleThis (type);
                        
                        return true;
                }
@@ -6549,19 +6750,28 @@ namespace Mono.CSharp {
 
                        if (variable_info != null)
                                variable_info.SetAssigned (ec);
-                       
+
                        if (ec.TypeContainer is Class){
-                               Error (1604, "Cannot assign to 'this' because it is read-only");
-                               return null;
+                               if (right_side == EmptyExpression.UnaryAddress)
+                                       Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
+                               else if (right_side == EmptyExpression.OutAccess)
+                                       Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only");
+                               else
+                                       Report.Error (1604, loc, "Cannot assign to `this' because it is read-only");
                        }
 
                        return this;
                }
+
                public override int GetHashCode()
                {
                        return block.GetHashCode ();
                }
 
+               public override string Name {
+                       get { return "this"; }
+               }
+
                public override bool Equals (object obj)
                {
                        This t = obj as This;
@@ -6571,53 +6781,21 @@ namespace Mono.CSharp {
                        return block == t.block;
                }
 
-               protected class SimpleThis : Variable
+               protected override void CloneTo (CloneContext clonectx, Expression t)
                {
-                       Type type;
-
-                       public SimpleThis (Type type)
-                       {
-                               this.type = type;
-                       }
-
-                       public override Type Type {
-                               get { return type; }
-                       }
-
-                       public override bool HasInstance {
-                               get { return false; }
-                       }
-
-                       public override bool NeedsTemporary {
-                               get { return false; }
-                       }
-
-                       public override void EmitInstance (EmitContext ec)
-                       {
-                               // Do nothing.
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               ec.ig.Emit (OpCodes.Ldarg_0);
-                       }
-
-                       public override void EmitAssign (EmitContext ec)
-                       {
-                               throw new InvalidOperationException ();
-                       }
+                       This target = (This) t;
 
-                       public override void EmitAddressOf (EmitContext ec)
-                       {
-                               ec.ig.Emit (OpCodes.Ldarg_0);
-                       }
+                       target.block = clonectx.LookupBlock (block);
                }
 
-               protected override void CloneTo (CloneContext clonectx, Expression t)
+               public void RemoveHoisting ()
                {
-                       This target = (This) t;
+                       TopToplevelBlock.HoistedThisVariable = null;
+               }
 
-                       target.block = clonectx.LookupBlock (block);
+               public override void SetHasAddressTaken ()
+               {
+                       // Nothing
                }
        }
 
@@ -6641,7 +6819,7 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Variable;
                        type = TypeManager.runtime_argument_handle_type;
 
-                       if (ec.IsInFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs
+                       if (ec.IsInFieldInitializer || !ec.CurrentBlock.Toplevel.Parameters.HasArglist
                        {
                                Error (190, "The __arglist construct is valid only within " +
                                       "a variable argument method");
@@ -6714,6 +6892,12 @@ namespace Mono.CSharp {
                                arg.Emit (ec);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (Argument arg in Arguments)
+                               arg.Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Arglist target = (Arglist) t;
@@ -6790,7 +6974,7 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
                }
 
-               public override bool GetAttributableValue (Type value_type, out object value)
+               public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
                {
                        if (TypeManager.ContainsGenericParameters (typearg) &&
                                !TypeManager.IsGenericTypeDefinition (typearg)) {
@@ -6809,10 +6993,13 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public Type TypeArgument
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
-                       get
-                       {
+                       typearg = storey.MutateType (typearg);
+               }
+
+               public Type TypeArgument {
+                       get {
                                return typearg;
                        }
                }
@@ -7014,11 +7201,6 @@ namespace Mono.CSharp {
                        if (TypeManager.IsEnumType (type_queried))
                                type_queried = TypeManager.GetEnumUnderlyingType (type_queried);
 
-                       if (type_queried == TypeManager.void_type) {
-                               Expression.Error_VoidInvalidInTheContext (loc);
-                               return null;
-                       }
-
                        int size_of = GetTypeSize (type_queried);
                        if (size_of > 0) {
                                return new IntConstant (size_of, loc);
@@ -7060,6 +7242,7 @@ namespace Mono.CSharp {
        public class QualifiedAliasMember : MemberAccess
        {
                readonly string alias;
+               public static readonly string GlobalAlias = "global";
 
                public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
                        : base (null, identifier, targs, l)
@@ -7075,7 +7258,7 @@ namespace Mono.CSharp {
 
                public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
-                       if (alias == "global") {
+                       if (alias == GlobalAlias) {
                                expr = RootNamespace.Global;
                                return base.ResolveAsTypeStep (ec, silent);
                        }
@@ -7480,7 +7663,7 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
-                       if (Expr is Constant)
+                       if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression)
                                return Expr;
                        
                        eclass = Expr.eclass;
@@ -7500,6 +7683,11 @@ namespace Mono.CSharp {
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        CheckedExpr target = (CheckedExpr) t;
@@ -7535,7 +7723,7 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
-                       if (Expr is Constant)
+                       if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression)
                                return Expr;
                        
                        eclass = Expr.eclass;
@@ -7555,6 +7743,11 @@ namespace Mono.CSharp {
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        UnCheckedExpr target = (UnCheckedExpr) t;
@@ -7576,16 +7769,14 @@ namespace Mono.CSharp {
                public ElementAccess (Expression e, ArrayList e_list)
                {
                        Expr = e;
-
                        loc  = e.Location;
                        
                        if (e_list == null)
                                return;
                        
-                       Arguments = new ArrayList ();
+                       Arguments = new ArrayList (e_list.Count);
                        foreach (Expression tmp in e_list)
                                Arguments.Add (new Argument (tmp, Argument.AType.Expression));
-                       
                }
 
                bool CommonResolve (EmitContext ec)
@@ -7615,10 +7806,6 @@ namespace Mono.CSharp {
 
                Expression MakePointerAccess (EmitContext ec, Type t)
                {
-                       if (t == TypeManager.void_ptr_type){
-                               Error (242, "The array index operation is not valid on void pointers");
-                               return null;
-                       }
                        if (Arguments.Count != 1){
                                Error (196, "A pointer must be indexed by only one value");
                                return null;
@@ -7718,7 +7905,6 @@ namespace Mono.CSharp {
                public ArrayAccess (ElementAccess ea_data, Location l)
                {
                        ea = ea_data;
-                       eclass = ExprClass.Variable;
                        loc = l;
                }
 
@@ -7745,6 +7931,9 @@ namespace Mono.CSharp {
                        }
 #endif
 
+                       if (eclass != ExprClass.Invalid)
+                               return this;
+
                        Type t = ea.Expr.Type;
                        int rank = ea.Arguments.Count;
                        if (t.GetArrayRank () != rank) {
@@ -7753,11 +7942,6 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (rank != 1 && TypeManager.int_getlength_int == null) {
-                               TypeManager.int_getlength_int = TypeManager.GetPredefinedMethod (
-                                       TypeManager.array_type, "GetLength", loc, TypeManager.int32_type);
-                       }
-
                        type = TypeManager.GetElementType (t);
                        if (type.IsPointer && !ec.InUnsafe) {
                                UnsafeError (ea.Location);
@@ -8046,19 +8230,9 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void EmitGetLength (EmitContext ec, int dim)
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
-                       int rank = ea.Expr.Type.GetArrayRank ();
-                       ILGenerator ig = ec.ig;
-
-                       ea.Expr.Emit (ec);
-                       if (rank == 1) {
-                               ig.Emit (OpCodes.Ldlen);
-                               ig.Emit (OpCodes.Conv_I4);
-                       } else {
-                               IntLiteral.EmitInt (ig, dim);
-                               ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
-                       }
+                       type = storey.MutateType (type);
                }
        }
 
@@ -8081,7 +8255,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       protected override int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
+                       protected override int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters)
                        {
                                //
                                // Here is the trick, decrease number of arguments by 1 when only
@@ -8413,6 +8587,20 @@ namespace Mono.CSharp {
                        return TypeManager.CSharpSignature (get != null ? get : set, false);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (get != null)
+                               get = storey.MutateGenericMethod (get);
+                       if (set != null)
+                               set = storey.MutateGenericMethod (set);
+
+                       instance_expr.MutateHoistedGenericType (storey);
+                       foreach (Argument a in arguments)
+                               a.Expr.MutateHoistedGenericType (storey);
+
+                       type = storey.MutateType (type);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        IndexerAccess target = (IndexerAccess) t;
@@ -8488,13 +8676,12 @@ namespace Mono.CSharp {
                        Type current_type = ec.ContainerType;
                        Type base_type = current_type.BaseType;
 
-                       if (ec.IsStatic){
-                               Error (1511, "Keyword `base' is not available in a static method");
-                               return null;
-                       }
-
-                       if (ec.IsInFieldInitializer){
-                               Error (1512, "Keyword `base' is not available in the current context");
+                       if (!This.IsThisAvailable (ec)) {
+                               if (ec.IsStatic) {
+                                       Error (1511, "Keyword `base' is not available in a static method");
+                               } else {
+                                       Error (1512, "Keyword `base' is not available in the current context");
+                               }
                                return null;
                        }
                        
@@ -8586,11 +8773,12 @@ namespace Mono.CSharp {
        ///   is needed (the `New' class).
        /// </summary>
        public class EmptyExpression : Expression {
-               public static readonly EmptyExpression Null = new EmptyExpression ();
+               public static readonly Expression Null = new EmptyExpression ();
 
                public static readonly EmptyExpression OutAccess = new EmptyExpression ();
                public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression ();
                public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression ();
+               public static readonly EmptyExpression UnaryAddress = new EmptyExpression ();
 
                static EmptyExpression temp = new EmptyExpression ();
                public static EmptyExpression Grab ()
@@ -8726,6 +8914,12 @@ namespace Mono.CSharp {
                        source.Emit (ec);
                        ec.ig.Emit (OpCodes.Call, method);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       source.MutateHoistedGenericType (storey);
+                       method = storey.MutateGenericMethod (method);
+               }
        }
 
        // <summary>
@@ -8750,17 +8944,6 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public Expression RemoveNullable ()
-               {
-                       if (dim.EndsWith ("?")) {
-                               dim = dim.Substring (0, dim.Length - 1);
-                               if (dim.Length == 0)
-                                       return left;
-                       }
-
-                       return this;
-               }
-
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
                        TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false);
@@ -8768,11 +8951,6 @@ namespace Mono.CSharp {
                                return null;
 
                        Type ltype = lexpr.Type;
-                       if ((ltype == TypeManager.void_type) && (dim != "*")) {
-                               Error_VoidInvalidInTheContext (loc);
-                               return null;
-                       }
-
 #if GMCS_SOURCE
                        if ((dim.Length > 0) && (dim [0] == '?')) {
                                TypeExpr nullable = new Nullable.NullableType (left, loc);
@@ -8785,10 +8963,17 @@ namespace Mono.CSharp {
                        if (dim == "*" && !TypeManager.VerifyUnManaged (ltype, loc))
                                return null;
 
-                       if (dim != "" && dim [0] == '[' &&
-                           (ltype == TypeManager.arg_iterator_type || ltype == TypeManager.typed_reference_type)) {
-                               Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
-                               return null;
+                       if (dim.Length != 0 && dim [0] == '[') {
+                               if (TypeManager.IsSpecialType (ltype)) {
+                                       Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
+                                       return null;
+                               }
+
+                               if ((ltype.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                                       Report.SymbolRelatedToPreviousError (ltype);
+                                       Report.Error (719, loc, "Array elements cannot be of static type `{0}'", 
+                                               TypeManager.CSharpName (ltype));
+                               }
                        }
 
                        if (dim != "")
@@ -8801,7 +8986,6 @@ namespace Mono.CSharp {
 
                        if (type.IsPointer && !ec.IsInUnsafeScope){
                                UnsafeError (loc);
-                               return null;
                        }
 
                        eclass = ExprClass.Type;
@@ -8940,7 +9124,7 @@ namespace Mono.CSharp {
                        if (count == null)
                                return null;
                        
-                       if (count.Type != TypeManager.int32_type){
+                       if (count.Type != TypeManager.uint32_type){
                                count = Convert.ImplicitConversionRequired (ec, count, TypeManager.int32_type, loc);
                                if (count == null)
                                        return null;
@@ -8976,13 +9160,15 @@ namespace Mono.CSharp {
                {
                        int size = GetTypeSize (otype);
                        ILGenerator ig = ec.ig;
-                               
+
+                       count.Emit (ec);
+
                        if (size == 0)
                                ig.Emit (OpCodes.Sizeof, otype);
                        else
                                IntConstant.EmitInt (ig, size);
-                       count.Emit (ec);
-                       ig.Emit (OpCodes.Mul);
+
+                       ig.Emit (OpCodes.Mul_Ovf_Un);
                        ig.Emit (OpCodes.Localloc);
                }
 
@@ -9149,7 +9335,11 @@ namespace Mono.CSharp {
                        // for known types like List<T>, Dictionary<T, U>
                        
                        for (int i = 0; i < Arguments.Count; ++i) {
-                               Expression expr = ((Expression) Arguments [i]).Resolve (ec);
+                               Expression expr = Arguments [i] as Expression;
+                               if (expr == null)
+                                       return null;
+
+                               expr = expr.Resolve (ec);
                                if (expr == null)
                                        return null;
 
@@ -9278,6 +9468,12 @@ namespace Mono.CSharp {
                        foreach (ExpressionStatement e in initializers)
                                e.EmitStatement (ec);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (Expression e in initializers)
+                               e.MutateHoistedGenericType (storey);
+               }
        }
        
        //
@@ -9377,7 +9573,7 @@ namespace Mono.CSharp {
                        ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
                        initializers.Resolve (ec);
                        ec.CurrentInitializerVariable = previous;
-                       return this;
+                       return e;
                }
 
                public override void Emit (EmitContext ec)
@@ -9385,15 +9581,16 @@ namespace Mono.CSharp {
                        base.Emit (ec);
 
                        //
-                       // If target is a value, let's use it
+                       // If target is non-hoisted variable, let's use it
                        //
                        VariableReference variable = value_target as VariableReference;
-                       if (variable != null) {
+                       if (variable != null && variable.HoistedVariable == null) {
                                if (variable.IsRef)
                                        StoreFromPtr (ec.ig, type);
                                else
-                                       variable.Variable.EmitAssign (ec);
+                                       variable.EmitAssign (ec, EmptyExpression.Null, false, false);
                        } else {
+                               variable = null;
                                if (value_target == null || value_target_set)
                                        value_target = new LocalTemporary (type);
 
@@ -9402,8 +9599,10 @@ namespace Mono.CSharp {
 
                        initializers.Emit (ec);
 
-                       if (variable == null)
+                       if (variable == null) {
                                value_target.Emit (ec);
+                               value_target = null;
+                       }
                }
 
                public override void EmitStatement (EmitContext ec)
@@ -9429,6 +9628,12 @@ namespace Mono.CSharp {
                                return !initializers.IsEmpty;
                        }
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       base.MutateHoistedGenericType (storey);
+                       initializers.MutateHoistedGenericType (storey);
+               }
        }
 
        public class AnonymousTypeDeclaration : Expression
@@ -9469,6 +9674,7 @@ namespace Mono.CSharp {
                        type.DefineMembers ();
                        type.Define ();
                        type.EmitType ();
+                       type.CloseType ();
 
                        RootContext.ToplevelTypes.AddAnonymousType (type);
                        return type;
@@ -9569,20 +9775,25 @@ namespace Mono.CSharp {
                        if (e == null)
                                return null;
 
+                       if (e.eclass == ExprClass.MethodGroup) {
+                               Error_InvalidInitializer (e.ExprClassName);
+                               return null;
+                       }
+
                        type = e.Type;
                        if (type == TypeManager.void_type || type == TypeManager.null_type ||
                                type == TypeManager.anonymous_method_type || type.IsPointer) {
-                               Error_InvalidInitializer (e);
+                               Error_InvalidInitializer (e.GetSignatureForError ());
                                return null;
                        }
 
                        return e;
                }
 
-               protected virtual void Error_InvalidInitializer (Expression initializer)
+               protected virtual void Error_InvalidInitializer (string initializer)
                {
                        Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
-                               Name, initializer.GetSignatureForError ());
+                               Name, initializer);
                }
 
                public override void Emit (EmitContext ec)