Merge pull request #1063 from esdrubal/bug18482
[mono.git] / mcs / mcs / ecore.cs
index e1162714ddc563b2df057d5ab17a17f64f893459..97fe44d239d5dc4213cce585784c0fbeab194858 100644 (file)
@@ -429,6 +429,18 @@ namespace Mono.CSharp {
                {
                        return type.GetDefinition ().GetSignatureForError ();
                }
+
+               protected static bool IsNullPropagatingValid (TypeSpec type)
+               {
+                       return (TypeSpec.IsReferenceType (type) && type != InternalType.NullLiteral) || type.IsNullableType;
+               }
+
+               protected static TypeSpec LiftMemberType (ResolveContext rc, TypeSpec type)
+               {
+                       return TypeSpec.IsValueType (type) && !type.IsNullableType ?
+                               Nullable.NullableInfo.MakeType (rc.Module, type) :
+                               type;
+               }
               
                /// <summary>
                ///   Resolves an expression and performs semantic analysis on it.
@@ -466,7 +478,7 @@ namespace Mono.CSharp {
 
                                return e;
                        } catch (Exception ex) {
-                               if (loc.IsNull || ec.Module.Compiler.Settings.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled || ex is FatalException ||
+                               if (loc.IsNull || ec.Module.Compiler.Settings.BreakOnInternalError || ex is CompletionResult || ec.Report.IsDisabled || ex is FatalException ||
                                        ec.Report.Printer is NullReportPrinter)
                                        throw;
 
@@ -540,10 +552,16 @@ namespace Mono.CSharp {
                        return c;
                }
 
-               public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
+               public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
                {
-                       rc.Module.Compiler.Report.Error (182, loc,
-                               "An attribute argument must be a constant expression, typeof expression or array creation expression");
+                       if (Attribute.IsValidArgumentType (parameterType)) {
+                               rc.Module.Compiler.Report.Error (182, loc,
+                                       "An attribute argument must be a constant expression, typeof expression or array creation expression");
+                       } else {
+                               rc.Module.Compiler.Report.Error (181, loc,
+                                       "Attribute constructor parameter has type `{0}', which is not a valid attribute parameter type",
+                                       targetType.GetSignatureForError ());
+                       }
                }
 
                /// <summary>
@@ -930,6 +948,11 @@ namespace Mono.CSharp {
                        ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
                }
 
+               protected void Error_NullShortCircuitInsideExpressionTree (ResolveContext rc)
+               {
+                       rc.Report.Error (8072, loc, "An expression tree cannot contain a null propagating operator");
+               }
+
                public virtual void FlowAnalysis (FlowAnalysisContext fc)
                {
                }
@@ -1582,9 +1605,9 @@ namespace Mono.CSharp {
                        Child.Emit (ec);
                }
 
-               public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
+               public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
                {
-                       Child.EncodeAttributeValue (rc, enc, Child.Type);
+                       Child.EncodeAttributeValue (rc, enc, Child.Type, parameterType);
                }
 
                public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
@@ -1702,16 +1725,16 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
+               public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
                {
                        // Only boxing to object type is supported
                        if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) {
-                               base.EncodeAttributeValue (rc, enc, targetType);
+                               base.EncodeAttributeValue (rc, enc, targetType, parameterType);
                                return;
                        }
 
                        enc.Encode (child.Type);
-                       child.EncodeAttributeValue (rc, enc, child.Type);
+                       child.EncodeAttributeValue (rc, enc, child.Type, parameterType);
                }
 
                public override void Emit (EmitContext ec)
@@ -2113,15 +2136,15 @@ namespace Mono.CSharp {
                                return c;
                        }
 
-                       public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
+                       public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
                        {
                                //
                                // LAMESPEC: Reduced conditional expression is allowed as an attribute argument
                                //
                                if (orig_expr is Conditional)
-                                       child.EncodeAttributeValue (rc, enc, targetType);
+                                       child.EncodeAttributeValue (rc, enc, targetType,parameterType);
                                else
-                                       base.EncodeAttributeValue (rc, enc, targetType);
+                                       base.EncodeAttributeValue (rc, enc, targetType, parameterType);
                        }
                }
 
@@ -2606,7 +2629,7 @@ namespace Mono.CSharp {
                                //
                                // dynamic namespace is ignored when dynamic is allowed (does not apply to types)
                                //
-                               if (!(fne is Namespace))
+                               if (!(fne is NamespaceExpression))
                                        return fne;
                        }
 
@@ -2754,6 +2777,15 @@ namespace Mono.CSharp {
                                        }
                                }
 
+                               var mg = NamespaceContainer.LookupStaticUsings (rc, Name, Arity, loc);
+                               if (mg != null) {
+                                       if (Arity > 0) {
+                                               targs.Resolve (rc);
+                                               mg.SetTypeArguments (rc, targs);
+                                       }
+                                       return mg;
+                               }
+
                                if (errorMode) {
                                        if (variable_found) {
                                                rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
@@ -2984,6 +3016,114 @@ namespace Mono.CSharp {
                }
        }
 
+       public class NamespaceExpression : FullNamedExpression
+       {
+               readonly Namespace ns;
+
+               public NamespaceExpression (Namespace ns, Location loc)
+               {
+                       this.ns = ns;
+                       this.Type = InternalType.Namespace;
+                       this.eclass = ExprClass.Namespace;
+                       this.loc = loc;
+               }
+
+               public Namespace Namespace {
+                       get {
+                               return ns;
+                       }
+               }
+
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc)
+               {
+                       return this;
+               }
+
+               public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity)
+               {
+                       var retval = Namespace.LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
+                       if (retval != null) {
+//                             ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.MemberDefinition);
+                               ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
+                               return;
+                       }
+
+                       retval = Namespace.LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc);
+                       if (retval != null) {
+                               Error_TypeArgumentsCannotBeUsed (ctx, retval, loc);
+                               return;
+                       }
+
+                       Namespace ns;
+                       if (arity > 0 && Namespace.TryGetNamespace (name, out ns)) {
+                               Error_TypeArgumentsCannotBeUsed (ctx, ExprClassName, ns.GetSignatureForError (), loc);
+                               return;
+                       }
+
+                       string assembly = null;
+                       string possible_name = Namespace.GetSignatureForError () + "." + name;
+
+                       // Only assembly unique name should be added
+                       switch (possible_name) {
+                       case "System.Drawing":
+                       case "System.Web.Services":
+                       case "System.Web":
+                       case "System.Data":
+                       case "System.Configuration":
+                       case "System.Data.Services":
+                       case "System.DirectoryServices":
+                       case "System.Json":
+                       case "System.Net.Http":
+                       case "System.Numerics":
+                       case "System.Runtime.Caching":
+                       case "System.ServiceModel":
+                       case "System.Transactions":
+                       case "System.Web.Routing":
+                       case "System.Xml.Linq":
+                       case "System.Xml":
+                               assembly = possible_name;
+                               break;
+
+                       case "System.Linq":
+                       case "System.Linq.Expressions":
+                               assembly = "System.Core";
+                               break;
+
+                       case "System.Windows.Forms":
+                       case "System.Windows.Forms.Layout":
+                               assembly = "System.Windows.Forms";
+                               break;
+                       }
+
+                       assembly = assembly == null ? "an" : "`" + assembly + "'";
+
+                       if (Namespace is GlobalRootNamespace) {
+                               ctx.Module.Compiler.Report.Error (400, loc,
+                                       "The type or namespace name `{0}' could not be found in the global namespace. Are you missing {1} assembly reference?",
+                                       name, assembly);
+                       } else {
+                               ctx.Module.Compiler.Report.Error (234, loc,
+                                       "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing {2} assembly reference?",
+                                       name, GetSignatureForError (), assembly);
+                       }
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return ns.GetSignatureForError ();
+               }
+
+               public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
+               {
+                       return ns.LookupTypeOrNamespace (ctx, name, arity, mode, loc);
+               }
+    }
+
        /// <summary>
        ///   This class denotes an expression which evaluates to a member
        ///   of a struct or a class.
@@ -3028,6 +3168,8 @@ namespace Mono.CSharp {
                        get;
                }
 
+               public bool NullShortCircuit { get; set; }
+
                protected abstract TypeSpec DeclaringType {
                        get;
                }
@@ -3233,7 +3375,7 @@ namespace Mono.CSharp {
                        //
                        // Check intermediate value modification which won't have any effect
                        //
-                       if (rhs != null && InstanceExpression.Type.IsStruct) {
+                       if (rhs != null && TypeSpec.IsValueType (InstanceExpression.Type)) {
                                var fexpr = InstanceExpression as FieldExpr;
                                if (fexpr != null) {
                                        if (!fexpr.Spec.IsReadOnly || rc.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
@@ -3308,14 +3450,25 @@ namespace Mono.CSharp {
 
                        if (InstanceExpression == null || InstanceExpression is TypeExpr) {
                                if (InstanceExpression != null || !This.IsThisAvailable (rc, true)) {
-                                       if (rc.HasSet (ResolveContext.Options.FieldInitializerScope))
+                                       if (rc.HasSet (ResolveContext.Options.FieldInitializerScope)) {
                                                rc.Report.Error (236, loc,
                                                        "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
                                                        GetSignatureForError ());
-                                       else
-                                               rc.Report.Error (120, loc,
-                                                       "An object reference is required to access non-static member `{0}'",
-                                                       GetSignatureForError ());
+                                       } else {
+                                               var fe = this as FieldExpr;
+                                               if (fe != null && fe.Spec.MemberDefinition is PrimaryConstructorField) {
+                                                       if (rc.HasSet (ResolveContext.Options.BaseInitializer)) {
+                                                               rc.Report.Error (9005, loc, "Constructor initializer cannot access primary constructor parameters");
+                                                       } else  {
+                                                               rc.Report.Error (9006, loc, "An object reference is required to access primary constructor parameter `{0}'",
+                                                                       fe.Name);
+                                                       }
+                                               } else {
+                                                       rc.Report.Error (120, loc,
+                                                               "An object reference is required to access non-static member `{0}'",
+                                                               GetSignatureForError ());
+                                               }
+                                       }
 
                                        InstanceExpression = new CompilerGeneratedThis (rc.CurrentType, loc).Resolve (rc);
                                        return false;
@@ -3360,7 +3513,7 @@ namespace Mono.CSharp {
 
                public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
                {
-                       if (left != null && left.IsNull && TypeSpec.IsReferenceType (left.Type)) {
+                       if (left != null && !NullShortCircuit && left.IsNull && TypeSpec.IsReferenceType (left.Type)) {
                                ec.Report.Warning (1720, 1, left.Location,
                                        "Expression will always cause a `{0}'", "System.NullReferenceException");
                        }
@@ -3369,30 +3522,16 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               protected void EmitInstance (EmitContext ec, bool prepare_for_load)
+               protected InstanceEmitter EmitInstance (EmitContext ec, bool prepare_for_load)
                {
-                       TypeSpec instance_type = InstanceExpression.Type;
-                       if (TypeSpec.IsValueType (instance_type)) {
-                               if (InstanceExpression is IMemoryLocation) {
-                                       ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.Load);
-                               } else {
-                                       // Cannot release the temporary variable when its address
-                                       // is required to be on stack for any parent
-                                       LocalTemporary t = new LocalTemporary (instance_type);
-                                       InstanceExpression.Emit (ec);
-                                       t.Store (ec);
-                                       t.AddressOf (ec, AddressOp.Store);
-                               }
-                       } else {
-                               InstanceExpression.Emit (ec);
-
-                               // Only to make verifier happy
-                               if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeSpec.IsReferenceType (instance_type))
-                                       ec.Emit (OpCodes.Box, instance_type);
-                       }
+                       var inst = new InstanceEmitter (InstanceExpression, TypeSpec.IsValueType (InstanceExpression.Type));
+                       inst.NullShortCircuit = NullShortCircuit;
+                       inst.Emit (ec);
 
                        if (prepare_for_load)
                                ec.Emit (OpCodes.Dup);
+
+                       return inst;
                }
 
                public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta);
@@ -3689,7 +3828,10 @@ namespace Mono.CSharp {
                        if (IsConditionallyExcluded)
                                ec.Report.Error (765, loc,
                                        "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
-                       
+
+                       if (NullShortCircuit)
+                               Error_NullShortCircuitInsideExpressionTree (ec);
+
                        return new TypeOfMethod (best_candidate, loc);
                }
                
@@ -3711,11 +3853,15 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ();
                }
                
-               public void EmitCall (EmitContext ec, Arguments arguments)
+               public void EmitCall (EmitContext ec, Arguments arguments, bool statement)
                {
                        var call = new CallEmitter ();
                        call.InstanceExpression = InstanceExpression;
-                       call.Emit (ec, best_candidate, arguments, loc);                 
+                       call.NullShortCircuit = NullShortCircuit;
+                       if (statement)
+                               call.EmitStatement (ec, best_candidate, arguments, loc);
+                       else
+                               call.Emit (ec, best_candidate, arguments, loc);
                }
 
                public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
@@ -3765,8 +3911,15 @@ namespace Mono.CSharp {
 
                        // TODO: When in probing mode do IsApplicable only and when called again do VerifyArguments for full error reporting
                        best_candidate = r.ResolveMember<MethodSpec> (ec, ref args);
-                       if (best_candidate == null)
-                               return r.BestCandidateIsDynamic ? this : null;
+                       if (best_candidate == null) {
+                               if (!r.BestCandidateIsDynamic)
+                                       return null;
+
+                               if (simple_name != null && ec.IsStatic)
+                                       InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name);
+
+                               return this;
+                       }
 
                        // Overload resolver had to create a new method group, all checks bellow have already been executed
                        if (r.BestCandidateNewMethodGroup != null)
@@ -3777,7 +3930,7 @@ namespace Mono.CSharp {
                                        if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) {
                                                InstanceExpression = null;
                                        } else {
-                                               if (best_candidate.IsStatic && simple_name != null) {
+                                               if (simple_name != null && best_candidate.IsStatic) {
                                                        InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name);
                                                }
 
@@ -3815,6 +3968,9 @@ namespace Mono.CSharp {
                        if (best_candidate_return.Kind == MemberKind.Void && best_candidate.IsConditionallyExcluded (ec))
                                Methods = Excluded;
 
+                       if (NullShortCircuit)
+                               best_candidate_return = LiftMemberType (ec, best_candidate_return);
+
                        return this;
                }
 
@@ -3904,7 +4060,8 @@ namespace Mono.CSharp {
                        ProbingOnly     = 1 << 1,
                        CovariantDelegate = 1 << 2,
                        NoBaseMembers = 1 << 3,
-                       BaseMembersIncluded = 1 << 4
+                       BaseMembersIncluded = 1 << 4,
+                       GetEnumeratorLookup = 1 << 5
                }
 
                public interface IBaseMembersProvider
@@ -4105,7 +4262,6 @@ namespace Mono.CSharp {
                                if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types))
                                        return 0;
 
-                               var orig_p = p;
                                p = p_m.ReturnType;
                                var orig_q = q;
                                q = q_m.ReturnType;
@@ -4135,33 +4291,34 @@ namespace Mono.CSharp {
                                                q = q.TypeArguments[0];
                                                p = p.TypeArguments[0];
                                        }
-                               } else if (q != p) {
+                               }
+
+                               if (q != p) {
                                        //
-                                       // LAMESPEC: Lambda expression returning dynamic type has identity (better) conversion to delegate returning object type
+                                       // An inferred return type X exists for E in the context of that parameter list, and 
+                                       // the conversion from X to Y1 is better than the conversion from X to Y2
                                        //
-                                       if (q.BuiltinType == BuiltinTypeSpec.Type.Object) {
-                                               var am_rt = am.InferReturnType (ec, null, orig_q);
-                                               if (am_rt != null && am_rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
-                                                       return 2;
-                                       } else if (p.BuiltinType == BuiltinTypeSpec.Type.Object) {
-                                               var am_rt = am.InferReturnType (ec, null, orig_p);
-                                               if (am_rt != null && am_rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
-                                                       return 1;
+                                       argument_type = am.InferReturnType (ec, null, orig_q);
+                                       if (argument_type == null) {
+                                               // TODO: Can this be hit?
+                                               return 1;
                                        }
+
+                                       if (argument_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
+                                               argument_type = ec.BuiltinTypes.Object;
                                }
+                       }
 
-                               //
-                               // The parameters are identicial and return type is not void, use better type conversion
-                               // on return type to determine better one
-                               //
-                       } else {
-                               if (argument_type == p)
-                                       return 1;
+                       if (argument_type == p)
+                               return 1;
 
-                               if (argument_type == q)
-                                       return 2;
-                       }
+                       if (argument_type == q)
+                               return 2;
 
+                       //
+                       // The parameters are identicial and return type is not void, use better type conversion
+                       // on return type to determine better one
+                       //
                        return BetterTypeConversion (ec, p, q);
                }
 
@@ -4269,7 +4426,7 @@ namespace Mono.CSharp {
                        AParametersCollection best_pd = ((IParametersMember) best).Parameters;
 
                        bool better_at_least_one = false;
-                       bool same = true;
+                       bool are_equivalent = true;
                        int args_count = args == null ? 0 : args.Count;
                        int j = 0;
                        Argument a = null;
@@ -4314,7 +4471,7 @@ namespace Mono.CSharp {
                                if (TypeSpecComparer.IsEqual (ct, bt))
                                        continue;
 
-                               same = false;
+                               are_equivalent = false;
                                int result = BetterExpressionConversion (ec, a, ct, bt);
 
                                // for each argument, the conversion to 'ct' should be no worse than 
@@ -4332,68 +4489,63 @@ namespace Mono.CSharp {
                                return true;
 
                        //
-                       // This handles the case
-                       //
-                       //   Add (float f1, float f2, float f3);
-                       //   Add (params decimal [] foo);
+                       // Tie-breaking rules are applied only for equivalent parameter types
                        //
-                       // The call Add (3, 4, 5) should be ambiguous.  Without this check, the
-                       // first candidate would've chosen as better.
-                       //
-                       if (!same && !a.IsDefaultArgument)
+                       if (!are_equivalent)
                                return false;
 
                        //
-                       // The two methods have equal non-optional parameter types, apply tie-breaking rules
+                       // If candidate is applicable in its normal form and best has a params array and is applicable
+                       // only in its expanded form, then candidate is better
                        //
+                       if (candidate_params != best_params)
+                               return !candidate_params;
 
                        //
-                       // 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)
-                       //  Foo (string s, params string[] args) is better than Foo (params string[] args)
-                       //
-                       // Prefer non-optional version
-                       //
-                       // LAMESPEC: Specification claims this should be done at last but the opposite is true
+                       // We have not reached end of parameters list due to params or used default parameters
                        //
-                       if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) {
-                               if (j < candidate_pd.Count && candidate_pd.FixedParameters[j].HasDefaultValue)
-                                       return false;
+                       while (j < candidate_pd.Count && j < best_pd.Count) {
+                               var cand_param = candidate_pd.FixedParameters [j];
+                               var best_param = best_pd.FixedParameters [j];
 
-                               if (j < best_pd.Count && best_pd.FixedParameters[j].HasDefaultValue)
-                                       return true;
+                               if (candidate_pd.Count == best_pd.Count) {
+                                       //
+                                       // LAMESPEC:
+                                       //
+                                       // void Foo (int i = 0) is better than void Foo (params int[]) for Foo ()
+                                       // void Foo (string[] s, string value = null) is better than Foo (string s, params string[]) for Foo (null) or Foo ()
+                                       //
+                                       if (cand_param.HasDefaultValue != best_param.HasDefaultValue)
+                                               return cand_param.HasDefaultValue;
 
-                               return candidate_pd.Count >= best_pd.Count;
+                                       if (cand_param.HasDefaultValue) {
+                                               ++j;
+                                               continue;
+                                       }
+                               } else {
+                                       //
+                                       // Neither is better when not all arguments are provided
+                                       //
+                                       // void Foo (string s, int i = 0) <-> Foo (string s, int i = 0, int i2 = 0)
+                                       // void Foo (string s, int i = 0) <-> Foo (string s, byte i = 0)
+                                       // void Foo (string s, params int[]) <-> Foo (string s, params byte[])
+                                       //
+                                       if (cand_param.HasDefaultValue && best_param.HasDefaultValue)
+                                               return false;
+                               }
+
+                               break;
                        }
 
+                       if (candidate_pd.Count != best_pd.Count)
+                               return candidate_pd.Count < best_pd.Count;
+
                        //
                        // 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:
-                       //
-                       //   Trim () is better than Trim (params char[] chars)
-                       //   Concat (string s1, string s2, string s3) is better than
-                       //     Concat (string s1, params string [] srest)
-                       //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
-                       //
-                       // 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;
-
-                       if (candidate_param_count != best_param_count)
-                               // can only happen if (candidate_params && best_params)
-                               return candidate_param_count > best_param_count && best_pd.HasParams;
-
                        //
                        // Both methods have the same number of parameters, and the parameters have equal types
                        // Pick the "more specific" signature using rules over original (non-inflated) types
@@ -4470,7 +4622,7 @@ namespace Mono.CSharp {
                // 0 = the best, int.MaxValue = the worst
                // -1 = fatal error
                //
-               int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType)
+               int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType, bool errorMode)
                {
                        // Parameters of most-derived type used mainly for named and optional parameters
                        var pd = pm.Parameters;
@@ -4567,7 +4719,10 @@ namespace Mono.CSharp {
                                                                ++arg_count;
                                                                temp = null;
                                                        } else {
-                                                               temp = arguments[index];
+                                                               if (index == arg_count) 
+                                                                       return (i + 1) * 3;
+
+                                                               temp = arguments [index];
 
                                                                // The slot has been taken by positional argument
                                                                if (temp != null && !(temp is NamedArgument))
@@ -4621,7 +4776,8 @@ namespace Mono.CSharp {
                                        if (g_args_count != type_arguments.Count)
                                                return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count);
 
-                                       ms = ms.MakeGenericMethod (ec, type_arguments.Arguments);
+                                       if (type_arguments.Arguments != null)
+                                               ms = ms.MakeGenericMethod (ec, type_arguments.Arguments);
                                } else {
                                        //
                                        // Deploy custom error reporting for infered anonymous expression or lambda methods. When
@@ -4659,6 +4815,13 @@ namespace Mono.CSharp {
                                                lambda_conv_msgs.ClearSession ();
 
                                        if (i_args.Length != 0) {
+                                               if (!errorMode) {
+                                                       foreach (var ta in i_args) {
+                                                               if (!ta.IsAccessible (ec))
+                                                                       return ti.InferenceScore - 10000;
+                                                       }
+                                               }
+
                                                ms = ms.MakeGenericMethod (ec, i_args);
                                        }
                                }
@@ -4803,12 +4966,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       //
-                       // When params parameter has no argument it will be provided later if the method is the best candidate
-                       //
-                       if (arg_count + 1 == pd.Count && (cpd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0)
-                               params_expanded_form = true;
-
                        //
                        // Restore original arguments for dynamic binder to keep the intention of original source code
                        //
@@ -5018,7 +5175,7 @@ namespace Mono.CSharp {
                                                bool params_expanded_form = false;
                                                bool dynamic_argument = false;
                                                TypeSpec rt = pm.MemberType;
-                                               int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt);
+                                               int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt, error_mode);
 
                                                if (lambda_conv_msgs != null)
                                                        lambda_conv_msgs.EndSession ();
@@ -5032,13 +5189,17 @@ namespace Mono.CSharp {
                                                        if (candidate_rate < 0)
                                                                return null;
 
-                                                       best_candidate_rate = candidate_rate;
-                                                       best_candidate = member;
-                                                       best_candidate_args = candidate_args;
-                                                       best_candidate_params = params_expanded_form;
-                                                       best_candidate_dynamic = dynamic_argument;
-                                                       best_parameter_member = pm;
-                                                       best_candidate_return_type = rt;
+                                                       if ((restrictions & Restrictions.GetEnumeratorLookup) != 0 && candidate_args.Count != 0) {
+                                                               // Only parameterless methods are considered
+                                                       } else {
+                                                               best_candidate_rate = candidate_rate;
+                                                               best_candidate = member;
+                                                               best_candidate_args = candidate_args;
+                                                               best_candidate_params = params_expanded_form;
+                                                               best_candidate_dynamic = dynamic_argument;
+                                                               best_parameter_member = pm;
+                                                               best_candidate_return_type = rt;
+                                                       }
                                                } else if (candidate_rate == 0) {
                                                        //
                                                        // The member look is done per type for most operations but sometimes
@@ -5322,8 +5483,7 @@ namespace Mono.CSharp {
                        // For candidates which match on parameters count report more details about incorrect arguments
                        //
                        if (pm != null) {
-                               int unexpanded_count = ((IParametersMember) best_candidate).Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count;
-                               if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) {
+                               if (pm.Parameters.Count == arg_count || params_expanded || HasUnfilledParams (best_candidate, pm, args)) {
                                        // Reject any inaccessible member
                                        if (!best_candidate.IsAccessible (rc) || !best_candidate.DeclaringType.IsAccessible (rc)) {
                                                rc.Report.SymbolRelatedToPreviousError (best_candidate);
@@ -5377,10 +5537,47 @@ namespace Mono.CSharp {
                        }
                }
 
+               static bool HasUnfilledParams (MemberSpec best_candidate, IParametersMember pm, Arguments args)
+               {
+                       var p = ((IParametersMember)best_candidate).Parameters;
+                       if (!p.HasParams)
+                               return false;
+
+                       string name = null;
+                       for (int i = p.Count - 1; i != 0; --i) {
+                               var fp = p.FixedParameters [i];
+                               if ((fp.ModFlags & Parameter.Modifier.PARAMS) == 0)
+                                       continue;
+
+                               name = fp.Name;
+                               break;
+                       }
+
+                       if (args == null)
+                               return false;
+
+                       foreach (var arg in args) {
+                               var na = arg as NamedArgument;
+                               if (na == null)
+                                       continue;
+
+                               if (na.Name == name) {
+                                       name = null;
+                                       break;
+                               }
+                       }
+
+                       if (name == null)
+                               return false;
+
+                       return args.Count + 1 == pm.Parameters.Count;
+               }
+
                bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, IParametersMember pm, bool chose_params_expanded)
                {
                        var pd = pm.Parameters;
-                       TypeSpec[] ptypes = ((IParametersMember) member).Parameters.Types;
+                       var cpd = ((IParametersMember) member).Parameters;
+                       var ptypes = cpd.Types;
 
                        Parameter.Modifier p_mod = 0;
                        TypeSpec pt = null;
@@ -5396,7 +5593,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (p_mod != Parameter.Modifier.PARAMS) {
-                                       p_mod = pd.FixedParameters[a_idx].ModFlags;
+                                       p_mod = cpd.FixedParameters [a_idx].ModFlags;
                                        pt = ptypes[a_idx];
                                        has_unsafe_arg |= pt.IsPointer;
 
@@ -5497,7 +5694,7 @@ namespace Mono.CSharp {
                        //
                        // Fill not provided arguments required by params modifier
                        //
-                       if (params_initializers == null && pd.HasParams && arg_count + 1 == pd.Count) {
+                       if (params_initializers == null && arg_count + 1 == pd.Count) {
                                if (args == null)
                                        args = new Arguments (1);
 
@@ -5701,8 +5898,20 @@ namespace Mono.CSharp {
                        }
                }
 
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       var t = (FieldExpr) target;
+
+                       if (InstanceExpression != null)
+                               t.InstanceExpression = InstanceExpression.Clone (clonectx);
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
+                       if (NullShortCircuit) {
+                               Error_NullShortCircuitInsideExpressionTree (ec);
+                       }
+
                        return CreateExpressionTree (ec, true);
                }
 
@@ -5796,6 +6005,13 @@ namespace Mono.CSharp {
                                variable_info = var.VariableInfo.GetStructFieldInfo (Name);
                        }
 
+                       if (NullShortCircuit) {
+                               type = LiftMemberType (ec, type);
+
+                               if (InstanceExpression.IsNull)
+                                       return Constant.CreateConstantFromValue (type, null, loc);
+                       }
+
                        eclass = ExprClass.Variable;
                        return this;
                }
@@ -5890,8 +6106,11 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
+               public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
+                       if (NullShortCircuit)
+                               throw new NotSupportedException ("null propagating operator assignment");
+
                        if (spec is FixedFieldSpec) {
                                // It could be much better error message but we want to be error compatible
                                Error_ValueAssignment (ec, right_side);
@@ -5951,7 +6170,7 @@ namespace Mono.CSharp {
                                        return;
                                }
 
-                               if (TypeSpec.IsValueType (InstanceExpression.Type))
+                               if (TypeSpec.IsValueType (InstanceExpression.Type) && InstanceExpression is VariableReference)
                                        return;
                        }
 
@@ -6002,8 +6221,11 @@ namespace Mono.CSharp {
 
                                ec.Emit (OpCodes.Ldsfld, spec);
                        } else {
+                               InstanceEmitter ie;
                                if (!prepared)
-                                       EmitInstance (ec, false);
+                                       ie = EmitInstance (ec, false);
+                               else
+                                       ie = new InstanceEmitter ();
 
                                // Optimization for build-in types
                                if (type.IsStruct && type == ec.CurrentType && InstanceExpression.Type == type) {
@@ -6018,6 +6240,10 @@ namespace Mono.CSharp {
                                                        ec.Emit (OpCodes.Volatile);
 
                                                ec.Emit (OpCodes.Ldfld, spec);
+
+                                               if (NullShortCircuit) {
+                                                       ie.EmitResultLift (ec, spec.MemberType, false);
+                                               }
                                        }
                                }
                        }
@@ -6034,16 +6260,14 @@ namespace Mono.CSharp {
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
                {
                        bool has_await_source = ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait ();
-                       if (isCompound && !(source is DynamicExpressionStatement)) {
-                               if (has_await_source) {
-                                       if (IsInstance)
-                                               InstanceExpression = InstanceExpression.EmitToField (ec);
-                               } else {
-                                       prepared = true;
-                               }
+                       if (isCompound && !(source is DynamicExpressionStatement) && !has_await_source) {
+                               prepared = true;
                        }
 
                        if (IsInstance) {
+                               if (NullShortCircuit)
+                                       throw new NotImplementedException ("null operator assignment");
+
                                if (has_await_source)
                                        source = source.EmitToField (ec);
 
@@ -6052,7 +6276,7 @@ namespace Mono.CSharp {
 
                        source.Emit (ec);
 
-                       if (leave_copy) {
+                       if (leave_copy || ec.NotifyEvaluatorOnStore) {
                                ec.Emit (OpCodes.Dup);
                                if (!IsStatic) {
                                        temp = new LocalTemporary (this.Type);
@@ -6069,6 +6293,16 @@ namespace Mono.CSharp {
                                ec.Emit (OpCodes.Stsfld, spec);
                        else
                                ec.Emit (OpCodes.Stfld, spec);
+
+                       if (ec.NotifyEvaluatorOnStore) {
+                               if (!IsStatic)
+                                       throw new NotImplementedException ("instance field write");
+
+                               if (leave_copy)
+                                       ec.Emit (OpCodes.Dup);
+
+                               ec.Module.Evaluator.EmitValueChangedCallback (ec, Name, type, loc);
+                       }
                        
                        if (temp != null) {
                                temp.Emit (ec);
@@ -6131,7 +6365,6 @@ namespace Mono.CSharp {
                                var temp = ec.GetTemporaryLocal (type);
                                ec.Emit (OpCodes.Stloc, temp);
                                ec.Emit (OpCodes.Ldloca, temp);
-                               ec.FreeTemporaryLocal (temp, type);
                                return;
                        }
 
@@ -6257,6 +6490,10 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
+                       if (NullShortCircuit) {
+                               Error_NullShortCircuitInsideExpressionTree (ec);
+                       }
+
                        Arguments args;
                        if (IsSingleDimensionalArrayLength ()) {
                                args = new Arguments (1);
@@ -6324,9 +6561,14 @@ namespace Mono.CSharp {
                        // Special case: length of single dimension array property is turned into ldlen
                        //
                        if (IsSingleDimensionalArrayLength ()) {
-                               EmitInstance (ec, false);
+                               var inst = EmitInstance (ec, false);
+
                                ec.Emit (OpCodes.Ldlen);
                                ec.Emit (OpCodes.Conv_I4);
+
+                               if (NullShortCircuit)
+                                       inst.EmitResultLift (ec, ec.BuiltinTypes.Int, false);
+
                                return;
                        }
 
@@ -6382,8 +6624,15 @@ namespace Mono.CSharp {
                        call.InstanceExpression = InstanceExpression;
                        if (args == null)
                                call.InstanceExpressionOnStack = true;
+                       if (NullShortCircuit) {
+                               call.NullShortCircuit = true;
+                               call.NullOperatorLabel = null_operator_label;
+                       }
 
-                       call.Emit (ec, Setter, args, loc);
+                       if (leave_copy)
+                               call.Emit (ec, Setter, args, loc);
+                       else
+                               call.EmitStatement (ec, Setter, args, loc);
 
                        if (temp != null) {
                                temp.Emit (ec);
@@ -6448,6 +6697,7 @@ namespace Mono.CSharp {
                protected LocalTemporary temp;
                protected bool emitting_compound_assignment;
                protected bool has_await_arguments;
+               protected Label null_operator_label;
 
                protected PropertyOrIndexerExpr (Location l)
                {
@@ -6485,6 +6735,10 @@ namespace Mono.CSharp {
                                if (expr == null)
                                        return null;
 
+                               if (NullShortCircuit && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
+                                       type = LiftMemberType (ec, type);
+                               }
+
                                if (expr != this)
                                        return expr.Resolve (ec);
                        }
@@ -6497,6 +6751,9 @@ namespace Mono.CSharp {
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
+                       if (NullShortCircuit)
+                               throw new NotSupportedException ("null propagating operator assignment");
+
                        if (right_side == EmptyExpression.OutAccess) {
                                // TODO: best_candidate can be null at this point
                                INamedBlockVariable variable = null;
@@ -6522,7 +6779,15 @@ namespace Mono.CSharp {
 
                        if (!ResolveSetter (ec))
                                return null;
-
+/*
+                       if (NullShortCircuit && ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
+                               var lifted_type = LiftMemberType (ec, type);
+                               if (type != lifted_type) {
+                                       // TODO: Workaround to disable codegen for now
+                                       return Nullable.Wrap.Create (this, lifted_type);
+                               }
+                       }
+*/
                        return this;
                }
 
@@ -6532,6 +6797,7 @@ namespace Mono.CSharp {
                public virtual void Emit (EmitContext ec, bool leave_copy)
                {
                        var call = new CallEmitter ();
+                       call.NullShortCircuit = NullShortCircuit;
                        call.InstanceExpression = InstanceExpression;
                        if (has_await_arguments)
                                call.HasAwaitArguments = true;
@@ -6546,6 +6812,9 @@ namespace Mono.CSharp {
                                has_await_arguments = true;
                        }
 
+                       if (NullShortCircuit && emitting_compound_assignment)
+                               null_operator_label = call.NullOperatorLabel;
+
                        if (leave_copy) {
                                ec.Emit (OpCodes.Dup);
                                temp = new LocalTemporary (Type);
@@ -6769,7 +7038,8 @@ namespace Mono.CSharp {
 
                        var call = new CallEmitter ();
                        call.InstanceExpression = InstanceExpression;
-                       call.Emit (ec, op, args, loc);
+                       call.NullShortCircuit = NullShortCircuit;
+                       call.EmitStatement (ec, op, args, loc);
                }
 
                #endregion