Fix compound event assigments with dynamic side effect
[mono.git] / mcs / mcs / ecore.cs
index 022ecf6eb326c1c8dba33f60e731b169df2ff04a..abc7fc252b9f0cfb31606b244665c21ce3d2445d 100644 (file)
@@ -195,15 +195,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               //
-               // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
-               // same name exists or as a keyword when no type was found
-               // 
-               public virtual TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
-               {
-                       return ResolveAsTypeTerminal (rc, silent);
-               }               
-               
                //
                // This is used to resolve the expression as a type, a null
                // value will be returned if the expression is not a type
@@ -329,11 +320,6 @@ namespace Mono.CSharp {
                                type.GetSignatureForError (), target.GetSignatureForError ());
                }
 
-               public virtual void Error_VariableIsUsedBeforeItIsDeclared (Report Report, string name)
-               {
-                       Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", name);
-               }
-
                public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity)
                {
                        // Better message for possible generic expressions
@@ -380,6 +366,11 @@ namespace Mono.CSharp {
                        ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
                }
 
+               protected void Error_VoidPointerOperation (ResolveContext rc)
+               {
+                       rc.Report.Error (242, loc, "The operation in question is undefined on void pointers");
+               }
+
                public ResolveFlags ExprClassToResolveFlags {
                        get {
                                switch (eclass) {
@@ -440,7 +431,7 @@ namespace Mono.CSharp {
                                        throw;
 
                                ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
-                               return EmptyExpression.Null;
+                               return EmptyExpression.Null;    // TODO: Add location
                        }
                }
 
@@ -497,7 +488,8 @@ namespace Mono.CSharp {
 
                public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
                {
-                       Attribute.Error_AttributeArgumentNotValid (rc, loc);
+                       rc.Compiler.Report.Error (182, loc,
+                               "An attribute argument must be a constant expression, typeof expression or array creation expression");
                }
 
                /// <summary>
@@ -579,11 +571,20 @@ namespace Mono.CSharp {
                        return r.ResolveMember<MethodSpec> (rc, ref args);
                }
 
+               [Flags]
+               public enum MemberLookupRestrictions
+               {
+                       None = 0,
+                       InvocableOnly = 1,
+                       ExactArity = 1 << 2,
+                       ReadAccess = 1 << 3
+               }
+
                //
                // Lookup type `queried_type' for code in class `container_type' with a qualifier of
                // `qualifier_type' or null to lookup members in the current class.
                //
-               public static Expression MemberLookup (ResolveContext rc, TypeSpec currentType, TypeSpec queried_type, string name, int arity, bool invocableOnly, Location loc)
+               public static Expression MemberLookup (ResolveContext rc, TypeSpec currentType, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
                {
                        var members = MemberCache.FindMembers (queried_type, name, false);
                        if (members == null)
@@ -600,13 +601,13 @@ namespace Mono.CSharp {
                                        if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
                                                continue;
 
-                                       if (arity > 0 && member.Arity != arity)
+                                       if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
                                                continue;
 
                                        if (rc != null && !member.IsAccessible (currentType))
                                                continue;
 
-                                       if (invocableOnly) {
+                                       if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
                                                if (member is MethodSpec)
                                                        return new MethodGroupExpr (members, queried_type, loc);
 
@@ -683,7 +684,7 @@ namespace Mono.CSharp {
                        Arguments arguments = new Arguments (1);
                        arguments.Add (new Argument (e));
 
-                       var res = new OverloadResolver (methods, OverloadResolver.Restrictions.NoBaseMembers, loc);
+                       var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
                        var oper = res.ResolveOperator (ec, ref arguments);
 
                        if (oper == null)
@@ -813,12 +814,7 @@ namespace Mono.CSharp {
                        else
                                return 0;
                }
-
-               protected void Error_CannotCallAbstractBase (ResolveContext ec, string name)
-               {
-                       ec.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
-               }
-               
+       
                protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec)
                {
                        ec.Report.SymbolRelatedToPreviousError (type);
@@ -898,7 +894,7 @@ namespace Mono.CSharp {
                // compile the same code using different type values for the same
                // arguments to find the correct overload
                //
-               public Expression Clone (CloneContext clonectx)
+               public virtual Expression Clone (CloneContext clonectx)
                {
                        Expression cloned = (Expression) MemberwiseClone ();
                        CloneTo (clonectx, cloned);
@@ -1877,6 +1873,16 @@ namespace Mono.CSharp {
                        this.loc = orig_expr.Location;
                }
 
+               #region Properties
+
+               public Expression OriginalExpression {
+                       get {
+                               return orig_expr;
+                       }
+               }
+
+               #endregion
+
                //
                // Creates fully resolved expression switcher
                //
@@ -2115,7 +2121,7 @@ namespace Mono.CSharp {
                        return Name;
                }
 
-               public abstract Expression LookupNameExpression (ResolveContext rc, bool readMode, bool invocableOnly);
+               public abstract Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restriction);
        }
        
        /// <summary>
@@ -2228,10 +2234,10 @@ namespace Mono.CSharp {
                        }
 
                        if (Arity == 0 && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3) {
-                               if (!PredefinedAttributes.Get.Dynamic.IsDefined) {
+                               if (!ec.Compiler.PredefinedAttributes.Dynamic.IsDefined) {
                                        ec.Compiler.Report.Error (1980, Location,
                                                "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?",
-                                               PredefinedAttributes.Get.Dynamic.GetSignatureForError ());
+                                               ec.Compiler.PredefinedAttributes.Dynamic.GetSignatureForError ());
                                }
 
                                return new DynamicTypeExpr (loc);
@@ -2247,50 +2253,38 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public override Expression LookupNameExpression (ResolveContext rc, bool readMode, bool invocableOnly)
+               public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
                {
                        int lookup_arity = Arity;
                        bool errorMode = false;
                        Expression e;
                        Block current_block = rc.CurrentBlock;
+                       INamedBlockVariable variable = null;
+                       bool variable_found = false;
 
                        while (true) {
                                //
                                // Stage 1: binding to local variables or parameters
                                //
+                               // LAMESPEC: It should take invocableOnly into account but that would break csc compatibility
+                               //
                                if (current_block != null && lookup_arity == 0) {
-                                       LocalInfo vi = current_block.GetLocalInfo (Name);
-                                       if (vi != null) {
-                                               // TODO: pass vi in to speed things up
-                                               e = new LocalVariableReference (rc.CurrentBlock, Name, loc);
-                                       } else {
-                                               e = current_block.Toplevel.GetParameterReference (Name, loc);
-                                       }
-
-                                       if (e != null) {
-                                               if (Arity > 0)
-                                                       Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
-
-                                               return e;
-                                       }
-
-                                       if (!errorMode)
-                                               current_block.CheckInvariantMeaningInBlock (Name, this, loc);
+                                       if (current_block.ParametersBlock.TopBlock.GetLocalName (Name, current_block.Original, ref variable)) {
+                                               if (!variable.IsDeclared) {
+                                                       // We found local name in accessible block but it's not
+                                                       // initialized yet, maybe the user wanted to bind to something else
+                                                       errorMode = true;
+                                                       variable_found = true;
+                                               } else {
+                                                       e = variable.CreateReferenceExpression (rc, loc);
+                                                       if (e != null) {
+                                                               if (Arity > 0)
+                                                                       Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
 
-/*
-                                       //if (errorMode) {
-                                               IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
-                                               if (ikv != null) {
-                                                       LocalInfo li = ikv as LocalInfo;
-                                                       // Supress CS0219 warning
-                                                       if (li != null)
-                                                               li.Used = true;
-
-                                                       Error_VariableIsUsedBeforeItIsDeclared (rc.Report, Name);
-                                                       return null;
+                                                               return e;
+                                                       }
                                                }
-                                       //}
-*/ 
+                                       }
                                }
 
                                //
@@ -2299,18 +2293,31 @@ namespace Mono.CSharp {
                                TypeSpec member_type = rc.CurrentType;
                                TypeSpec current_type = member_type;
                                for (; member_type != null; member_type = member_type.DeclaringType) {
-                                       var me = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, invocableOnly, loc) as MemberExpr;
+                                       var me = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, restrictions, loc) as MemberExpr;
                                        if (me == null)
                                                continue;
 
                                        if (errorMode) {
-                                               if (me is MethodGroupExpr) {
+                                               if (variable != null) {
+                                                       if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) {
+                                                               rc.Report.Error (844, loc,
+                                                                       "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the member `{1}'",
+                                                                       Name, me.GetSignatureForError ());
+                                                       } else {
+                                                               break;
+                                                       }
+                                               } else if (me is MethodGroupExpr) {
                                                        // Leave it to overload resolution to report correct error
                                                } else {
                                                        // TODO: rc.Report.SymbolRelatedToPreviousError ()
                                                        ErrorIsInaccesible (rc, me.GetSignatureForError (), loc);
                                                }
                                        } else {
+                                               if (variable != null && (restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+                                                       rc.Report.SymbolRelatedToPreviousError (variable.Location, Name);
+                                                       rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name);
+                                               }
+
                                                //
                                                // MemberLookup does not check accessors availability, this is actually needed for properties only
                                                //
@@ -2318,7 +2325,7 @@ namespace Mono.CSharp {
                                                if (pe != null) {
 
                                                        // Break as there is no other overload available anyway
-                                                       if (readMode) {
+                                                       if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) {
                                                                if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (current_type))
                                                                        break;
 
@@ -2347,14 +2354,19 @@ namespace Mono.CSharp {
                                //
                                // Stage 3: Lookup nested types, namespaces and type parameters in the context
                                //
-                               if (!invocableOnly) {
+                               if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
                                        e = ResolveAsTypeStep (rc, lookup_arity == 0 || !errorMode);
                                        if (e != null)
                                                return e;
                                }
 
                                if (errorMode) {
-                                       rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
+                                       if (variable_found) {
+                                               rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
+                                       } else {
+                                               rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
+                                       }
+
                                        return null;
                                }
 
@@ -2365,22 +2377,28 @@ namespace Mono.CSharp {
                                }
 
                                lookup_arity = 0;
-                               invocableOnly = false;
+                               restrictions &= ~MemberLookupRestrictions.InvocableOnly;
                                errorMode = true;
                        }
                }
-
+               
                Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
                {
-                       Expression e = LookupNameExpression (ec, right_side == null, false);
+                       Expression e = LookupNameExpression (ec, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
 
                        if (e == null)
                                return null;
 
-                       if (right_side != null)
+                       if (right_side != null) {
+                               if (e is TypeExpr) {
+                                   e.Error_UnexpectedKind (ec, ResolveFlags.VariableOrValue, loc);
+                                   return null;
+                               }
+
                                e = e.ResolveLValue (ec, right_side);
-                       else
+                       } else {
                                e = e.Resolve (ec);
+                       }
 
                        //if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
                        return e;
@@ -2543,17 +2561,43 @@ namespace Mono.CSharp {
                        // Overload resulution works on virtual or non-virtual members only (no overrides). That
                        // means for base.member access we have to find the closest match after we found best candidate
                        //
-                       if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC)) != Modifiers.STATIC && method.DeclaringType != InstanceExpression.Type) {
-                               var base_override = MemberCache.FindMember (InstanceExpression.Type, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec;
-                               if (base_override != null && base_override.DeclaringType != method.DeclaringType) {
-                                       if (base_override.IsGeneric)
-                                               base_override = base_override.MakeGenericMethod (method.TypeArguments);
+                       if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC)) != Modifiers.STATIC) {
+                               //
+                               // The method could already be what we are looking for
+                               //
+                               TypeSpec[] targs = null;
+                               if (method.DeclaringType != InstanceExpression.Type) {
+                                       var base_override = MemberCache.FindMember (InstanceExpression.Type, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec;
+                                       if (base_override != null && base_override.DeclaringType != method.DeclaringType) {
+                                               if (base_override.IsGeneric)
+                                                       targs = method.TypeArguments;
+
+                                               method = base_override;
+                                       }
+                               }
+
+                               // TODO: For now we do it for any hoisted call even if it's needed for
+                               // hoisted stories only but that requires a new expression wrapper
+                               if (rc.CurrentAnonymousMethod != null) {
+                                       if (targs == null && method.IsGeneric) {
+                                               targs = method.TypeArguments;
+                                               method = method.GetGenericMethodDefinition ();
+                                       }
 
-                                       if (rc.CurrentAnonymousMethod != null)
-                                               throw new NotImplementedException ("base call hoisting");
+                                       if (method.Parameters.HasArglist)
+                                               throw new NotImplementedException ("__arglist base call proxy");
 
-                                       return base_override;
+                                       method = rc.CurrentMemberDefinition.Parent.PartialContainer.CreateHoistedBaseCallProxy (rc, method);
+
+                                       // Ideally this should apply to any proxy rewrite but in the case of unary mutators on
+                                       // get/set member expressions second call would fail to proxy because left expression
+                                       // would be of 'this' and not 'base'
+                                       if (rc.CurrentType.IsStruct)
+                                               InstanceExpression = rc.GetThis (loc);
                                }
+
+                               if (targs != null)
+                                       method = method.MakeGenericMethod (targs);
                        }
 
                        //
@@ -2574,7 +2618,7 @@ namespace Mono.CSharp {
                        if ((member.Modifiers & Modifiers.AccessibilityMask) == Modifiers.PROTECTED && !(InstanceExpression is This)) {
                                var ct = rc.CurrentType;
                                var expr_type = InstanceExpression.Type;
-                               if (ct != expr_type && !TypeManager.IsSubclassOf (expr_type, ct)) {
+                               if (ct != expr_type) {
                                        expr_type = expr_type.GetDefinition ();
                                        if (ct != expr_type && !IsSameOrBaseQualifier (ct, expr_type)) {
                                                rc.Report.SymbolRelatedToPreviousError (member);
@@ -2621,6 +2665,11 @@ namespace Mono.CSharp {
                                member.MemberDefinition.SetIsUsed ();
                }
 
+               protected virtual void Error_CannotCallAbstractBase (ResolveContext rc, string name)
+               {
+                       rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
+               }
+
                //
                // Implements identicial simple name and type-name
                //
@@ -2721,18 +2770,24 @@ namespace Mono.CSharp {
 
                protected void EmitInstance (EmitContext ec, bool prepare_for_load)
                {
-                       if (TypeManager.IsValueType (InstanceExpression.Type)) {
+                       TypeSpec instance_type = InstanceExpression.Type;
+                       if (TypeManager.IsValueType (instance_type)) {
                                if (InstanceExpression is IMemoryLocation) {
                                        ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
                                } else {
-                                       LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
+                                       LocalTemporary t = new LocalTemporary (instance_type);
                                        InstanceExpression.Emit (ec);
                                        t.Store (ec);
                                        t.AddressOf (ec, AddressOp.Store);
                                }
-                       } else
+                       } else {
                                InstanceExpression.Emit (ec);
 
+                               // Only to make verifier happy
+                               if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeManager.IsReferenceType (instance_type))
+                                       ec.Emit (OpCodes.Box, instance_type);
+                       }
+
                        if (prepare_for_load)
                                ec.Emit (OpCodes.Dup);
                }
@@ -2740,26 +2795,46 @@ namespace Mono.CSharp {
                public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta);
        }
 
-       /// 
-       /// Represents group of extension method candidates
-       /// 
-       public class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler
+       // 
+       // Represents a group of extension method candidates for whole namespace
+       // 
+       class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler
        {
-               readonly NamespaceEntry namespace_entry;
-               public Expression ExtensionExpression;
+               NamespaceEntry namespace_entry;
+               public readonly Expression ExtensionExpression;
 
-               public ExtensionMethodGroupExpr (List<MethodSpec> list, NamespaceEntry n, TypeSpec extensionType, Location l)
-                       : base (list.Cast<MemberSpec>().ToList (), extensionType, l)
+               public ExtensionMethodGroupExpr (IList<MethodSpec> list, NamespaceEntry n, Expression extensionExpr, Location l)
+                       : base (list.Cast<MemberSpec>().ToList (), extensionExpr.Type, l)
                {
                        this.namespace_entry = n;
+                       this.ExtensionExpression = extensionExpr;
                }
 
                public override bool IsStatic {
                        get { return true; }
                }
 
-               public bool IsTopLevel {
-                       get { return namespace_entry == null; }
+               public override IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+               {
+                       if (namespace_entry == null)
+                               return null;
+
+                       //
+                       // For extension methodgroup we are not looking for base members but parent
+                       // namespace extension methods
+                       //
+                       int arity = type_arguments == null ? 0 : type_arguments.Count;
+                       var found = namespace_entry.LookupExtensionMethod (DeclaringType, Name, arity, ref namespace_entry);
+                       if (found == null)
+                               return null;
+
+                       return found.Cast<MemberSpec> ().ToList ();
+               }
+
+               public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
+               {
+                       // We are already here
+                       return null;
                }
 
                public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, OverloadResolver.IErrorHandler ehandler, OverloadResolver.Restrictions restr)
@@ -2767,40 +2842,22 @@ namespace Mono.CSharp {
                        if (arguments == null)
                                arguments = new Arguments (1);
 
-                       arguments.Insert (0, new Argument (ExtensionExpression));
-                       MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, ehandler ?? this, namespace_entry, loc);
+                       arguments.Insert (0, new Argument (ExtensionExpression, Argument.AType.ExtensionType));
+                       var res = base.OverloadResolve (ec, ref arguments, ehandler ?? this, restr);
 
                        // Store resolved argument and restore original arguments
-                       if (mg == null) {
-                               arguments.RemoveAt (0); // Clean-up modified arguments for error reporting
-                       } else {
-                               var me = ExtensionExpression as MemberExpr;
-                               if (me != null)
-                                       me.ResolveInstanceExpression (ec);
-                       }
-
-                       return mg;
-               }
-
-               MethodGroupExpr ResolveOverloadExtensions (ResolveContext ec, ref Arguments arguments, OverloadResolver.IErrorHandler ehandler, NamespaceEntry ns, Location loc)
-               {
-                       // Use normal resolve rules
-                       MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ehandler, ns != null ? OverloadResolver.Restrictions.ProbingOnly : OverloadResolver.Restrictions.None);
-                       if (mg != null)
-                               return mg;
-
-                       if (ns == null)
+                       if (res == null) {
+                               // Clean-up modified arguments for error reporting
+                               arguments.RemoveAt (0);
                                return null;
+                       }
 
-                       // Search continues
-                       int arity = type_arguments == null ? 0 : type_arguments.Count;
-                       ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, arity, loc);
-                       if (e == null)
-                               return base.OverloadResolve (ec, ref arguments, ehandler, OverloadResolver.Restrictions.None);
+                       var me = ExtensionExpression as MemberExpr;
+                       if (me != null)
+                               me.ResolveInstanceExpression (ec);
 
-                       e.ExtensionExpression = ExtensionExpression;
-                       e.SetTypeArguments (ec, type_arguments);                        
-                       return e.ResolveOverloadExtensions (ec, ref arguments, ehandler, e.namespace_entry, loc);
+                       InstanceExpression = null;
+                       return this;
                }
 
                #region IErrorHandler Members
@@ -2932,13 +2989,6 @@ namespace Mono.CSharp {
                        return Methods.First ().GetSignatureForError ();
                }
 
-               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
-               {
-                       simple_name = original;
-
-                       return base.ResolveMemberAccess (ec, left, original);
-               }
-
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        if (best_candidate == null) {
@@ -2987,7 +3037,7 @@ namespace Mono.CSharp {
                        //
                        // LAMESPEC: No details about which expressions are not allowed
                        //
-                       return !(expr is BaseThis);
+                       return !(expr is TypeExpr) && !(expr is BaseThis);
                }
 
                /// <summary>
@@ -3025,6 +3075,10 @@ namespace Mono.CSharp {
                        if (best_candidate == null)
                                return r.BestCandidateIsDynamic ? this : null;
 
+                       // Overload resolver had to create a new method group, all checks bellow have already been executed
+                       if (r.BestCandidateNewMethodGroup != null)
+                               return r.BestCandidateNewMethodGroup;
+
                        if (best_candidate.Kind == MemberKind.Method) {
                                if (InstanceExpression != null) {
                                        if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) {
@@ -3041,17 +3095,18 @@ namespace Mono.CSharp {
                                ResolveInstanceExpression (ec);
                                if (InstanceExpression != null)
                                        CheckProtectedMemberAccess (ec, best_candidate);
-
-                               if (best_candidate.IsGeneric) {
-                                       ConstraintChecker.CheckAll (ec.MemberContext, best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
-                                               best_candidate.Constraints, loc);
-                               }
                        }
 
                        best_candidate = CandidateToBaseOverride (ec, best_candidate);
                        return this;
                }
 
+               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
+               {
+                       simple_name = original;
+                       return base.ResolveMemberAccess (ec, left, original);
+               }
+
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
                        type_arguments = ta;
@@ -3059,12 +3114,15 @@ namespace Mono.CSharp {
 
                #region IBaseMembersProvider Members
 
-               IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType)
+               public virtual IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
                {
                        return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
                }
 
-               MethodGroupExpr OverloadResolver.IBaseMembersProvider.LookupExtensionMethod (ResolveContext rc, int arity)
+               //
+               // Extension methods lookup after ordinary methods candidates failed to apply
+               //
+               public virtual MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
                {
                        if (InstanceExpression == null)
                                return null;
@@ -3073,12 +3131,14 @@ namespace Mono.CSharp {
                        if (!IsExtensionMethodArgument (InstanceExpression))
                                return null;
 
-                       var emg = rc.LookupExtensionMethod (InstanceExpression.Type, Methods [0].Name, arity, loc);
-                       if (emg != null) {
-                               emg.ExtensionExpression = InstanceExpression;
-                               emg.SetTypeArguments (rc, type_arguments);
-                       }
+                       int arity = type_arguments == null ? 0 : type_arguments.Count;
+                       NamespaceEntry methods_scope = null;
+                       var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope);
+                       if (methods == null)
+                               return null;
 
+                       var emg = new ExtensionMethodGroupExpr (methods, methods_scope, InstanceExpression, loc);
+                       emg.SetTypeArguments (rc, type_arguments);
                        return emg;
                }
 
@@ -3093,14 +3153,15 @@ namespace Mono.CSharp {
                        None = 0,
                        DelegateInvoke = 1,
                        ProbingOnly     = 1 << 1,
-                       Covariant = 1 << 2,
-                       NoBaseMembers = 1 << 3
+                       CovariantDelegate = 1 << 2,
+                       NoBaseMembers = 1 << 3,
+                       BaseMembersIncluded = 1 << 4
                }
 
                public interface IBaseMembersProvider
                {
                        IList<MemberSpec> GetBaseMembers (TypeSpec baseType);
-                       MethodGroupExpr LookupExtensionMethod (ResolveContext rc, int arity);
+                       MethodGroupExpr LookupExtensionMethod (ResolveContext rc);
                }
 
                public interface IErrorHandler
@@ -3120,7 +3181,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       public MethodGroupExpr LookupExtensionMethod (ResolveContext rc, int arity)
+                       public MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
                        {
                                return null;
                        }
@@ -3144,6 +3205,7 @@ namespace Mono.CSharp {
                IBaseMembersProvider base_provider;
                IErrorHandler custom_errors;
                Restrictions restrictions;
+               MethodGroupExpr best_candidate_extension_group;
 
                SessionReportPrinter lambda_conv_msgs;
                ReportPrinter prev_recorder;
@@ -3182,6 +3244,15 @@ namespace Mono.CSharp {
 
                public bool BestCandidateIsDynamic { get; set; }
 
+               //
+               // Best candidate was found in newly created MethodGroupExpr, used by extension methods
+               //
+               public MethodGroupExpr BestCandidateNewMethodGroup {
+                       get {
+                               return best_candidate_extension_group;
+                       }
+               }
+
                public IErrorHandler CustomErrors {
                        get {
                                return custom_errors;
@@ -3331,12 +3402,13 @@ namespace Mono.CSharp {
                        bool better_at_least_one = false;
                        bool same = true;
                        int args_count = args == null ? 0 : args.Count;
-                       for (int j = 0, c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) {
+                       int j = 0;
+                       for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) {
                                Argument a = args[j];
 
-                               // Provided default argument value is never better
-                               if (a.IsDefaultArgument && candidate_params == best_params)
-                                       return false;
+                               // Default arguments are ignored for better decision
+                               if (a.IsDefaultArgument)
+                                       break;
 
                                TypeSpec ct = candidate_pd.Types[c_idx];
                                TypeSpec bt = best_pd.Types[b_idx];
@@ -3351,7 +3423,7 @@ namespace Mono.CSharp {
                                        --b_idx;
                                }
 
-                               if (TypeManager.IsEqual (ct, bt))
+                               if (ct == bt)
                                        continue;
 
                                same = false;
@@ -3384,15 +3456,34 @@ namespace Mono.CSharp {
                                return false;
 
                        //
-                       // The two methods have equal parameter types.  Now apply tie-breaking rules
+                       // The two methods have equal non-optional parameter types, apply tie-breaking rules
                        //
-                       if (best.IsGeneric) {
-                               if (!candidate.IsGeneric)
-                                       return true;
-                       } else if (candidate.IsGeneric) {
-                               return false;
+
+                       //
+                       // This handles the following cases:
+                       //
+                       //  Foo (int i) is better than Foo (int i, long l = 0)
+                       //  Foo (params int[] args) is better than Foo (int i = 0, params int[] args)
+                       //
+                       // Prefer non-optional version
+                       //
+                       // LAMESPEC: Specification claims this should be done at last but the opposite is true
+                       if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) {
+                               if (candidate_pd.Count >= best_pd.Count)
+                                       return false;
+
+                               if (j < candidate_pd.Count && candidate_pd.FixedParameters[j].HasDefaultValue)
+                                       return false;
+
+                               return true;
                        }
 
+                       //
+                       // One is a non-generic method and second is a generic method, then non-generic is better
+                       //
+                       if (best.IsGeneric != candidate.IsGeneric)
+                               return best.IsGeneric;
+
                        //
                        // This handles the following cases:
                        //
@@ -3401,10 +3492,10 @@ namespace Mono.CSharp {
                        //     Concat (string s1, params string [] srest)
                        //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
                        //
-                       if (!candidate_params && best_params)
-                               return true;
-                       if (candidate_params && !best_params)
-                               return false;
+                       // Prefer non-expanded version
+                       //
+                       if (candidate_params != best_params)
+                               return best_params;
 
                        int candidate_param_count = candidate_pd.Count;
                        int best_param_count = best_pd.Count;
@@ -3421,7 +3512,7 @@ namespace Mono.CSharp {
                        var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters;
 
                        bool specific_at_least_once = false;
-                       for (int j = 0; j < candidate_param_count; ++j) {
+                       for (j = 0; j < candidate_param_count; ++j) {
                                var ct = candidate_def_pd.Types[j];
                                var bt = best_def_pd.Types[j];
                                if (ct == bt)
@@ -3460,6 +3551,7 @@ namespace Mono.CSharp {
                        AParametersCollection pd = ((IParametersMember) candidate).Parameters;
                        int param_count = pd.Count;
                        int optional_count = 0;
+                       int score;
 
                        if (arg_count != param_count) {
                                for (int i = 0; i < pd.Count; ++i) {
@@ -3489,22 +3581,19 @@ namespace Mono.CSharp {
                                                return int.MaxValue - 10000 + args_gap;
                                }
 
-                               // Initialize expanded form of a method with 1 params parameter
-                               params_expanded_form = param_count == 1 && pd.HasParams;
-
                                // Resize to fit optional arguments
                                if (optional_count != 0) {
-                                       Arguments resized;
                                        if (arguments == null) {
-                                               resized = new Arguments (optional_count);
+                                               arguments = new Arguments (optional_count);
                                        } else {
-                                               resized = new Arguments (param_count);
+                                               // Have to create a new container, so the next run can do same
+                                               var resized = new Arguments (param_count);
                                                resized.AddRange (arguments);
+                                               arguments = resized;
                                        }
 
                                        for (int i = arg_count; i < param_count; ++i)
-                                               resized.Add (null);
-                                       arguments = resized;
+                                               arguments.Add (null);
                                }
                        }
 
@@ -3525,19 +3614,31 @@ namespace Mono.CSharp {
                                                        int index = pd.GetParameterIndexByName (na.Name);
 
                                                        // Named parameter not found or already reordered
-                                                       if (index <= i)
+                                                       if (index == i || index < 0)
                                                                break;
 
-                                                       // When using parameters which should not be available to the user
-                                                       if (index >= param_count)
-                                                               break;
+                                                       Argument temp;
+                                                       if (index >= param_count) {
+                                                               // When using parameters which should not be available to the user
+                                                               if ((pd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0)
+                                                                       break;
+
+                                                               arguments.Add (null);
+                                                               ++arg_count;
+                                                               temp = null;
+                                                       } else {
+                                                               temp = arguments[index];
+
+                                                               // The slot has been taken by positional argument
+                                                               if (temp != null && !(temp is NamedArgument))
+                                                                       break;
+                                                       }
 
                                                        if (!arg_moved) {
                                                                arguments.MarkReorderedArgument (na);
                                                                arg_moved = true;
                                                        }
 
-                                                       Argument temp = arguments[index];
                                                        arguments[index] = arguments[i];
                                                        arguments[i] = temp;
 
@@ -3557,6 +3658,9 @@ namespace Mono.CSharp {
                        //
                        var ms = candidate as MethodSpec;
                        if (ms != null && ms.IsGeneric) {
+                               // Setup constraint checker for probing only
+                               ConstraintChecker cc = new ConstraintChecker (null);
+
                                if (type_arguments != null) {
                                        var g_args_count = ms.Arity;
                                        if (g_args_count != type_arguments.Count)
@@ -3572,15 +3676,27 @@ namespace Mono.CSharp {
                                                prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs);
                                        }
 
-                                       int score = TypeManager.InferTypeArguments (ec, arguments, ref ms);
+                                       var ti = new TypeInference (arguments);
+                                       TypeSpec[] i_args = ti.InferMethodArguments (ec, ms);
                                        lambda_conv_msgs.EndSession ();
 
-                                       if (score != 0)
-                                               return score - 20000;
+                                       if (i_args == null)
+                                               return ti.InferenceScore - 20000;
 
-                                       candidate = ms;
-                                       pd = ms.Parameters;
+                                       if (i_args.Length != 0) {
+                                               candidate = ms = ms.MakeGenericMethod (i_args);
+                                               pd = ms.Parameters;
+                                       }
+
+                                       cc.IgnoreInferredDynamic = true;
                                }
+
+                               //
+                               // Type arguments constraints have to match for the method to be applicable
+                               //
+                               if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc))
+                                       return int.MaxValue - 25000;
+
                        } else {
                                if (type_arguments != null)
                                        return int.MaxValue - 15000;
@@ -3597,31 +3713,51 @@ namespace Mono.CSharp {
                                        if (!pd.FixedParameters[i].HasDefaultValue)
                                                throw new InternalErrorException ();
 
-                                       Expression e = pd.FixedParameters[i].DefaultValue as Constant;
-                                       if (e == null)
-                                               e = new DefaultValueExpression (new TypeExpression (pd.Types[i], loc), loc).Resolve (ec);
+                                       //
+                                       // Get the default value expression, we can use the same expression
+                                       // if the type matches
+                                       //
+                                       Expression e = pd.FixedParameters[i].DefaultValue;
+                                       if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) {
+                                               //
+                                               // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
+                                               //
+                                               if (e == EmptyExpression.MissingValue && pd.Types[i] == TypeManager.object_type) {
+                                                       e = new MemberAccess (new MemberAccess (new MemberAccess (
+                                                               new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
+                                               } else {
+                                                       e = new DefaultValueExpression (new TypeExpression (pd.Types[i], loc), loc);
+                                               }
+
+                                               e = e.Resolve (ec);
+                                       }
 
                                        arguments[i] = new Argument (e, Argument.AType.Default);
                                        continue;
                                }
 
                                if (p_mod != Parameter.Modifier.PARAMS) {
-                                       p_mod = pd.FixedParameters[i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+                                       p_mod = pd.FixedParameters[i].ModFlags;
                                        pt = pd.Types[i];
-                               } else {
+                               } else if (!params_expanded_form) {
                                        params_expanded_form = true;
+                                       pt = ((ElementTypeSpec) pt).Element;
+                                       i -= 2;
+                                       continue;
                                }
 
-                               Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
-                               int score = 1;
+                               score = 1;
                                if (!params_expanded_form)
-                                       score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
+                                       score = IsArgumentCompatible (ec, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
 
                                //
                                // It can be applicable in expanded form (when not doing exact match like for delegates)
                                //
-                               if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.Covariant) == 0) {
-                                       score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
+                               if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) {
+                                       if (!params_expanded_form)
+                                               pt = ((ElementTypeSpec) pt).Element;
+
+                                       score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt);
                                        if (score == 0)
                                                params_expanded_form = true;
                                }
@@ -3633,23 +3769,34 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (arg_count != param_count)
+                       //
+                       // When params parameter has notargument, will be provided later if the method is the best candidate
+                       //
+                       if (arg_count + 1 == pd.Count && (pd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0)
                                params_expanded_form = true;
 
                        return 0;
                }
 
-               int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
+               int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
                {
                        //
-                       // Types have to be identical when ref or out modifer is used 
+                       // Types have to be identical when ref or out modifer
+                       // is used and argument is not of dynamic type
                        //
-                       if ((arg_mod | param_mod) != 0) {
-                               if (argument.Type != parameter) {
-                                       if (argument.Type == InternalType.Dynamic)
-                                               return 0;
+                       if ((argument.Modifier | param_mod) != 0) {
+                               //
+                               // Defer to dynamic binder
+                               //
+                               if (argument.Type == InternalType.Dynamic)
+                                       return 0;
 
-                                       return 2;
+                               if (argument.Type != parameter) {
+                                       //
+                                       // Do full equality check after quick path
+                                       //
+                                       if (!TypeSpecComparer.IsEqual (argument.Type, parameter))
+                                               return 2;
                                }
                        } else {
                                //
@@ -3670,14 +3817,11 @@ namespace Mono.CSharp {
                                                lambda_conv_msgs.EndSession ();
                                        }
 
-                                       if (argument.Type == InternalType.Dynamic)
-                                               return 0;
-
                                        return 2;
                                }
                        }
 
-                       if (arg_mod != param_mod)
+                       if (argument.Modifier != param_mod)
                                return 1;
 
                        return 0;
@@ -3740,74 +3884,86 @@ namespace Mono.CSharp {
                        var current_type = rc.CurrentType;
                        MemberSpec invocable_member = null;
 
-                       // Cannot return until error reporter is restored
+                       // Be careful, cannot return until error reporter is restored
                        while (true) {
                                best_candidate = null;
                                best_candidate_rate = int.MaxValue;
 
                                var type_members = members;
+                               try {
 
-                               do {
-                                       for (int i = 0; i < type_members.Count; ++i) {
-                                               var member = type_members [i];
+                                       do {
+                                               for (int i = 0; i < type_members.Count; ++i) {
+                                                       var member = type_members[i];
 
-                                               //
-                                               // Methods in a base class are not candidates if any method in a derived
-                                               // class is applicable
-                                               //
-                                               if ((member.Modifiers & Modifiers.OVERRIDE) != 0)
-                                                       continue;
-
-                                               if (!member.IsAccessible (current_type) && !error_mode)
-                                                       continue;
-
-                                               if (!(member is IParametersMember)) {
                                                        //
-                                                       // Will use it later to report ambiguity between best method and invocable member
+                                                       // Methods in a base class are not candidates if any method in a derived
+                                                       // class is applicable
                                                        //
-                                                       if (Invocation.IsMemberInvocable (member))
-                                                               invocable_member = member;
+                                                       if ((member.Modifiers & Modifiers.OVERRIDE) != 0)
+                                                               continue;
 
-                                                       continue;
-                                               }
+                                                       if (!member.IsAccessible (current_type) && !error_mode)
+                                                               continue;
 
-                                               //
-                                               // Check if candidate is applicable
-                                               //
-                                               bool params_expanded_form = false;
-                                               int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, ref params_expanded_form);
+                                                       if (!(member is IParametersMember)) {
+                                                               //
+                                                               // Will use it later to report ambiguity between best method and invocable member
+                                                               //
+                                                               if (Invocation.IsMemberInvocable (member))
+                                                                       invocable_member = member;
 
-                                               //
-                                               // How does it score compare to others
-                                               //
-                                               if (candidate_rate < best_candidate_rate) {
-                                                       best_candidate_rate = candidate_rate;
-                                                       best_candidate = member;
-                                                       best_candidate_args = candidate_args;
-                                                       best_candidate_params = params_expanded_form;
-                                               } else if (candidate_rate == 0) {
-                                                       // Is new candidate better
-                                                       if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) {
+                                                               continue;
+                                                       }
+
+                                                       //
+                                                       // Check if candidate is applicable
+                                                       //
+                                                       bool params_expanded_form = false;
+                                                       int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, ref params_expanded_form);
+
+                                                       //
+                                                       // How does it score compare to others
+                                                       //
+                                                       if (candidate_rate < best_candidate_rate) {
+                                                               best_candidate_rate = candidate_rate;
                                                                best_candidate = member;
                                                                best_candidate_args = candidate_args;
                                                                best_candidate_params = params_expanded_form;
-                                                       } else {
-                                                               // It's not better but any other found later could be but we are not sure yet
-                                                               if (ambiguous_candidates == null)
-                                                                       ambiguous_candidates = new List<AmbiguousCandidate> ();
+                                                       } else if (candidate_rate == 0) {
+                                                               //
+                                                               // The member look is done per type for most operations but sometimes
+                                                               // it's not possible like for binary operators overload because they
+                                                               // are unioned between 2 sides
+                                                               //
+                                                               if ((restrictions & Restrictions.BaseMembersIncluded) != 0) {
+                                                                       if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true))
+                                                                               continue;
+                                                               }
 
-                                                               ambiguous_candidates.Add (new AmbiguousCandidate (member, params_expanded_form));
+                                                               // Is new candidate better
+                                                               if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) {
+                                                                       best_candidate = member;
+                                                                       best_candidate_args = candidate_args;
+                                                                       best_candidate_params = params_expanded_form;
+                                                               } else {
+                                                                       // It's not better but any other found later could be but we are not sure yet
+                                                                       if (ambiguous_candidates == null)
+                                                                               ambiguous_candidates = new List<AmbiguousCandidate> ();
+
+                                                                       ambiguous_candidates.Add (new AmbiguousCandidate (member, params_expanded_form));
+                                                               }
                                                        }
-                                               }
-
-                                               // Restore expanded arguments
-                                               if (candidate_args != args)
-                                                       candidate_args = args;
-                                       }
-                               } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
 
-                               if (prev_recorder != null)
-                                       rc.Report.SetPrinter (prev_recorder);
+                                                       // Restore expanded arguments
+                                                       if (candidate_args != args)
+                                                               candidate_args = args;
+                                               }
+                                       } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
+                               } finally {
+                                       if (prev_recorder != null)
+                                               rc.Report.SetPrinter (prev_recorder);
+                               }
 
                                //
                                // We've found exact match
@@ -3816,14 +3972,16 @@ namespace Mono.CSharp {
                                        break;
 
                                //
-                               // Extension methods lookup when no ordinary method match was found
+                               // Try extension methods lookup when no ordinary method match was found and provider enables it
                                //
                                if (!error_mode) {
-                                       var emg = base_provider.LookupExtensionMethod (rc, type_arguments == null ? 0 : type_arguments.Count);
+                                       var emg = base_provider.LookupExtensionMethod (rc);
                                        if (emg != null) {
-                                               emg = emg.OverloadResolve (rc, ref args, custom_errors, error_mode ? Restrictions.ProbingOnly : Restrictions.None);
-                                               if (emg != null)
+                                               emg = emg.OverloadResolve (rc, ref args, null, restrictions);
+                                               if (emg != null) {
+                                                       best_candidate_extension_group = emg;
                                                        return (T) (MemberSpec) emg.BestCandidate;
+                                               }
                                        }
                                }
 
@@ -3846,8 +4004,14 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       // TODO: quite slow
-                       if (args_count != 0 && args.HasDynamic) {
+                       // TODO: HasDynamic is quite slow
+                       if (args_count != 0 && (restrictions & Restrictions.CovariantDelegate) == 0 && args.HasDynamic) {
+                               if (args [0].ArgType == Argument.AType.ExtensionType) {
+                                       rc.Report.Error (1973, loc,
+                                               "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' cannot be dynamically dispatched. Consider calling the method without the extension method syntax",
+                                               args [0].Type.GetSignatureForError (), best_candidate.Name, best_candidate.GetSignatureForError());
+                               }
+
                                BestCandidateIsDynamic = true;
                                return null;
                        }
@@ -3995,14 +4159,23 @@ namespace Mono.CSharp {
                                        }
 
                                        var ms = best_candidate as MethodSpec;
-                                       if (ms != null && ms.IsGeneric && ta_count == 0) {
-                                               if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
-                                                       return;
+                                       if (ms != null && ms.IsGeneric) {
+                                               bool constr_ok = true;
+                                               if (ms.TypeArguments != null)
+                                                       constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc);
+
+                                               if (ta_count == 0) {
+                                                       if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
+                                                               return;
+
+                                                       if (constr_ok) {
+                                                               rc.Report.Error (411, loc,
+                                                                       "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
+                                                                       ms.GetGenericMethodDefinition ().GetSignatureForError ());
+                                                       }
 
-                                               rc.Report.Error (411, loc,
-                                                       "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
-                                                       ms.GetGenericMethodDefinition ().GetSignatureForError ());
-                                               return;
+                                                       return;
+                                               }
                                        }
 
                                        VerifyArguments (rc, ref args, best_candidate, params_expanded);
@@ -4066,10 +4239,10 @@ namespace Mono.CSharp {
                                        if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
                                                break;
 
-                                       if (!TypeManager.IsEqual (a.Expr.Type, pt))
-                                               break;
+                                       if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt))
+                                               continue;
 
-                                       continue;
+                                       break;
                                }
 
                                NamedArgument na = a as NamedArgument;
@@ -4102,7 +4275,7 @@ namespace Mono.CSharp {
                                if (a.Expr.Type == InternalType.Dynamic)
                                        continue;
 
-                               if ((restrictions & Restrictions.Covariant) != 0 && !Delegate.IsTypeCovariant (a.Expr, pt)) {
+                               if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (a.Expr, pt)) {
                                        custom_errors.NoArgumentMatch (ec, member);
                                        return false;
                                }
@@ -4158,6 +4331,20 @@ namespace Mono.CSharp {
                                Expression.UnsafeError (ec, loc);
                        }
 
+                       //
+                       // We could infer inaccesible type arguments
+                       //
+                       if (type_arguments == null && member.IsGeneric) {
+                               var ms = (MethodSpec) member;
+                               foreach (var ta in ms.TypeArguments) {
+                                       if (!ta.IsAccessible (ec.CurrentType)) {
+                                               ec.Report.SymbolRelatedToPreviousError (ta);
+                                               Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
+                                               break;
+                                       }
+                               }
+                       }
+
                        return true;
                }
        }
@@ -4304,7 +4491,7 @@ namespace Mono.CSharp {
                {
                        // Checks possible ldflda of field access expression
                        return !spec.IsStatic && TypeManager.IsValueType (spec.MemberType) &&
-                               TypeManager.IsSubclassOf (spec.DeclaringType, TypeManager.mbr_type) &&
+                               TypeSpec.IsBaseClass (spec.DeclaringType, TypeManager.mbr_type, false) &&
                                !(InstanceExpression is This);
                }
 
@@ -4473,7 +4660,7 @@ namespace Mono.CSharp {
                                if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
 
                                        // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
-                                       if (!TypeManager.IsEqual (ec.CurrentMemberDefinition.Parent.Definition, spec.DeclaringType.GetDefinition ()))
+                                       if (ec.CurrentMemberDefinition.Parent.Definition != spec.DeclaringType.GetDefinition ())
                                                return Report_AssignToReadonly (ec, right_side);
                                        // static InitOnly fields cannot be assigned-to in an instance constructor
                                        if (IsStatic && !ec.IsStatic)
@@ -4485,7 +4672,7 @@ namespace Mono.CSharp {
                        }
 
                        if (right_side == EmptyExpression.OutAccess.Instance &&
-                           !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (spec.DeclaringType, TypeManager.mbr_type)) {
+                               !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeSpec.IsBaseClass (spec.DeclaringType, TypeManager.mbr_type, false)) {
                                ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType);
                                ec.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",
@@ -4549,7 +4736,7 @@ namespace Mono.CSharp {
                                        EmitInstance (ec, false);
 
                                // Optimization for build-in types
-                               if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType) && TypeManager.IsEqual (InstanceExpression.Type, type)) {
+                               if (TypeManager.IsStruct (type) && type == ec.MemberContext.CurrentType && InstanceExpression.Type == type) {
                                        ec.EmitLoadFromPtr (type);
                                } else {
                                        var ff = spec as FixedFieldSpec;
@@ -4576,7 +4763,7 @@ namespace Mono.CSharp {
 
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       prepared = prepare_for_load;
+                       prepared = prepare_for_load && !(source is DynamicExpressionStatement);
                        if (IsInstance)
                                EmitInstance (ec, prepared);
 
@@ -4619,13 +4806,6 @@ namespace Mono.CSharp {
                                base.EmitSideEffect (ec);
                }
 
-               public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name)
-               {
-                       r.Error (844, loc,
-                               "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'",
-                               name, GetSignatureForError ());
-               }
-
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        if ((mode & AddressOp.Store) != 0)
@@ -4816,9 +4996,10 @@ namespace Mono.CSharp {
 
                public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       Expression my_source = source;
+                       Arguments args;
 
-                       if (prepare_for_load) {
+                       if (prepare_for_load && !(source is DynamicExpressionStatement)) {
+                               args = new Arguments (0);
                                prepared = true;
                                source.Emit (ec);
                                
@@ -4829,16 +5010,19 @@ namespace Mono.CSharp {
                                                temp.Store (ec);
                                        }
                                }
-                       } else if (leave_copy) {
-                               source.Emit (ec);
-                               temp = new LocalTemporary (this.Type);
-                               temp.Store (ec);
-                               my_source = temp;
+                       } else {
+                               args = new Arguments (1);
+
+                               if (leave_copy) {
+                                       source.Emit (ec);
+                                       temp = new LocalTemporary (this.Type);
+                                       temp.Store (ec);
+                                       args.Add (new Argument (temp));
+                               } else {
+                                       args.Add (new Argument (source));
+                               }
                        }
 
-                       Arguments args = new Arguments (1);
-                       args.Add (new Argument (my_source));
-                       
                        Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared);
                        
                        if (temp != null) {
@@ -4930,7 +5114,8 @@ namespace Mono.CSharp {
                {
                        if (right_side == EmptyExpression.OutAccess.Instance) {
                                // TODO: best_candidate can be null at this point
-                               if (best_candidate != null && ec.CurrentBlock.Toplevel.GetParameterReference (best_candidate.Name, loc) is MemberAccess) {
+                               INamedBlockVariable variable = null;
+                               if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
                                        ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
                                                best_candidate.Name);
                                } else {
@@ -5005,13 +5190,8 @@ namespace Mono.CSharp {
                bool ResolveSetter (ResolveContext rc)
                {
                        if (!best_candidate.HasSet) {
-                               if (rc.CurrentBlock.Toplevel.GetParameterReference (best_candidate.Name, loc) is MemberAccess) {
-                                       rc.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
-                                               best_candidate.Name);
-                               } else {
-                                       rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
-                                               GetSignatureForError ());
-                               }
+                               rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
+                                       GetSignatureForError ());
                                return false;
                        }
 
@@ -5037,9 +5217,10 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved expression that evaluates to an Event
        /// </summary>
-       public class EventExpr : MemberExpr
+       public class EventExpr : MemberExpr, IAssignMethod
        {
                readonly EventSpec spec;
+               MethodSpec op;
 
                public EventExpr (EventSpec spec, Location loc)
                {
@@ -5047,6 +5228,14 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               #region Properties
+
+               protected override TypeSpec DeclaringType {
+                       get {
+                               return spec.DeclaringType;
+                       }
+               }
+
                public override string Name {
                        get {
                                return spec.Name;
@@ -5065,31 +5254,23 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected override TypeSpec DeclaringType {
+               public MethodSpec Operator {
                        get {
-                               return spec.DeclaringType;
+                               return op;
                        }
                }
-               
-               public void Error_AssignmentEventOnly (ResolveContext ec)
-               {
-                       ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
-                               GetSignatureForError ());
-               }
+
+               #endregion
 
                public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
                {
                        //
-                       // If the event is local to this class, we transform ourselves into a FieldExpr
+                       // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr
                        //
+                       if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
+                               if (spec.BackingField != null &&
+                                       (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType))) {
 
-                       if (spec.DeclaringType == ec.CurrentType ||
-                           TypeManager.IsNestedChildOf(ec.CurrentType, spec.DeclaringType)) {
-                                       
-                               // TODO: Breaks dynamic binder as currect context fields are imported and not compiled
-                               // EventField mi = spec.MemberDefinition as EventField;
-
-                               if (spec.BackingField != null) {
                                        spec.MemberDefinition.SetIsUsed ();
 
                                        if (!ec.IsObsolete) {
@@ -5098,19 +5279,18 @@ namespace Mono.CSharp {
                                                        AttributeTester.Report_ObsoleteMessage (oa, spec.GetSignatureForError (), loc, ec.Report);
                                        }
 
-                                       if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
+                                       if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
                                                Error_AssignmentEventOnly (ec);
-                                       
+
                                        FieldExpr ml = new FieldExpr (spec.BackingField, loc);
 
                                        InstanceExpression = null;
-                               
+
                                        return ml.ResolveMemberAccess (ec, left, original);
                                }
-                       }
 
-                       if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))                        
                                Error_AssignmentEventOnly (ec);
+                       }
 
                        return base.ResolveMemberAccess (ec, left, original);
                }
@@ -5122,24 +5302,25 @@ namespace Mono.CSharp {
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
-                       // contexts where an LValue is valid have already devolved to FieldExprs
-                       Error_CannotAssign (ec);
-                       return null;
+                       if (right_side == EmptyExpression.EventAddition) {
+                               op = spec.AccessorAdd;
+                       } else if (right_side == EmptyExpression.EventSubtraction) {
+                               op = spec.AccessorRemove;
+                       }
+
+                       if (op == null) {
+                               Error_AssignmentEventOnly (ec);
+                               return null;
+                       }
+
+                       op = CandidateToBaseOverride (ec, op);
+                       return this;
                }
 
                protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.EventAccess;
                        type = spec.MemberType;
-/*
-                       if (!spec.IsAccessible (ec.CurrentType)) {
-                               ec.Report.SymbolRelatedToPreviousError (spec);
-                               ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report);
-                       }
-*/
-                       if (IsBase && spec.IsAbstract) {
-                               Error_CannotCallAbstractBase (ec, GetSignatureForError ());
-                       }
 
                        ResolveInstanceExpression (ec);
 
@@ -5157,6 +5338,31 @@ namespace Mono.CSharp {
                        //Error_CannotAssign ();
                }
 
+               #region IAssignMethod Members
+
+               public void Emit (EmitContext ec, bool leave_copy)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               {
+                       if (leave_copy || !prepare_for_load)
+                               throw new NotImplementedException ("EventExpr::EmitAssign");
+
+                       Arguments args = new Arguments (1);
+                       args.Add (new Argument (source));
+                       Invocation.EmitCall (ec, InstanceExpression, op, args, loc);
+               }
+
+               #endregion
+
+               void Error_AssignmentEventOnly (ResolveContext ec)
+               {
+                       ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
+                               GetSignatureForError ());
+               }
+
                public void Error_CannotAssign (ResolveContext ec)
                {
                        ec.Report.Error (70, loc,
@@ -5164,16 +5370,15 @@ namespace Mono.CSharp {
                                GetSignatureForError (), TypeManager.CSharpName (spec.DeclaringType));
                }
 
-               public override string GetSignatureForError ()
+               protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name)
                {
-                       return TypeManager.CSharpSignature (spec);
+                       name = name.Substring (0, name.LastIndexOf ('.'));
+                       base.Error_CannotCallAbstractBase (rc, name);
                }
 
-               public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
+               public override string GetSignatureForError ()
                {
-                       Arguments args = new Arguments (1);
-                       args.Add (new Argument (source));
-                       Invocation.EmitCall (ec, InstanceExpression, is_add ? spec.AccessorAdd : spec.AccessorRemove, args, loc);
+                       return TypeManager.CSharpSignature (spec);
                }
 
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
@@ -5182,16 +5387,50 @@ namespace Mono.CSharp {
                }
        }
 
-       public class TemporaryVariable : VariableReference
+       public class TemporaryVariableReference : VariableReference
        {
-               LocalInfo li;
+               public class Declarator : Statement
+               {
+                       TemporaryVariableReference variable;
+
+                       public Declarator (TemporaryVariableReference variable)
+                       {
+                               this.variable = variable;
+                               loc = variable.loc;
+                       }
+
+                       protected override void DoEmit (EmitContext ec)
+                       {
+                               variable.li.CreateBuilder (ec);
+                       }
+
+                       protected override void CloneTo (CloneContext clonectx, Statement target)
+                       {
+                               // Nothing
+                       }
+               }
+
+               LocalVariable li;
 
-               public TemporaryVariable (TypeSpec type, Location loc)
+               public TemporaryVariableReference (LocalVariable li, Location loc)
                {
-                       this.type = type;
+                       this.li = li;
+                       this.type = li.Type;
                        this.loc = loc;
                }
 
+               public LocalVariable LocalInfo {
+                   get {
+                       return li;
+                   }
+               }
+
+               public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc)
+               {
+                       var li = LocalVariable.CreateCompilerGenerated (type, block, loc);
+                       return new TemporaryVariableReference (li, loc);
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        throw new NotSupportedException ("ET");
@@ -5201,11 +5440,6 @@ namespace Mono.CSharp {
                {
                        eclass = ExprClass.Variable;
 
-                       TypeExpr te = new TypeExpression (type, loc);
-                       li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
-                       if (!li.Resolve (ec))
-                               return null;
-
                        //
                        // Don't capture temporary variables except when using
                        // iterator redirection
@@ -5225,11 +5459,15 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
+                       li.CreateBuilder (ec);
+
                        Emit (ec, false);
                }
 
                public void EmitAssign (EmitContext ec, Expression source)
                {
+                       li.CreateBuilder (ec);
+
                        EmitAssign (ec, source, false, false);
                }
 
@@ -5270,19 +5508,9 @@ namespace Mono.CSharp {
        /// 
        class VarExpr : SimpleName
        {
-               // Used for error reporting only
-               int initializers_count;
-
                public VarExpr (Location loc)
                        : base ("var", loc)
                {
-                       initializers_count = 1;
-               }
-
-               public int VariableInitializersCount {
-                       set {
-                               this.initializers_count = value;
-                       }
                }
 
                public bool InferType (ResolveContext ec, Expression right_side)
@@ -5291,7 +5519,7 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
                        
                        type = right_side.Type;
-                       if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+                       if (type == InternalType.Null || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
                                ec.Report.Error (815, loc,
                                        "An implicitly typed local variable declaration cannot be initialized with `{0}'",
                                        type.GetSignatureForError ());
@@ -5309,32 +5537,5 @@ namespace Mono.CSharp {
                        else
                                ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
                }
-
-               public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
-               {
-                       TypeExpr te = base.ResolveAsContextualType (rc, true);
-                       if (te != null)
-                               return te;
-
-                       if (RootContext.Version < LanguageVersion.V_3)
-                               rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable");
-
-                       if (initializers_count == 1)
-                               return null;
-
-                       if (initializers_count > 1) {
-                               rc.Compiler.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
-                               initializers_count = 1;
-                               return null;
-                       }
-
-                       if (initializers_count == 0) {
-                               initializers_count = 1;
-                               rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
-                               return null;
-                       }
-
-                       return null;
-               }
        }
 }