2008-07-14 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / ecore.cs
index d77d41ad8573e6cdd76821cf07bef96dd3c3de05..e8e0e6f3b86a32a5505d15ec3cdf75e2060dc7dd 100644 (file)
@@ -5,7 +5,8 @@
 //   Miguel de Icaza (miguel@ximian.com)
 //   Marek Safar (marek.safar@seznam.cz)
 //
-// (C) 2001, 2002, 2003 Ximian, Inc.
+// Copyright 2001, 2002, 2003 Ximian, Inc.
+// Copyright 2003-2008 Novell, Inc.
 //
 //
 
@@ -96,15 +97,10 @@ namespace Mono.CSharp {
                void AddressOf (EmitContext ec, AddressOp mode);
        }
 
-       /// <summary>
-       ///   This interface is implemented by variables
-       /// </summary>
+       // TODO: Rename to something meaningful, this is flow-analysis interface only
        public interface IVariable {
-               VariableInfo VariableInfo {
-                       get;
-               }
-
-               bool VerifyFixed ();
+               VariableInfo VariableInfo { get; }
+               bool IsFixed { get; }
        }
 
        /// <remarks>
@@ -165,8 +161,7 @@ namespace Mono.CSharp {
                                return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
                                        TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
 
-                       if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
-                                       TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
+                       if (TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) {
                                if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
                                        return true;
                        } else {
@@ -229,8 +224,16 @@ namespace Mono.CSharp {
                // This is used if the expression should be resolved as a type or namespace name.
                // the default implementation fails.   
                //
-               public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec,  bool silent)
+               public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext rc,  bool silent)
                {
+                       if (!silent) {
+                               Expression e = this;
+                               EmitContext ec = rc as EmitContext;
+                               if (ec != null)
+                                       e = e.Resolve (ec);
+                               if (e != null)
+                                       e.Error_UnexpectedKind (ResolveFlags.Type, loc);
+                       }
                        return null;
                }
 
@@ -347,9 +350,9 @@ namespace Mono.CSharp {
 
                        if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) {
 #if GMCS_SOURCE
-                               string sig1 = Type.DeclaringMethod == null ?
-                                       TypeManager.CSharpName (Type.DeclaringType) :
-                                       TypeManager.CSharpSignature (Type.DeclaringMethod);
+                               string sig1 = type.DeclaringMethod == null ?
+                                       TypeManager.CSharpName (type.DeclaringType) :
+                                       TypeManager.CSharpSignature (type.DeclaringMethod);
                                string sig2 = target.DeclaringMethod == null ?
                                        TypeManager.CSharpName (target.DeclaringType) :
                                        TypeManager.CSharpSignature (target.DeclaringMethod);
@@ -377,7 +380,7 @@ namespace Mono.CSharp {
                        if (b ||
                            Convert.ExplicitReferenceConversionExists (Type, target) ||
                            Convert.ExplicitUnsafe (e, target) != null ||
-                           (ec != null && Convert.UserDefinedConversion (ec, this, target, Location.Null, true) != null))
+                           (ec != null && Convert.ExplicitUserConversion (ec, this, target, Location.Null) != null))
                        {
                                Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " +
                                              "An explicit conversion exists (are you missing a cast?)",
@@ -385,12 +388,6 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) {
-                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
-                                       ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target));
-                               return;
-                       }
-
                        Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
                                TypeManager.CSharpName (type),
                                TypeManager.CSharpName (target));
@@ -577,12 +574,25 @@ namespace Mono.CSharp {
                /// </remarks>
                public abstract void Emit (EmitContext ec);
 
+               // Emit code to branch to @target if this expression is equivalent to @on_true.
+               // The default implementation is to emit the value, and then emit a brtrue or brfalse.
+               // Subclasses can provide more efficient implementations, but those MUST be equivalent,
+               // including the use of conditional branches.  Note also that a branch MUST be emitted
                public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        Emit (ec);
                        ec.ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
                }
 
+               // Emit this expression for its side effects, not for its value.
+               // The default implementation is to emit the value, and then throw it away.
+               // Subclasses can provide more efficient implementations, but those MUST be equivalent
+               public virtual void EmitSideEffect (EmitContext ec)
+               {
+                       Emit (ec);
+                       ec.ig.Emit (OpCodes.Pop);
+               }
+
                /// <summary>
                ///   Protected constructor.  Only derivate types should
                ///   be able to be created
@@ -893,6 +903,11 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
                }
 
+               protected void Error_PointerInsideExpressionTree ()
+               {
+                       Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
+               }
+
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -914,25 +929,20 @@ namespace Mono.CSharp {
                static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
                        MethodGroupExpr operator_group;
-
-#if GMCS_SOURCE
-                       if (TypeManager.IsNullableType (e.Type))
-                               return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
-#endif
-
-                       operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
+                       string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
+                       operator_group = MethodLookup (ec.ContainerType, e.Type, mname, loc) as MethodGroupExpr;
                        if (operator_group == null)
                                return null;
 
                        ArrayList arguments = new ArrayList (1);
                        arguments.Add (new Argument (e, Argument.AType.Expression));
                        operator_group = operator_group.OverloadResolve (
-                               ec, arguments, false, loc);
+                               ec, ref arguments, false, loc);
 
                        if (operator_group == null)
                                return null;
 
-                       return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc);
+                       return new UserOperatorCall (operator_group, arguments, null, loc);
                }
 
                /// <summary>
@@ -1084,7 +1094,7 @@ namespace Mono.CSharp {
                                if (t == TypeManager.enum_type)
                                        ig.Emit (OpCodes.Ldind_Ref);
                                else
-                                       LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
+                                       LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t));
                        } else if (t.IsValueType || TypeManager.IsGenericParameter (t))
                                ig.Emit (OpCodes.Ldobj, t);
                        else if (t.IsPointer)
@@ -1099,7 +1109,7 @@ namespace Mono.CSharp {
                public static void StoreFromPtr (ILGenerator ig, Type type)
                {
                        if (TypeManager.IsEnumType (type))
-                               type = TypeManager.EnumToUnderlying (type);
+                               type = TypeManager.GetEnumUnderlyingType (type);
                        if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
                                ig.Emit (OpCodes.Stind_I4);
                        else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
@@ -1236,11 +1246,10 @@ namespace Mono.CSharp {
                        return cloned;
                }
 
-               public virtual Expression CreateExpressionTree (EmitContext ec)
-               {
-                       throw new NotImplementedException (
-                               "Expression tree conversion not implemented for " + GetType ());
-               }
+               //
+               // Implementation of expression to expression tree conversion
+               //
+               public abstract Expression CreateExpressionTree (EmitContext ec);
 
                protected Expression CreateExpressionFactoryCall (string name, ArrayList args)
                {
@@ -1254,9 +1263,26 @@ namespace Mono.CSharp {
 
                public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args, Location loc)
                {
-                       return new Invocation (
-                               new MemberAccess (ExpressionTreeManager.Type, name, typeArguments, loc),
-                               args);
+                       return new Invocation (new MemberAccess (CreateExpressionTypeExpression (loc), name, typeArguments, loc), args);
+               }
+
+               protected static TypeExpr CreateExpressionTypeExpression (Location loc)
+               {
+                       TypeExpr texpr = TypeManager.expression_type_expr;
+                       if (texpr == null) {
+                               Type t = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression", Kind.Class, true);
+                               if (t == null)
+                                       return null;
+
+                               TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null);
+                       }
+
+                       return texpr;
+               }
+
+               public virtual void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       // TODO: It should probably be type = storey.MutateType (type);
                }
        }
 
@@ -1289,6 +1315,11 @@ namespace Mono.CSharp {
                ///   Emit that will always leave a value on the stack).
                /// </summary>
                public abstract void EmitStatement (EmitContext ec);
+
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       EmitStatement (ec);
+               }
        }
 
        /// <summary>
@@ -1303,30 +1334,28 @@ namespace Mono.CSharp {
        ///   would be "unsigned int".
        ///
        /// </summary>
-       public class EmptyCast : Expression
+       public abstract class TypeCast : Expression
        {
-               protected Expression child;
+               protected readonly Expression child;
 
-               protected EmptyCast (Expression child, Type return_type)
+               protected TypeCast (Expression child, Type return_type)
                {
                        eclass = child.eclass;
                        loc = child.Location;
                        type = return_type;
                        this.child = child;
                }
-               
-               public static Expression Create (Expression child, Type type)
-               {
-                       Constant c = child as Constant;
-                       if (c != null)
-                               return new EmptyConstantCast (c, type);
-
-                       return new EmptyCast (child, type);
-               }
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       return child.CreateExpressionTree (ec);
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (child.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+
+                       if (type.IsPointer || child.Type.IsPointer)
+                               Error_PointerInsideExpressionTree ();
+
+                       return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -1347,18 +1376,55 @@ namespace Mono.CSharp {
                        return child.GetAttributableValue (value_type, out value);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       child.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
-                       EmptyCast target = (EmptyCast) t;
+                       // Nothing to clone
+               }
+
+               public override bool IsNull {
+                       get { return child.IsNull; }
+               }
+       }
+
+       public class EmptyCast : TypeCast {
+               EmptyCast (Expression child, Type target_type)
+                       : base (child, target_type)
+               {
+               }
+
+               public static Expression Create (Expression child, Type type)
+               {
+                       Constant c = child as Constant;
+                       if (c != null)
+                               return new EmptyConstantCast (c, type);
+
+                       EmptyCast e = child as EmptyCast;
+                       if (e != null)
+                               return new EmptyCast (e.child, type);
+
+                       return new EmptyCast (child, type);
+               }
+
+               public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
+               {
+                       child.EmitBranchable (ec, label, on_true);
+               }
 
-                       target.child = child.Clone (clonectx);
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       child.EmitSideEffect (ec);
                }
        }
 
        /// <summary>
        ///    Performs a cast using an operator (op_Explicit or op_Implicit)
        /// </summary>
-       public class OperatorCast : EmptyCast {
+       public class OperatorCast : TypeCast {
                MethodInfo conversion_operator;
                bool find_explicit;
                        
@@ -1389,7 +1455,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo oper in mi) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
-                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                               if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
                                        return oper;
                        }
 
@@ -1415,7 +1481,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///     This is a numeric cast to a Decimal
        /// </summary>
-       public class CastToDecimal : EmptyCast {
+       public class CastToDecimal : TypeCast {
                MethodInfo conversion_operator;
 
                public CastToDecimal (Expression child)
@@ -1444,7 +1510,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo oper in mi) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
-                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                               if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
                                        return oper;
                        }
 
@@ -1462,7 +1528,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///     This is an explicit numeric cast from a Decimal
        /// </summary>
-       public class CastFromDecimal : EmptyCast
+       public class CastFromDecimal : TypeCast
        {
                static IDictionary operators;
 
@@ -1487,7 +1553,7 @@ namespace Mono.CSharp {
                                foreach (MethodInfo oper in all_oper) {
                                        ParameterData pd = TypeManager.GetParameterData (oper);
                                        if (pd.ParameterType (0) == TypeManager.decimal_type)
-                                               operators.Add (oper.ReturnType, oper);
+                                               operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper);
                                }
                        }
 
@@ -1537,6 +1603,17 @@ namespace Mono.CSharp {
                        return child.ConvertExplicitly (in_checked_context, target_type);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (child.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       if (type.IsPointer)
+                               Error_PointerInsideExpressionTree ();
+
+                       return CreateExpressionFactoryCall ("Convert", args);
+               }
+
                public override Constant Increment ()
                {
                        return child.Increment ();
@@ -1556,13 +1633,23 @@ namespace Mono.CSharp {
 
                public override bool IsZeroInteger {
                        get { return child.IsZeroInteger; }
-               }               
+               }
                
                public override void Emit (EmitContext ec)
                {
                        child.Emit (ec);
                }
 
+               public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
+               {
+                       child.EmitBranchable (ec, label, on_true);
+               }
+
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       child.EmitSideEffect (ec);
+               }
+
                public override Constant ConvertImplicitly (Type target_type)
                {
                        // FIXME: Do we need to check user conversions?
@@ -1600,6 +1687,16 @@ namespace Mono.CSharp {
                        Child.Emit (ec);
                }
 
+               public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
+               {
+                       Child.EmitBranchable (ec, label, on_true);
+               }
+
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       Child.EmitSideEffect (ec);
+               }
+
                public override bool GetAttributableValue (Type value_type, out object value)
                {
                        value = GetTypedValue ();
@@ -1691,7 +1788,7 @@ namespace Mono.CSharp {
        ///   The effect of it is to box the value type emitted by the previous
        ///   operation.
        /// </summary>
-       public class BoxedCast : EmptyCast {
+       public class BoxedCast : TypeCast {
 
                public BoxedCast (Expression expr, Type target_type)
                        : base (expr, target_type)
@@ -1713,9 +1810,20 @@ namespace Mono.CSharp {
                        
                        ec.ig.Emit (OpCodes.Box, child.Type);
                }
+
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType
+                       // so, we need to emit the box+pop instructions in most cases
+                       if (child.Type.IsValueType &&
+                           (type == TypeManager.object_type || type == TypeManager.value_type))
+                               child.EmitSideEffect (ec);
+                       else
+                               base.EmitSideEffect (ec);
+               }
        }
 
-       public class UnboxCast : EmptyCast {
+       public class UnboxCast : TypeCast {
                public UnboxCast (Expression expr, Type return_type)
                        : base (expr, return_type)
                {
@@ -1753,6 +1861,11 @@ namespace Mono.CSharp {
                                LoadFromPtr (ig, t);
                        }
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       type = storey.MutateType (type);
+               }
        }
        
        /// <summary>
@@ -1762,7 +1875,7 @@ namespace Mono.CSharp {
        ///   context, so they should generate the conv.ovf opcodes instead of
        ///   conv opcodes.
        /// </summary>
-       public class ConvCast : EmptyCast {
+       public class ConvCast : TypeCast {
                public enum Mode : byte {
                        I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
                        U1_I1, U1_CH,
@@ -1970,25 +2083,13 @@ namespace Mono.CSharp {
                }
        }
        
-       public class OpcodeCast : EmptyCast {
-               OpCode op, op2;
-               bool second_valid;
+       public class OpcodeCast : TypeCast {
+               readonly OpCode op;
                
                public OpcodeCast (Expression child, Type return_type, OpCode op)
                        : base (child, return_type)
-                       
-               {
-                       this.op = op;
-                       second_valid = false;
-               }
-
-               public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
-                       : base (child, return_type)
-                       
                {
                        this.op = op;
-                       this.op2 = op2;
-                       second_valid = true;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -2003,21 +2104,26 @@ namespace Mono.CSharp {
                {
                        base.Emit (ec);
                        ec.ig.Emit (op);
+               }
 
-                       if (second_valid)
-                               ec.ig.Emit (op2);
-               }                       
+               public Type UnderlyingType {
+                       get { return child.Type; }
+               }
        }
 
        /// <summary>
        ///   This kind of cast is used to encapsulate a child and cast it
        ///   to the class requested
        /// </summary>
-       public class ClassCast : EmptyCast {
+       public sealed class ClassCast : TypeCast {
+               Type child_generic_parameter;
+
                public ClassCast (Expression child, Type return_type)
                        : base (child, return_type)
                        
                {
+                       if (TypeManager.IsGenericParameter (child.Type))
+                               child_generic_parameter = child.Type;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -2032,8 +2138,8 @@ namespace Mono.CSharp {
                {
                        base.Emit (ec);
 
-                       if (TypeManager.IsGenericParameter (child.Type))
-                               ec.ig.Emit (OpCodes.Box, child.Type);
+                       if (child_generic_parameter != null)
+                               ec.ig.Emit (OpCodes.Box, child_generic_parameter);
 
 #if GMCS_SOURCE
                        if (type.IsGenericParameter)
@@ -2042,38 +2148,192 @@ namespace Mono.CSharp {
 #endif
                                ec.ig.Emit (OpCodes.Castclass, type);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       type = storey.MutateType (type);
+                       if (child_generic_parameter != null)
+                               child_generic_parameter = storey.MutateGenericArgument (child_generic_parameter);
+
+                       base.MutateHoistedGenericType (storey);
+               }
+       }
+
+       //
+       // Used when resolved expression has different representations for
+       // expression trees and emit phase
+       //
+       public class ReducedExpression : Expression
+       {
+               class ReducedConstantExpression : Constant
+               {
+                       readonly Constant expr;
+                       readonly Expression orig_expr;
+
+                       public ReducedConstantExpression (Constant expr, Expression orig_expr)
+                               : base (expr.Location)
+                       {
+                               this.expr = expr;
+                               this.orig_expr = orig_expr;
+                               eclass = expr.eclass;
+                               type = expr.Type;
+                       }
+
+                       public override string AsString ()
+                       {
+                               return expr.AsString ();
+                       }
+
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               return orig_expr.CreateExpressionTree (ec);
+                       }
+
+                       public override object GetValue ()
+                       {
+                               return expr.GetValue ();
+                       }
+
+                       public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               return this;
+                       }
+
+                       public override Constant Increment ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public override bool IsDefaultValue {
+                               get {
+                                       return expr.IsDefaultValue;
+                               }
+                       }
+
+                       public override bool IsNegative {
+                               get {
+                                       return expr.IsNegative;
+                               }
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               expr.Emit (ec);
+                       }
+               }
+
+               readonly Expression expr, orig_expr;
+
+               private ReducedExpression (Expression expr, Expression orig_expr)
+               {
+                       this.expr = expr;
+                       this.orig_expr = orig_expr;
+                       this.loc = orig_expr.Location;
+               }
+
+               public static Expression Create (Constant expr, Expression original_expr)
+               {
+                       return new ReducedConstantExpression (expr, original_expr);
+               }
+
+               public static Expression Create (Expression expr, Expression original_expr)
+               {
+                       Constant c = expr as Constant;
+                       if (c != null)
+                               return Create (c, original_expr);
+
+                       return new ReducedExpression (expr, original_expr);
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return orig_expr.CreateExpressionTree (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = expr.eclass;
+                       type = expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       expr.Emit (ec);
+               }
+
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
+               {
+                       expr.EmitBranchable (ec, target, on_true);
+               }
+       }
+
+       //
+       // Unresolved type name expressions
+       //
+       public abstract class ATypeNameExpression : FullNamedExpression
+       {
+               public readonly string Name;
+               protected TypeArguments targs;
+
+               protected ATypeNameExpression (string name, Location l)
+               {
+                       Name = name;
+                       loc = l;
+               }
+
+               protected ATypeNameExpression (string name, TypeArguments targs, Location l)
+               {
+                       Name = name;
+                       this.targs = targs;
+                       loc = l;
+               }
+
+               public bool HasTypeArguments {
+                       get {
+                               return targs != null;
+                       }
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       if (targs != null) {
+                               return TypeManager.RemoveGenericArity (Name) + "<" +
+                                       targs.GetSignatureForError () + ">";
+                       }
+
+                       return Name;
+               }
        }
        
        /// <summary>
        ///   SimpleName expressions are formed of a single word and only happen at the beginning 
        ///   of a dotted-name.
        /// </summary>
-       public class SimpleName : Expression {
-               public readonly string Name;
-               public readonly TypeArguments Arguments;
+       public class SimpleName : ATypeNameExpression {
                bool in_transit;
 
                public SimpleName (string name, Location l)
+                       : base (name, l)
                {
-                       Name = name;
-                       loc = l;
                }
 
                public SimpleName (string name, TypeArguments args, Location l)
+                       : base (name, args, l)
                {
-                       Name = name;
-                       Arguments = args;
-                       loc = l;
                }
 
                public SimpleName (string name, TypeParameter[] type_params, Location l)
+                       : base (name, l)
                {
-                       Name = name;
-                       loc = l;
-
-                       Arguments = new TypeArguments (l);
+                       targs = new TypeArguments (l);
                        foreach (TypeParameter type_param in type_params)
-                               Arguments.Add (new TypeParameterExpr (type_param, l));
+                               targs.Add (new TypeParameterExpr (type_param, l));
                }
 
                public static string RemoveGenericArity (string name)
@@ -2106,7 +2366,7 @@ namespace Mono.CSharp {
 
                public SimpleName GetMethodGroup ()
                {
-                       return new SimpleName (RemoveGenericArity (Name), Arguments, loc);
+                       return new SimpleName (RemoveGenericArity (Name), targs, loc);
                }
 
                public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
@@ -2170,7 +2430,7 @@ namespace Mono.CSharp {
 
                        Type[] gen_params = TypeManager.GetTypeArguments (t);
 
-                       int arg_count = Arguments != null ? Arguments.Count : 0;
+                       int arg_count = targs != null ? targs.Count : 0;
 
                        for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
                                if (arg_count + ds.CountTypeParameters == gen_params.Length) {
@@ -2178,8 +2438,8 @@ namespace Mono.CSharp {
                                        foreach (TypeParameter param in ds.TypeParameters)
                                                new_args.Add (new TypeParameterExpr (param, loc));
 
-                                       if (Arguments != null)
-                                               new_args.Add (Arguments);
+                                       if (targs != null)
+                                               new_args.Add (targs);
 
                                        return new ConstructedType (t, new_args, loc);
                                }
@@ -2205,8 +2465,8 @@ namespace Mono.CSharp {
                                if (nested != null)
                                        return nested.ResolveAsTypeStep (ec, false);
 
-                               if (Arguments != null) {
-                                       ConstructedType ct = new ConstructedType (fne, Arguments, loc);
+                               if (targs != null) {
+                                       ConstructedType ct = new ConstructedType (fne, targs, loc);
                                        return ct.ResolveAsTypeStep (ec, false);
                                }
 
@@ -2245,7 +2505,7 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (Arguments != null) {
+                       if (targs != null) {
                                FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
                                if (retval != null) {
                                        Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc);
@@ -2322,7 +2582,7 @@ namespace Mono.CSharp {
                        if (current_block != null){
                                LocalInfo vi = current_block.GetLocalInfo (Name);
                                if (vi != null){
-                                       if (Arguments != null) {
+                                       if (targs != null) {
                                                Report.Error (307, loc,
                                                              "The variable `{0}' cannot be used with type arguments",
                                                              Name);
@@ -2342,7 +2602,7 @@ namespace Mono.CSharp {
 
                                ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
                                if (pref != null) {
-                                       if (Arguments != null) {
+                                       if (targs != null) {
                                                Report.Error (307, loc,
                                                              "The variable `{0}' cannot be used with type arguments",
                                                              Name);
@@ -2428,11 +2688,11 @@ namespace Mono.CSharp {
                        }
 
                        if (e is TypeExpr) {
-                               if (Arguments == null)
+                               if (targs == null)
                                        return e;
 
                                ConstructedType ct = new ConstructedType (
-                                       (FullNamedExpression) e, Arguments, loc);
+                                       e.Type, targs, loc);
                                return ct.ResolveAsTypeStep (ec, false);
                        }
 
@@ -2452,7 +2712,7 @@ namespace Mono.CSharp {
                                                if (!me.IsStatic &&
                                                    (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
                                                        Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
-                                                       return EmptyExpression.Null;
+                                                       return null;
                                                }
 
                                                //
@@ -2470,9 +2730,9 @@ namespace Mono.CSharp {
                                if (me == null)
                                        return null;
 
-                               if (Arguments != null) {
-                                       Arguments.Resolve (ec);
-                                       me.SetTypeArguments (Arguments);
+                               if (targs != null) {
+                                       targs.Resolve (ec);
+                                       me.SetTypeArguments (targs);
                                }
 
                                if (!me.IsStatic && (me.InstanceExpression != null) &&
@@ -2493,26 +2753,6 @@ namespace Mono.CSharp {
                        return e;
                }
                
-               public override void Emit (EmitContext ec)
-               {
-                       throw new InternalErrorException ("The resolve phase was not executed");
-               }
-
-               public override string ToString ()
-               {
-                       return Name;
-               }
-
-               public override string GetSignatureForError ()
-               {
-                       if (Arguments != null) {
-                               return TypeManager.RemoveGenericArity (Name) + "<" +
-                                       Arguments.GetSignatureForError () + ">";
-                       }
-
-                       return Name;
-               }
-
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
                        // CloneTo: Nothing, we do not keep any state on this expression
@@ -2524,13 +2764,21 @@ namespace Mono.CSharp {
        ///   section 10.8.1 (Fully Qualified Names).
        /// </summary>
        public abstract class FullNamedExpression : Expression {
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
                        return this;
                }
 
-               public abstract string FullName {
-                       get;
+               public override void Emit (EmitContext ec)
+               {
+                       throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
+                               GetSignatureForError ());
                }
        }
        
@@ -2553,19 +2801,14 @@ namespace Mono.CSharp {
                        return ResolveAsTypeTerminal (ec, false);
                }
 
-               override public void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Should never be called");
-               }
-
                public virtual bool CheckAccessLevel (DeclSpace ds)
                {
                        return ds.CheckAccessLevel (Type);
                }
 
-               public virtual bool AsAccessible (DeclSpace ds, int flags)
+               public virtual bool AsAccessible (DeclSpace ds)
                {
-                       return ds.AsAccessible (Type, flags);
+                       return ds.IsAccessibleAs (Type);
                }
 
                public virtual bool IsClass {
@@ -2598,10 +2841,6 @@ namespace Mono.CSharp {
 
                protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
 
-               public abstract string Name {
-                       get;
-               }
-
                public override bool Equals (object obj)
                {
                        TypeExpr tobj = obj as TypeExpr;
@@ -2615,10 +2854,10 @@ namespace Mono.CSharp {
                {
                        return Type.GetHashCode ();
                }
-               
-               public override string ToString ()
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                {
-                       return Name;
+                       type = storey.MutateType (type);
                }
        }
 
@@ -2642,14 +2881,6 @@ namespace Mono.CSharp {
                {
                        return this;
                }
-
-               public override string Name {
-                       get { return Type.ToString (); }
-               }
-
-               public override string FullName {
-                       get { return Type.FullName; }
-               }
        }
 
        /// <summary>
@@ -2783,14 +3014,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override string Name {
-                       get { return name; }
-               }
-
-               public override string FullName {
-                       get { return name; }
-               }
-
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
                        // CloneTo: Nothing, we do not keep any state on this expression
@@ -2819,6 +3042,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       // Nothing to clone
+               }
+
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
                        Expression expr;
@@ -2836,99 +3064,6 @@ namespace Mono.CSharp {
                        type = fne.Type;
                        return new TypeExpression (type, loc);
                }
-
-               public override string Name {
-                       get { return name.FullName; }
-               }
-
-               public override string FullName {
-                       get { return name.FullName; }
-               }
-       }
-
-       public class TypeAliasExpression : TypeExpr {
-               FullNamedExpression alias;
-               TypeExpr texpr;
-               TypeArguments args;
-               string name;
-
-               public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
-               {
-                       this.alias = alias;
-                       this.args = args;
-                       loc = l;
-
-                       eclass = ExprClass.Type;
-                       if (args != null)
-                               name = alias.FullName + "<" + args.ToString () + ">";
-                       else
-                               name = alias.FullName;
-               }
-
-               public override string Name {
-                       get { return alias.FullName; }
-               }
-
-               public override string FullName {
-                       get { return name; }
-               }
-
-               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
-               {
-                       texpr = alias.ResolveAsTypeTerminal (ec, false);
-                       if (texpr == null)
-                               return null;
-
-                       Type type = texpr.Type;
-                       int num_args = TypeManager.GetNumberOfTypeArguments (type);
-
-                       if (args != null) {
-                               if (num_args == 0) {
-                                       Report.Error (308, loc,
-                                                     "The non-generic type `{0}' cannot " +
-                                                     "be used with type arguments.",
-                                                     TypeManager.CSharpName (type));
-                                       return null;
-                               }
-
-                               ConstructedType ctype = new ConstructedType (type, args, loc);
-                               return ctype.ResolveAsTypeTerminal (ec, false);
-                       } else if (num_args > 0) {
-                               Report.Error (305, loc,
-                                             "Using the generic type `{0}' " +
-                                             "requires {1} type arguments",
-                                             TypeManager.CSharpName (type), num_args.ToString ());
-                               return null;
-                       }
-
-                       return texpr;
-               }
-
-               public override bool CheckAccessLevel (DeclSpace ds)
-               {
-                       return texpr.CheckAccessLevel (ds);
-               }
-
-               public override bool AsAccessible (DeclSpace ds, int flags)
-               {
-                       return texpr.AsAccessible (ds, flags);
-               }
-
-               public override bool IsClass {
-                       get { return texpr.IsClass; }
-               }
-
-               public override bool IsValueType {
-                       get { return texpr.IsValueType; }
-               }
-
-               public override bool IsInterface {
-                       get { return texpr.IsInterface; }
-               }
-
-               public override bool IsSealed {
-                       get { return texpr.IsSealed; }
-               }
        }
 
        /// <summary>
@@ -2987,6 +3122,17 @@ namespace Mono.CSharp {
                                      "with an instance reference, qualify it with a type name instead", name);
                }
 
+               public static void Error_BaseAccessInExpressionTree (Location loc)
+               {
+                       Report.Error (831, loc, "An expression tree may not contain a base access");
+               }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (InstanceExpression != null)
+                               InstanceExpression.MutateHoistedGenericType (storey);
+               }
+
                // TODO: possible optimalization
                // Cache resolved constant result in FieldBuilder <-> expression map
                public virtual MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
@@ -3100,11 +3246,8 @@ namespace Mono.CSharp {
                        base.EmitCall (ec, arguments);
                }
 
-               public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc)
+               public override MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList arguments, bool may_fail, Location loc)
                {
-                       if ((ExtensionExpression.eclass & (ExprClass.Value | ExprClass.Variable)) == 0)
-                               return base.OverloadResolve (ec, arguments, may_fail, loc);
-
                        if (arguments == null)
                                arguments = new ArrayList (1);
 
@@ -3122,7 +3265,7 @@ namespace Mono.CSharp {
                MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
                {
                        // Use normal resolve rules
-                       MethodGroupExpr mg = base.OverloadResolve (ec, arguments, ns != null, loc);
+                       MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
                        if (mg != null)
                                return mg;
 
@@ -3130,11 +3273,12 @@ namespace Mono.CSharp {
                                return null;
 
                        // Search continues
-                       ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name);
+                       ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name, loc);
                        if (e == null)
-                               return base.OverloadResolve (ec, arguments, false, loc);
+                               return base.OverloadResolve (ec, ref arguments, false, loc);
 
                        e.ExtensionExpression = ExtensionExpression;
+                       e.SetTypeArguments (type_arguments);                    
                        return e.ResolveOverloadExtensions (ec, arguments, e.namespace_entry, loc);
                }               
        }
@@ -3266,57 +3410,84 @@ namespace Mono.CSharp {
                        return (MethodInfo)mg.best_candidate;
                }
 
-               /// <summary>
-               ///   Determines "better conversion" as specified in 14.4.2.3
-               ///
-               ///    Returns : p    if a->p is better,
-               ///              q    if a->q is better,
-               ///              null if neither is better
-               /// </summary>
-               static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q)
+               //
+               //  7.4.3.3  Better conversion from expression
+               //  Returns :   1    if a->p is better,
+               //              2    if a->q is better,
+               //              0 if neither is better
+               //
+               static int BetterExpressionConversion (EmitContext ec, Argument a, Type p, Type q)
                {
                        Type argument_type = TypeManager.TypeToCoreType (a.Type);
-                       Expression argument_expr = a.Expr;
+                       if (argument_type == TypeManager.anonymous_method_type && RootContext.Version > LanguageVersion.ISO_2) {
+                               //
+                               // Uwrap delegate from Expression<T>
+                               //
+                               if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) {
+                                       p = TypeManager.GetTypeArguments (p) [0];
+                               }
+                               if (TypeManager.DropGenericTypeArguments (q) == TypeManager.expression_type) {
+                                       q = TypeManager.GetTypeArguments (q) [0];
+                               }
+                               
+                               p = Delegate.GetInvokeMethod (null, p).ReturnType;
+                               q = Delegate.GetInvokeMethod (null, q).ReturnType;
+                               if (p == TypeManager.void_type && q != TypeManager.void_type)
+                                       return 2;
+                               if (q == TypeManager.void_type && p != TypeManager.void_type)
+                                       return 1;
+                       } else {
+                               if (argument_type == p)
+                                       return 1;
 
-                       if (argument_type == null)
-                               throw new Exception ("Expression of type " + a.Expr +
-                                       " does not resolve its type");
+                               if (argument_type == q)
+                                       return 2;
+                       }
 
-                       if (p == null || q == null)
-                               throw new InternalErrorException ("BetterConversion Got a null conversion");
+                       return BetterTypeConversion (ec, p, q);
+               }
 
-                       if (p == q)
-                               return null;
+               //
+               // 7.4.3.4  Better conversion from type
+               //
+               public static int BetterTypeConversion (EmitContext ec, Type p, Type q)
+               {
+                       if (p == null || q == null)
+                               throw new InternalErrorException ("BetterTypeConversion got a null conversion");
 
-                       if (argument_expr is NullLiteral) 
-                       {
-                               //
-                               // If the argument is null and one of the types to compare is 'object' and
-                               // the other is a reference type, we prefer the other.
-                               //
-                               // This follows from the usual rules:
-                               //   * There is an implicit conversion from 'null' to type 'object'
-                               //   * There is an implicit conversion from 'null' to any reference type
-                               //   * There is an implicit conversion from any reference type to type 'object'
-                               //   * There is no implicit conversion from type 'object' to other reference types
-                               //  => Conversion of 'null' to a reference type is better than conversion to 'object'
-                               //
-                               //  FIXME: This probably isn't necessary, since the type of a NullLiteral is the 
-                               //         null type. I think it used to be 'object' and thus needed a special 
-                               //         case to avoid the immediately following two checks.
-                               //
-                               if (!p.IsValueType && q == TypeManager.object_type)
-                                       return p;
-                               if (!q.IsValueType && p == TypeManager.object_type)
-                                       return q;
+                       if (p == TypeManager.int32_type) {
+                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.int64_type) {
+                               if (q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.sbyte_type) {
+                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
+                                       q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.short_type) {
+                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
+                                       q == TypeManager.uint64_type)
+                                       return 1;
                        }
-                                
-                       if (argument_type == p)
-                               return p;
 
-                       if (argument_type == q)
-                               return q;
+                       if (q == TypeManager.int32_type) {
+                               if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return 2;
+                       } if (q == TypeManager.int64_type) {
+                               if (p == TypeManager.uint64_type)
+                                       return 2;
+                       } else if (q == TypeManager.sbyte_type) {
+                               if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+                                       p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return 2;
+                       } if (q == TypeManager.short_type) {
+                               if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
+                                       p == TypeManager.uint64_type)
+                                       return 2;
+                       }
 
+                       // TODO: this is expensive
                        Expression p_tmp = new EmptyExpression (p);
                        Expression q_tmp = new EmptyExpression (q);
 
@@ -3324,44 +3495,12 @@ namespace Mono.CSharp {
                        bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
 
                        if (p_to_q && !q_to_p)
-                               return p;
+                               return 1;
 
                        if (q_to_p && !p_to_q)
-                               return q;
-
-                       if (p == TypeManager.sbyte_type)
-                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
-                                       q == TypeManager.uint32_type || q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.sbyte_type)
-                               if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
-                                       p == TypeManager.uint32_type || p == TypeManager.uint64_type)
-                                       return q;
-
-                       if (p == TypeManager.short_type)
-                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
-                                       q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.short_type)
-                               if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
-                                       p == TypeManager.uint64_type)
-                                       return q;
-
-                       if (p == TypeManager.int32_type)
-                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.int32_type)
-                               if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
-                                       return q;
-
-                       if (p == TypeManager.int64_type)
-                               if (q == TypeManager.uint64_type)
-                                       return p;
-                       if (q == TypeManager.int64_type)
-                               if (p == TypeManager.uint64_type)
-                                       return q;
+                               return 2;
 
-                       return null;
+                       return 0;
                }
 
                /// <summary>
@@ -3405,16 +3544,16 @@ namespace Mono.CSharp {
                                        continue;
 
                                same = false;
-                               Type better = BetterConversion (ec, a, ct, bt);
+                               int result = BetterExpressionConversion (ec, a, ct, bt);
 
                                // for each argument, the conversion to 'ct' should be no worse than 
                                // the conversion to 'bt'.
-                               if (better == bt)
+                               if (result == 2)
                                        return false;
 
                                // for at least one argument, the conversion to 'ct' should be better than 
                                // the conversion to 'bt'.
-                               if (better == ct)
+                               if (result != 0)
                                        better_at_least_one = true;
                        }
 
@@ -3520,7 +3659,20 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       return new Cast (new TypeExpression (typeof (MethodInfo), loc), new TypeOfMethod (this));
+                       if (best_candidate == null) {
+                               Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
+                               return null;
+                       }
+
+                       if (best_candidate.IsConstructor)
+                               return new TypeOfConstructorInfo (best_candidate, loc);
+
+                       IMethodData md = TypeManager.GetMethod (best_candidate);
+                       if (md != null && md.IsExcluded ())
+                               Report.Error (765, loc,
+                                       "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
+                       
+                       return new TypeOfMethodInfo (best_candidate, loc);
                }
                
                override public Expression DoResolve (EmitContext ec)
@@ -3547,7 +3699,7 @@ namespace Mono.CSharp {
                
                public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
                {
-                       Invocation.EmitArguments (ec, best_candidate, arguments, false, null);  
+                       Invocation.EmitArguments (ec, arguments, false, null);  
                }
                
                public virtual void EmitCall (EmitContext ec, ArrayList arguments)
@@ -3558,6 +3710,8 @@ namespace Mono.CSharp {
                protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method,
                                                                                                        Argument a, ParameterData expected_par, Type paramType)
                {
+                       ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr;
+
                        if (a is CollectionElementInitializer.ElementInitializerArgument) {
                                Report.SymbolRelatedToPreviousError (method);
                                if ((expected_par.ParameterModifier (idx) & Parameter.Modifier.ISBYREF) != 0) {
@@ -3569,8 +3723,15 @@ namespace Mono.CSharp {
                                          TypeManager.CSharpSignature (method));
                        } else if (delegate_type == null) {
                                Report.SymbolRelatedToPreviousError (method);
-                               Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
-                                                 TypeManager.CSharpSignature (method));
+                               if (emg != null) {
+                                       Report.Error (1928, loc,
+                                               "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
+                                               emg.ExtensionExpression.GetSignatureForError (),
+                                               emg.Name, TypeManager.CSharpSignature (method));
+                               } else {
+                                       Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
+                                               TypeManager.CSharpSignature (method));
+                               }
                        } else
                                Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
                                        TypeManager.CSharpName (delegate_type));
@@ -3578,16 +3739,16 @@ namespace Mono.CSharp {
                        Parameter.Modifier mod = expected_par.ParameterModifier (idx);
 
                        string index = (idx + 1).ToString ();
-                       if ((mod & Parameter.Modifier.ISBYREF) != (a.Modifier & Parameter.Modifier.ISBYREF) ||
-                               (mod & Parameter.Modifier.ISBYREF) != 0) {
-                               if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0)
-                                       Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword",
+                       if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
+                               (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
+                               if ((mod & Parameter.Modifier.ISBYREF) == 0)
+                                       Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
                                                index, Parameter.GetModifierSignature (a.Modifier));
                                else
-                                       Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
+                                       Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
                                                index, Parameter.GetModifierSignature (mod));
                        } else {
-                               string p1 = Argument.FullDesc (a);
+                               string p1 = a.GetSignatureForError ();
                                string p2 = TypeManager.CSharpName (paramType);
 
                                if (p1 == p2) {
@@ -3595,9 +3756,22 @@ namespace Mono.CSharp {
                                        Report.SymbolRelatedToPreviousError (a.Expr.Type);
                                        Report.SymbolRelatedToPreviousError (paramType);
                                }
-                               Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2);
+
+                               if (idx == 0 && emg != null) {
+                                       Report.Error (1929, loc,
+                                               "Extension method instance type `{0}' cannot be converted to `{1}'", p1, p2);
+                               } else {
+                                       Report.Error (1503, loc,
+                                               "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
+                               }
                        }
                }
+
+               public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
+               {
+                       Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
+                               Name, TypeManager.CSharpName (target));
+               }
                
                protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
                {
@@ -3652,7 +3826,8 @@ namespace Mono.CSharp {
                                                return score - 20000;
 
                                        if (TypeManager.IsGenericMethodDefinition (candidate))
-                                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
+                                               throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution",
+                                                       TypeManager.CSharpSignature (candidate));
 
                                        pd = TypeManager.GetParameterData (candidate);
                                }
@@ -3665,6 +3840,7 @@ namespace Mono.CSharp {
                        //
                        // 2. Each argument has to be implicitly convertible to method parameter
                        //
+                       method = candidate;
                        Parameter.Modifier p_mod = 0;
                        Type pt = null;
                        for (int i = 0; i < arg_count; i++) {
@@ -3698,14 +3874,16 @@ namespace Mono.CSharp {
                                                params_expanded_form = true;
                                }
 
-                               if (score != 0)
+                               if (score != 0) {
+                                       if (params_expanded_form)
+                                               ++score;
                                        return (arg_count - i) * 2 + score;
+                               }
                        }
                        
                        if (arg_count != param_count)
                                params_expanded_form = true;                    
                        
-                       method = candidate;                     
                        return 0;
                }
 
@@ -3724,26 +3902,16 @@ namespace Mono.CSharp {
 
                                if (a_type != parameter)
                                        return 2;
-
-                               return 0;
-                       }
-
-                       // FIXME: Kill this abomination (EmitContext.TempEc)
-                       EmitContext prevec = EmitContext.TempEc;
-                       EmitContext.TempEc = ec;
-                       try {
+                       } else {
                                if (delegate_type != null ?
                                        !Delegate.IsTypeCovariant (argument.Expr, parameter) :
                                        !Convert.ImplicitConversionExists (ec, argument.Expr, parameter))
                                        return 2;
-
-                               if (arg_mod != param_mod)
-                                       return 1;
-
-                       } finally {
-                               EmitContext.TempEc = prevec;
                        }
 
+                       if (arg_mod != param_mod)
+                               return 1;
+
                        return 0;
                }
 
@@ -3860,6 +4028,19 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       base.MutateHoistedGenericType (storey);
+
+                       MethodInfo mi = best_candidate as MethodInfo;
+                       if (mi != null) {
+                               best_candidate = storey.MutateGenericMethod (mi);
+                               return;
+                       }
+
+                       best_candidate = storey.MutateConstructor ((ConstructorInfo) this);
+               }
+
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -3876,7 +4057,7 @@ namespace Mono.CSharp {
                ///            that is the best match of me on Arguments.
                ///
                /// </summary>
-               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments,
+               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList Arguments,
                        bool may_fail, Location loc)
                {
                        bool method_params = false;
@@ -3989,8 +4170,12 @@ namespace Mono.CSharp {
                        }
 
                        Report.SetMessageRecorder (prev_recorder);
-                       if (msg_recorder != null && msg_recorder.PrintMessages ())
+                       if (msg_recorder != null && !msg_recorder.IsEmpty) {
+                               if (!may_fail)
+                                       msg_recorder.PrintMessages ();
+
                                return null;
+                       }
                        
                        int candidate_top = candidates.Count;
 
@@ -4000,11 +4185,11 @@ namespace Mono.CSharp {
                                // not an extension method. We start extension methods lookup from here
                                //
                                if (InstanceExpression != null) {
-                                       ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name);
+                                       ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name, loc);
                                        if (ex_method_lookup != null) {
                                                ex_method_lookup.ExtensionExpression = InstanceExpression;
                                                ex_method_lookup.SetTypeArguments (type_arguments);
-                                               return ex_method_lookup.OverloadResolve (ec, Arguments, may_fail, loc);
+                                               return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
                                        }
                                }
                                
@@ -4024,7 +4209,7 @@ namespace Mono.CSharp {
                                        ParameterData pd = TypeManager.GetParameterData (best_candidate);
                                        bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
                                        if (arg_count == pd.Count || pd.HasParams) {
-                                               if (TypeManager.IsGenericMethod (best_candidate)) {
+                                               if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
                                                        if (type_arguments == null) {
                                                                Report.Error (411, loc,
                                                                        "The type arguments for method `{0}' cannot be inferred from " +
@@ -4042,15 +4227,14 @@ namespace Mono.CSharp {
                                                                return null;
                                                        }
                                                } else {
-                                                       if (type_arguments != null) {
+                                                       if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
                                                                Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
                                                                return null;
                                                        }
                                                }
                                                
-                                               if (VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
-                                                       throw new InternalErrorException ("Overload verification expected failure");
-                                               return null;
+                                               if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
+                                                       return null;
                                        }
                                }
 
@@ -4132,7 +4316,9 @@ namespace Mono.CSharp {
                        //
 
                        best_candidate = (MethodBase) candidates [0];
-                       method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+                       if (delegate_type == null)
+                               method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+
                        for (int ix = 1; ix < candidate_top; ix++) {
                                MethodBase candidate = (MethodBase) candidates [ix];
 
@@ -4153,7 +4339,7 @@ namespace Mono.CSharp {
                        // should be better than all the others
                        //
                        MethodBase ambiguous = null;
-                       for (int ix = 0; ix < candidate_top; ix++) {
+                       for (int ix = 1; ix < candidate_top; ix++) {
                                MethodBase candidate = (MethodBase) candidates [ix];
 
                                if (candidate == best_candidate)
@@ -4223,7 +4409,7 @@ namespace Mono.CSharp {
                        // necessary etc. and return if everything is
                        // all right
                        //
-                       if (!VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate,
+                       if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate,
                                method_params, may_fail, loc))
                                return null;
 
@@ -4249,7 +4435,7 @@ namespace Mono.CSharp {
                        type_arguments = ta;
                }
 
-               public bool VerifyArgumentsCompat (EmitContext ec, ArrayList arguments,
+               public bool VerifyArgumentsCompat (EmitContext ec, ref ArrayList arguments,
                                                          int arg_count, MethodBase method,
                                                          bool chose_params_expanded,
                                                          bool may_fail, Location loc)
@@ -4259,9 +4445,11 @@ namespace Mono.CSharp {
                        int errors = Report.Errors;
                        Parameter.Modifier p_mod = 0;
                        Type pt = null;
-                       int a_idx = 0;
+                       int a_idx = 0, a_pos = 0;
                        Argument a = null;
-                       for (; a_idx < arg_count; a_idx++) {
+                       ArrayList params_initializers = null;
+
+                       for (; a_idx < arg_count; a_idx++, ++a_pos) {
                                a = (Argument) arguments [a_idx];
                                if (p_mod != Parameter.Modifier.PARAMS) {
                                        p_mod = pd.ParameterModifier (a_idx);
@@ -4281,8 +4469,10 @@ namespace Mono.CSharp {
                                        }
 
                                        if (p_mod == Parameter.Modifier.PARAMS) {
-                                               if (chose_params_expanded)
+                                               if (chose_params_expanded) {
+                                                       params_initializers = new ArrayList (arg_count - a_idx);
                                                        pt = TypeManager.GetElementType (pt);
+                                               }
                                        } else if (p_mod != 0) {
                                                pt = TypeManager.GetElementType (pt);
                                        }
@@ -4300,26 +4490,62 @@ namespace Mono.CSharp {
 
                                        continue;
                                }
-               
-                               if (TypeManager.IsEqual (a.Type, pt))
-                                       continue;
-                               
-                               Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
-                               if (conv == null)
-                                       break;
 
-                               if (!chose_params_expanded && (p_mod & Parameter.Modifier.PARAMS) != 0 && a.Type == TypeManager.null_type)
-                                       conv.Type = pd.ParameterType (a_idx);
+                               Expression conv;
+                               if (TypeManager.IsEqual (a.Type, pt)) {
+                                       conv = a.Expr;
+                               } else {
+                                       conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
+                                       if (conv == null)
+                                               break;
+                               }
+
+                               //
+                               // Convert params arguments to an array initializer
+                               //
+                               if (params_initializers != null) {
+                                       // we choose to use 'a.Expr' rather than 'conv' so that
+                                       // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
+                                       params_initializers.Add (a.Expr);
+                                       arguments.RemoveAt (a_idx--);
+                                       --arg_count;
+                                       continue;
+                               }
 
                                // Update the argument with the implicit conversion
                                a.Expr = conv;
                        }
 
-                       if (a_idx == arg_count)
+                       //
+                       // Fill not provided arguments required by params modifier
+                       //
+                       if (params_initializers == null && pd.HasParams && arg_count < pd.Count && a_idx + 1 == pd.Count) {
+                               if (arguments == null)
+                                       arguments = new ArrayList (1);
+
+                               pt = pd.Types [GetApplicableParametersCount (method, pd) - 1];
+                               pt = TypeManager.GetElementType (pt);
+                               params_initializers = new ArrayList (0);
+                       }
+
+                       if (a_idx == arg_count) {
+                               //
+                               // Append an array argument with all params arguments
+                               //
+                               if (params_initializers != null) {
+                                       arguments.Add (new Argument (
+                                               new ArrayCreation (new TypeExpression (pt, loc), "[]",
+                                               params_initializers, loc).Resolve (ec)));
+                               }
                                return true;
+                       }
 
-                       if (!may_fail && Report.Errors == errors)
-                               Error_InvalidArguments (ec, loc, a_idx, method, a, pd, pt);
+                       if (!may_fail && Report.Errors == errors) {
+                               if (CustomErrorHandler != null)
+                                       CustomErrorHandler.NoExactMatch (ec, best_candidate);
+                               else
+                                       Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
+                       }
                        return false;
                }
        }
@@ -4370,6 +4596,11 @@ namespace Mono.CSharp {
                        return base.ResolveMemberAccess (ec, left, loc, original);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        IConstant ic = TypeManager.GetConstant (constant);
@@ -4396,7 +4627,8 @@ namespace Mono.CSharp {
        ///   Fully resolved expression that evaluates to a Field
        /// </summary>
        public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
-               public readonly FieldInfo FieldInfo;
+               public FieldInfo FieldInfo;
+               readonly Type constructed_generic_type;
                VariableInfo variable_info;
                
                LocalTemporary temp;
@@ -4417,6 +4649,12 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public FieldExpr (FieldInfo fi, Type genericType, Location l)
+                       : this (fi, l)
+               {
+                       this.constructed_generic_type = genericType;
+               }
+
                public override string Name {
                        get {
                                return FieldInfo.Name;
@@ -4465,6 +4703,26 @@ namespace Mono.CSharp {
                        return base.ResolveMemberAccess (ec, left, loc, original);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Expression instance;
+                       if (InstanceExpression == null) {
+                               instance = new NullLiteral (loc);
+                       } else {
+                               instance = InstanceExpression.CreateExpressionTree (ec);
+                       }
+
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (instance));
+                       args.Add (new Argument (CreateTypeOfExpression ()));
+                       return CreateExpressionFactoryCall ("Field", args);
+               }
+
+               public Expression CreateTypeOfExpression ()
+               {
+                       return new TypeOfField (FieldInfo, loc);
+               }
+
                override public Expression DoResolve (EmitContext ec)
                {
                        return DoResolve (ec, false, false);
@@ -4520,18 +4778,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       AnonymousContainer am = ec.CurrentAnonymousMethod;
-                       if (am != null){
-                               if (!FieldInfo.IsStatic){
-                                       if (!am.IsIterator && (ec.TypeContainer is Struct)){
-                                               Report.Error (1673, loc,
-                                               "Anonymous methods inside structs cannot access instance members of `{0}'. Consider copying `{0}' to a local variable outside the anonymous method and using the local instead",
-                                                       "this");
-                                               return null;
-                                       }
-                               }
-                       }
-
                        IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo);
                        if (fb != null) {
                                if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) {
@@ -4549,7 +4795,7 @@ namespace Mono.CSharp {
 
                        // If the instance expression is a local variable or parameter.
                        IVariable var = InstanceExpression as IVariable;
-                       if ((var == null) || (var.VariableInfo == null))
+                       if (var == null || var.VariableInfo == null)
                                return this;
 
                        VariableInfo vi = var.VariableInfo;
@@ -4600,7 +4846,7 @@ namespace Mono.CSharp {
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        IVariable var = InstanceExpression as IVariable;
-                       if ((var != null) && (var.VariableInfo != null))
+                       if (var != null && var.VariableInfo != null)
                                var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
 
                        bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
@@ -4638,7 +4884,7 @@ namespace Mono.CSharp {
                        }
 
                        if (right_side == EmptyExpression.OutAccess &&
-                           !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                           !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
                                Report.SymbolRelatedToPreviousError (DeclaringType);
                                Report.Warning (197, 1, loc,
                                                "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
@@ -4648,28 +4894,34 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               bool is_marshal_by_ref ()
+               {
+                       return !IsStatic && Type.IsValueType && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type);
+               }
+
                public override void CheckMarshalByRefAccess (EmitContext ec)
                {
-                       if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                       if (is_marshal_by_ref () && !(InstanceExpression is This)) {
                                Report.SymbolRelatedToPreviousError (DeclaringType);
                                Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
                                                GetSignatureForError ());
                        }
                }
 
-               public bool VerifyFixed ()
-               {
-                       IVariable variable = InstanceExpression as IVariable;
-                       // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
-                       // We defer the InstanceExpression check after the variable check to avoid a 
-                       // separate null check on InstanceExpression.
-                       return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
-               }
-
                public override int GetHashCode ()
                {
                        return FieldInfo.GetHashCode ();
                }
+               
+               public bool IsFixed {
+                       get {
+                               IVariable variable = InstanceExpression as IVariable;
+                               // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
+                               // We defer the InstanceExpression check after the variable check to avoid a 
+                               // separate null check on InstanceExpression.
+                               return variable != null && InstanceExpression.Type.IsValueType && variable.IsFixed;
+                       }
+               }               
 
                public override bool Equals (object obj)
                {
@@ -4702,21 +4954,21 @@ namespace Mono.CSharp {
                        if (FieldInfo.IsStatic){
                                if (is_volatile)
                                        ig.Emit (OpCodes.Volatile);
-                               
-                               ig.Emit (OpCodes.Ldsfld, FieldInfo);
+
+                               ig.Emit (OpCodes.Ldsfld, GetConstructedFieldInfo ());
                        } else {
                                if (!prepared)
                                        EmitInstance (ec, false);
 
                                IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
                                if (ff != null) {
-                                       ig.Emit (OpCodes.Ldflda, FieldInfo);
+                                       ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
                                        ig.Emit (OpCodes.Ldflda, ff.Element);
                                } else {
                                        if (is_volatile)
                                                ig.Emit (OpCodes.Volatile);
 
-                                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+                                       ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ());
                                }
                        }
 
@@ -4741,10 +4993,7 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       //
-                       // String concatenation creates a new string instance 
-                       //
-                       prepared = prepare_for_load && !(source is StringConcat);
+                       prepared = prepare_for_load;
                        EmitInstance (ec, prepared);
 
                        source.Emit (ec);                       
@@ -4765,13 +5014,14 @@ namespace Mono.CSharp {
                        }
 
                        if (is_static)
-                               ig.Emit (OpCodes.Stsfld, FieldInfo);
-                       else 
-                               ig.Emit (OpCodes.Stfld, FieldInfo);
+                               ig.Emit (OpCodes.Stsfld, GetConstructedFieldInfo ());
+                       else
+                               ig.Emit (OpCodes.Stfld, GetConstructedFieldInfo ());
                        
                        if (temp != null) {
                                temp.Emit (ec);
                                temp.Release (ec);
+                               temp = null;
                        }
                }
 
@@ -4780,6 +5030,15 @@ namespace Mono.CSharp {
                        Emit (ec, false);
                }
 
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       FieldBase f = TypeManager.GetField (FieldInfo);
+                       bool is_volatile = f != null && (f.ModFlags & Modifiers.VOLATILE) != 0;
+
+                       if (is_volatile || is_marshal_by_ref ())
+                               base.EmitSideEffect (ec);
+               }
+
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ILGenerator ig = ec.ig;
@@ -4825,13 +5084,30 @@ namespace Mono.CSharp {
 
 
                        if (FieldInfo.IsStatic){
-                               ig.Emit (OpCodes.Ldsflda, FieldInfo);
+                               ig.Emit (OpCodes.Ldsflda, GetConstructedFieldInfo ());
                        } else {
                                if (!prepared)
                                        EmitInstance (ec, false);
-                               ig.Emit (OpCodes.Ldflda, FieldInfo);
+                               ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
                        }
                }
+
+               FieldInfo GetConstructedFieldInfo ()
+               {
+                       if (constructed_generic_type == null)
+                               return FieldInfo;
+#if GMCS_SOURCE
+                       return TypeBuilder.GetField (constructed_generic_type, FieldInfo);
+#else
+                       throw new NotSupportedException ();
+#endif                 
+               }
+               
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       FieldInfo = storey.MutateField (FieldInfo);
+                       base.MutateHoistedGenericType (storey);
+               }               
        }
 
        
@@ -4884,18 +5160,30 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
+                       ArrayList args;
                        if (IsSingleDimensionalArrayLength ()) {
-                               ArrayList args = new ArrayList (1);
+                               args = new ArrayList (1);
                                args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
                                return CreateExpressionFactoryCall ("ArrayLength", args);
                        }
 
-                       // TODO: it's waiting for PropertyExpr refactoring
-                       //ArrayList args = new ArrayList (2);
-                       //args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
-                       //args.Add (getter expression);
-                       //return CreateExpressionFactoryCall ("Property", args);
-                       return base.CreateExpressionTree (ec);
+                       if (is_base) {
+                               Error_BaseAccessInExpressionTree (loc);
+                               return null;
+                       }
+
+                       args = new ArrayList (2);
+                       if (InstanceExpression == null)
+                               args.Add (new Argument (new NullLiteral (loc)));
+                       else
+                               args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOfMethodInfo (getter, loc)));
+                       return CreateExpressionFactoryCall ("Property", args);
+               }
+
+               public Expression CreateSetterTypeOfExpression ()
+               {
+                       return new TypeOfMethodInfo (setter, loc);
                }
 
                public override Type DeclaringType {
@@ -4971,6 +5259,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (InstanceExpression != null)
+                               InstanceExpression.MutateHoistedGenericType (storey);
+
+                       type = storey.MutateType (type);
+                       getter = storey.MutateGenericMethod (getter);
+               }
+
                bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
                {
                        if (is_static) {
@@ -5011,7 +5308,7 @@ namespace Mono.CSharp {
                                Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
                                return;
                        }
-
+                       
                        StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
                        sig.Append ('.');
                        ParameterData iparams = TypeManager.GetParameterData (mi);
@@ -5035,18 +5332,12 @@ namespace Mono.CSharp {
 
                bool IsSingleDimensionalArrayLength ()
                {
-                       if (getter == TypeManager.system_int_array_get_length ||
-                               getter == TypeManager.int_array_get_length) {
-                               Type iet = InstanceExpression.Type;
-
-                               //
-                               // System.Array.Length can be called, but the Type does not
-                               // support invoking GetArrayRank, so test for that case first
-                               //
-                               return iet != TypeManager.array_type && (iet.GetArrayRank () == 1);
-                       }
+                       if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length")
+                               return false;
 
-                       return false;
+                       string t_name = InstanceExpression.Type.Name;
+                       int t_name_len = t_name.Length;
+                       return t_name_len > 2 && t_name [t_name_len - 2] == '[';
                }
 
                override public Expression DoResolve (EmitContext ec)
@@ -5217,14 +5508,9 @@ namespace Mono.CSharp {
                        Expression my_source = source;
 
                        if (prepare_for_load) {
-                               if (source is StringConcat)
-                                       EmitInstance (ec, false);
-                               else
-                                       prepared = true;                                        
-
+                               prepared = true;
                                source.Emit (ec);
                                
-                               prepared = true;
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
                                        if (!is_static) {
@@ -5341,7 +5627,6 @@ namespace Mono.CSharp {
                        return base.ResolveMemberAccess (ec, left, loc, original);
                }
 
-
                bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
                {
                        if (is_static) {
@@ -5369,7 +5654,7 @@ namespace Mono.CSharp {
                        //
                        if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
                            InstanceExpression.Type != ec.ContainerType &&
-                           ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
+                           TypeManager.IsSubclassOf (ec.ContainerType, InstanceExpression.Type)) {
                                Report.SymbolRelatedToPreviousError (EventInfo);
                                ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
                                return false;
@@ -5385,9 +5670,16 @@ namespace Mono.CSharp {
                                IsAccessorAccessible (invocation_type, remove_accessor, out dummy);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       return DoResolve (ec);
+                       // contexts where an LValue is valid have already devolved to FieldExprs
+                       Error_CannotAssign ();
+                       return null;
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -5402,14 +5694,25 @@ namespace Mono.CSharp {
 
                        if (!InstanceResolve (ec, must_do_cs1540_check))
                                return null;
+
+                       if (!ec.IsInCompoundAssignment) {
+                               Error_CannotAssign ();
+                               return null;
+                       }
                        
                        return this;
                }               
 
                public override void Emit (EmitContext ec)
                {
-                       Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
-                                     "(except on the defining type)", GetSignatureForError ());
+                       Error_CannotAssign ();
+               }
+
+               public void Error_CannotAssign ()
+               {
+                       Report.Error (70, loc,
+                               "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
+                               GetSignatureForError (), TypeManager.CSharpName (EventInfo.DeclaringType));
                }
 
                public override string GetSignatureForError ()
@@ -5417,96 +5720,76 @@ namespace Mono.CSharp {
                        return TypeManager.CSharpSignature (EventInfo);
                }
 
-               public void EmitAddOrRemove (EmitContext ec, Expression source)
+               public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
                {
-                       BinaryDelegate source_del = source as BinaryDelegate;
-                       if (source_del == null) {
-                               Emit (ec);
-                               return;
-                       }
-                       Expression handler = source_del.Right;
-                       
-                       Argument arg = new Argument (handler, Argument.AType.Expression);
-                       ArrayList args = new ArrayList ();
-                               
-                       args.Add (arg);
-                       
-                       if (source_del.IsAddition)
-                               Invocation.EmitCall (
-                                       ec, IsBase, InstanceExpression, add_accessor, args, loc);
-                       else
-                               Invocation.EmitCall (
-                                       ec, IsBase, InstanceExpression, remove_accessor, args, loc);
+                       ArrayList args = new ArrayList (1);
+                       args.Add (new Argument (source, Argument.AType.Expression));
+                       Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc);
                }
        }
 
-       public class TemporaryVariable : Expression, IMemoryLocation
+       public class TemporaryVariable : VariableReference
        {
                LocalInfo li;
-               Variable var;
-               
+
                public TemporaryVariable (Type type, Location loc)
                {
                        this.type = type;
                        this.loc = loc;
-                       eclass = ExprClass.Value;
+                       eclass = ExprClass.Variable;
                }
-               
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        if (li != null)
                                return this;
-                       
+
                        TypeExpr te = new TypeExpression (type, loc);
                        li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
                        if (!li.Resolve (ec))
                                return null;
 
-                       if (ec.MustCaptureVariable (li)) {
-                               ScopeInfo scope = li.Block.CreateScopeInfo ();
-                               var = scope.AddLocal (li);
-                               type = var.Type;
+                       if (ec.MustCaptureVariable (li) && !ec.IsInProbingMode) {
+                               AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
+                               storey.CaptureLocalVariable (ec, li);
                        }
-                       
-                       return this;
-               }
 
-               public Variable Variable {
-                       get { return var != null ? var : li.Variable; }
+                       return this;
                }
                
                public override void Emit (EmitContext ec)
                {
-                       Variable.EmitInstance (ec);
-                       Variable.Emit (ec);
+                       Emit (ec, false);
                }
-               
-               public void EmitLoadAddress (EmitContext ec)
+
+               public void EmitAssign (EmitContext ec, Expression source)
                {
-                       Variable.EmitInstance (ec);
-                       Variable.EmitAddressOf (ec);
+                       EmitAssign (ec, source, false, false);
                }
-               
-               public void Store (EmitContext ec, Expression right_side)
-               {
-                       Variable.EmitInstance (ec);
-                       right_side.Emit (ec);
-                       Variable.EmitAssign (ec);
+
+               public override HoistedVariable HoistedVariable {
+                       get { return li.HoistedVariableReference; }
                }
-               
-               public void EmitThis (EmitContext ec)
-               {
-                       Variable.EmitInstance (ec);
+
+               public override bool IsFixed {
+                       get { return true; }
                }
-               
-               public void EmitStore (EmitContext ec)
-               {
-                       Variable.EmitAssign (ec);
+
+               public override bool IsRef {
+                       get { return false; }
                }
-               
-               public void AddressOf (EmitContext ec, AddressOp mode)
-               {
-                       EmitLoadAddress (ec);
+
+               protected override ILocalVariable Variable {
+                       get { return li; }
+               }
+
+               public override VariableInfo VariableInfo {
+                       get { throw new NotImplementedException (); }
                }
        }
 
@@ -5530,7 +5813,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               public bool InferType (EmitContext ec, Expression right_side)
                {
                        if (type != null)
                                throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
@@ -5539,11 +5822,11 @@ namespace Mono.CSharp {
                        if (type == TypeManager.null_type || type == TypeManager.void_type || type == TypeManager.anonymous_method_type) {
                                Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
                                              right_side.GetSignatureForError ());
-                               return null;
+                               return false;
                        }
 
                        eclass = ExprClass.Variable;
-                       return this;
+                       return true;
                }
 
                protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec)