[mcs] Allow properties and indexers of by-ref values to be set without setter
[mono.git] / mcs / mcs / ecore.cs
index 42eba97ee475763eb15186ea8a25bbe36fc1fca9..34ff9a30dab3cb423f4b9f64b7a7640d67a2b56a 100644 (file)
@@ -45,7 +45,7 @@ namespace Mono.CSharp {
                PropertyAccess,
                EventAccess,
                IndexerAccess,
-               Nothing, 
+               Nothing,
        }
 
        /// <remarks>
@@ -239,6 +239,15 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               protected void CheckExpressionVariable (ResolveContext rc)
+               {
+                       if (rc.HasAny (ResolveContext.Options.BaseInitializer | ResolveContext.Options.FieldInitializerScope)) {
+                               rc.Report.Error (8200, loc, "Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers");
+                       } else if (rc.HasSet (ResolveContext.Options.QueryClauseScope)) {
+                               rc.Report.Error (8201, loc, "Out variable and pattern variable declarations are not allowed within a query clause");
+                       }
+               }
+
                public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
                {
                        rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
@@ -294,7 +303,12 @@ namespace Mono.CSharp {
                                return;
 
                        string from_type = type.GetSignatureForError ();
+                       if (type.Kind == MemberKind.ByRef)
+                               from_type = "ref " + from_type;
                        string to_type = target.GetSignatureForError ();
+                       if (target.Kind == MemberKind.ByRef)
+                               to_type = "ref " + to_type;
+
                        if (from_type == to_type) {
                                from_type = type.GetSignatureForErrorIncludingAssemblyName ();
                                to_type = target.GetSignatureForErrorIncludingAssemblyName ();
@@ -550,18 +564,18 @@ namespace Mono.CSharp {
                public Expression ResolveLValue (ResolveContext ec, Expression right_side)
                {
                        int errors = ec.Report.Errors;
-                       bool out_access = right_side == EmptyExpression.OutAccess;
+                       //bool out_access = right_side == EmptyExpression.OutAccess;
 
                        Expression e = DoResolveLValue (ec, right_side);
 
-                       if (e != null && out_access && !(e is IMemoryLocation)) {
+                       //if (e != null && out_access && !(e is IMemoryLocation)) {
                                // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
                                //        Enabling this 'throw' will "only" result in deleting useless code elsewhere,
 
                                //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
                                //                                e.GetType () + " " + e.GetSignatureForError ());
-                               e = null;
-                       }
+                       //      e = null;
+                       //}
 
                        if (e == null) {
                                if (errors == ec.Report.Errors) {
@@ -638,6 +652,10 @@ namespace Mono.CSharp {
                        ec.Emit (OpCodes.Pop);
                }
 
+               public virtual void EmitPrepare (EmitContext ec)
+               {
+               }
+
                //
                // Emits the expression into temporary field variable. The method
                // should be used for await expressions only
@@ -841,22 +859,38 @@ namespace Mono.CSharp {
                public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
                {
                        var members = MemberCache.FindMembers (queried_type, name, false);
-                       if (members == null)
-                               return null;
 
-                       Expression expr;
-                       do {
-                               expr = MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
-                               if (expr != null)
-                                       return expr;
+                       if (members != null) {
+                               Expression expr;
+                               do {
+                                       expr = MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
+                                       if (expr != null)
+                                               return expr;
 
-                               if (members [0].DeclaringType.BaseType == null)
-                                       members = null;
-                               else
-                                       members = MemberCache.FindMembers (members [0].DeclaringType.BaseType, name, false);
-                       } while (members != null);
+                                       if (members [0].DeclaringType.BaseType == null)
+                                               members = null;
+                                       else
+                                               members = MemberCache.FindMembers (members [0].DeclaringType.BaseType, name, false);
+                               } while (members != null);
+                       }
+
+                       var tps = queried_type as TypeParameterSpec;
+                       if (tps != null) {
+                               members = MemberCache.FindInterfaceMembers (tps, name);
+                               if (members != null)
+                                       return MemberLookupToExpression (rc, members, errorMode, queried_type, name, arity, restrictions, loc);
+                       }
 
-                       return expr;
+                       if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+                               var ntuple = queried_type as NamedTupleSpec;
+                               if (ntuple != null) {
+                                       var ms = ntuple.FindElement (rc, name, loc);
+                                       if (ms != null)
+                                               return ExprClassFromMemberInfo (ms, loc);
+                               }
+                       }
+
+                       return null;
                }
 
                public static Expression MemberLookupToExpression (IMemberContext rc, IList<MemberSpec> members, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
@@ -901,15 +935,6 @@ namespace Mono.CSharp {
 
                                if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
                                        if (member is MethodSpec) {
-                                               //
-                                               // Interface members that are hidden by class members are removed from the set. This
-                                               // step only has an effect if T is a type parameter and T has both an effective base 
-                                               // class other than object and a non-empty effective interface set
-                                               //
-                                               var tps = queried_type as TypeParameterSpec;
-                                               if (tps != null && tps.HasTypeConstraint)
-                                                       members = RemoveHiddenTypeParameterMethods (members);
-
                                                return new MethodGroupExpr (members, queried_type, loc);
                                        }
 
@@ -959,57 +984,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               static IList<MemberSpec> RemoveHiddenTypeParameterMethods (IList<MemberSpec> members)
-               {
-                       if (members.Count < 2)
-                               return members;
-
-                       //
-                       // If M is a method, then all non-method members declared in an interface declaration
-                       // are removed from the set, and all methods with the same signature as M declared in
-                       // an interface declaration are removed from the set
-                       //
-
-                       bool copied = false;
-                       for (int i = 0; i < members.Count; ++i) {
-                               var method = members[i] as MethodSpec;
-                               if (method == null) {
-                                       if (!copied) {
-                                               copied = true;
-                                               members = new List<MemberSpec> (members);
-                                       } 
-                                       
-                                       members.RemoveAt (i--);
-                                       continue;
-                               }
-
-                               if (!method.DeclaringType.IsInterface)
-                                       continue;
-
-                               for (int ii = 0; ii < members.Count; ++ii) {
-                                       var candidate = members[ii] as MethodSpec;
-                                       if (candidate == null || !candidate.DeclaringType.IsClass)
-                                               continue;
-
-                                       if (!TypeSpecComparer.Override.IsEqual (candidate.Parameters, method.Parameters))
-                                               continue;
-
-                                       if (!AParametersCollection.HasSameParameterDefaults (candidate.Parameters, method.Parameters))
-                                               continue;
-
-                                       if (!copied) {
-                                               copied = true;
-                                               members = new List<MemberSpec> (members);
-                                       }
-
-                                       members.RemoveAt (i--);
-                                       break;
-                               }
-                       }
-
-                       return members;
-               }
-
                protected static void Error_NamedArgument (NamedArgument na, Report Report)
                {
                        Report.Error (1742, na.Location, "An element access expression cannot use named argument");
@@ -1048,6 +1022,11 @@ namespace Mono.CSharp {
                {
                }
 
+               public virtual Reachability MarkReachable (Reachability rc)
+               {
+                       return rc;
+               }
+
                //
                // Special version of flow analysis for expressions which can return different
                // on-true and on-false result. Used by &&, ||, ?: expressions
@@ -1183,6 +1162,16 @@ namespace Mono.CSharp {
                        Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
                }
 
+               public static void UnsafeInsideIteratorError (ResolveContext rc, Location loc)
+               {
+                       UnsafeInsideIteratorError (rc.Report, loc);
+               }
+
+               public static void UnsafeInsideIteratorError (Report report, Location loc)
+               {
+                       report.Error (1629, loc, "Unsafe code may not appear in iterators");
+               }
+
                //
                // Converts `source' to an int, uint, long or ulong.
                //
@@ -1338,10 +1327,6 @@ namespace Mono.CSharp {
        /// </summary>
        public abstract class ExpressionStatement : Expression
        {
-               public virtual void MarkReachable (Reachability rc)
-               {
-               }
-
                public virtual ExpressionStatement ResolveStatement (BlockContext ec)
                {
                        Expression e = Resolve (ec);
@@ -1503,6 +1488,11 @@ namespace Mono.CSharp {
 #endif
                }
 
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       return child.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        // Nothing to clone
@@ -2444,13 +2434,23 @@ namespace Mono.CSharp {
 
                public override void FlowAnalysis (FlowAnalysisContext fc)
                {
-                       expr.FlowAnalysis (fc);
+                       orig_expr.FlowAnalysis (fc);
+               }
+
+               public override void FlowAnalysisConditional (FlowAnalysisContext fc)
+               {
+                       orig_expr.FlowAnalysisConditional (fc);
                }
 
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        return orig_expr.MakeExpression (ctx);
                }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       return expr.MarkReachable (rc);
+               }
        }
 
        //
@@ -2805,9 +2805,13 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               public bool IsPossibleTypeOrNamespace (IMemberContext mc)
+               bool IsPossibleTypeOrNamespace (IMemberContext mc)
                {
-                       return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) != null;
+                       //
+                       // Has to ignore static usings because we are looking for any member not just type
+                       // in this context
+                       //
+                       return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing | LookupMode.IgnoreStaticUsing, loc) != null;
                }
 
                public bool IsPossibleType (IMemberContext mc)
@@ -2929,6 +2933,15 @@ namespace Mono.CSharp {
                                        return me;
                                }
 
+                               //
+                               // Stage 3: Lookup nested types, namespaces and type parameters in the context
+                               //
+                               if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
+                                       if (IsPossibleTypeOrNamespace (rc)) {
+                                               return ResolveAsTypeOrNamespace (rc, false);
+                                       }
+                               }
+
                                var expr = NamespaceContainer.LookupStaticUsings (rc, Name, Arity, loc);
                                if (expr != null) {
                                        if (Arity > 0) {
@@ -2941,15 +2954,6 @@ namespace Mono.CSharp {
                                        return expr;
                                }
 
-                               //
-                               // Stage 3: Lookup nested types, namespaces and type parameters in the context
-                               //
-                               if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
-                                       if (IsPossibleTypeOrNamespace (rc)) {
-                                               return ResolveAsTypeOrNamespace (rc, false);
-                                       }
-                               }
-
                                if ((restrictions & MemberLookupRestrictions.NameOfExcluded) == 0 && Name == "nameof")
                                        return new NameOf (this);
 
@@ -3405,6 +3409,8 @@ namespace Mono.CSharp {
                                // introduce redundant storey but with `this' only but it's tricky to avoid
                                // at this stage as we don't know what expressions follow base
                                //
+                               // TODO: It's needed only when the method with base call is moved to a storey
+                               //
                                if (rc.CurrentAnonymousMethod != null) {
                                        if (targs == null && method.IsGeneric) {
                                                targs = method.TypeArguments;
@@ -3507,8 +3513,12 @@ namespace Mono.CSharp {
                                CheckProtectedMemberAccess (rc, member);
                        }
 
-                       if (member.MemberType.IsPointer && !rc.IsUnsafe) {
-                               UnsafeError (rc, loc);
+                       if (member.MemberType.IsPointer) {
+                               if (rc.CurrentIterator != null) {
+                                       UnsafeInsideIteratorError (rc, loc);
+                               } else if (!rc.IsUnsafe) {
+                                       UnsafeError (rc, loc);
+                               }
                        }
 
                        var dep = member.GetMissingDependencies ();
@@ -3701,6 +3711,11 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public virtual void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+               {
+
+               }
+
                protected void EmitInstance (EmitContext ec, bool prepare_for_load)
                {
                        var inst = new InstanceEmitter (InstanceExpression, TypeSpec.IsValueType (InstanceExpression.Type));
@@ -3776,7 +3791,7 @@ namespace Mono.CSharp {
                // For extension methodgroup we are not looking for base members but parent
                // namespace extension methods
                //
-               public override IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+               public override IList<MemberSpec> GetBaseMembers (TypeSpec type)
                {
                        // TODO: candidates are null only when doing error reporting, that's
                        // incorrect. We have to discover same extension methods in error mode
@@ -3805,27 +3820,9 @@ namespace Mono.CSharp {
                                Convert.ImplicitBoxingConversion (null, argType, extensionType) != null;
                }
 
-               public bool ResolveNameOf (ResolveContext rc, MemberAccess ma)
+               public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
                {
-                       rc.Report.Error (8093, ma.Location, "An argument to nameof operator cannot be extension method group");
-
-                       // Not included in C#6
-                       /*
-                       ExtensionExpression = ExtensionExpression.Resolve (rc);
-                       if (ExtensionExpression == null)
-                               return false;
-
-                       var argType = ExtensionExpression.Type;
-                       foreach (MethodSpec candidate in Candidates) {
-                               if (ExtensionMethodGroupExpr.IsExtensionTypeCompatible (argType, candidate.Parameters.ExtensionMethodType))
-                                       return true;
-                       }
-
-                       // TODO: Scan full hierarchy
-
-                       ma.Error_TypeDoesNotContainDefinition (rc, argType, ma.Name);
-                       */
-                       return false;
+                       rc.Report.Error (8093, expr.Location, "An argument to nameof operator cannot be extension method group");
                }
 
                public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
@@ -4067,6 +4064,11 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ();
                }
 
+               public override void EmitPrepare (EmitContext ec)
+               {
+                       InstanceExpression?.EmitPrepare (ec);
+               }
+
                public void EmitCall (EmitContext ec, Arguments arguments, bool statement)
                {
                        var call = new CallEmitter ();
@@ -4226,6 +4228,17 @@ namespace Mono.CSharp {
                        return base.ResolveMemberAccess (ec, left, original);
                }
 
+               public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+               {
+                       if (!HasAccessibleCandidate (rc)) {
+                               ErrorIsInaccesible (rc, expr.GetSignatureForError (), loc);
+                       }
+
+                       if (expr.HasTypeArguments) {
+                               rc.Report.Error (8084, expr.Location, "An argument to nameof operator cannot be method group with type arguments");
+                       }
+               }
+
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
                        type_arguments = ta;
@@ -4233,9 +4246,19 @@ namespace Mono.CSharp {
 
                #region IBaseMembersProvider Members
 
-               public virtual IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+               public virtual IList<MemberSpec> GetBaseMembers (TypeSpec type)
                {
-                       return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
+                       var baseType = type.BaseType;
+                       
+                       IList<MemberSpec> members = baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
+
+                       if (members == null && !type.IsInterface) {
+                               var tps = queried_type as TypeParameterSpec;
+                               if (tps != null)
+                                       members = MemberCache.FindInterfaceMembers (tps, Methods [0].Name);
+                       }
+
+                       return members;
                }
 
                public IParametersMember GetOverrideMemberParameters (MemberSpec member)
@@ -4826,12 +4849,18 @@ namespace Mono.CSharp {
 
                                //
                                // A candidate with no default parameters is still better when there
-                               // is no better expression conversion
+                               // is no better expression conversion and does not have more parameters
                                //
                                if (candidate_pd.Count < best_pd.Count) {
-                                       if (!candidate_params && !candidate_pd.FixedParameters [j - j].HasDefaultValue) {
+                                       if (candidate_params)
+                                               return false;
+                                       
+                                       if (!candidate_pd.FixedParameters [j - 1].HasDefaultValue)
                                                return true;
-                                       }
+
+                                       if (best_pd.FixedParameters [j].HasDefaultValue)
+                                               return true;
+                                       
                                } else if (candidate_pd.Count == best_pd.Count) {
                                        if (candidate_params)
                                                return false;
@@ -5095,7 +5124,7 @@ namespace Mono.CSharp {
 
                                                                // The slot has been taken by positional argument
                                                                if (temp != null && !(temp is NamedArgument))
-                                                                       break;
+                                                                       return NamedArgumentsMismatch - i - 1;
                                                        }
 
                                                        if (!arg_moved) {
@@ -5267,7 +5296,7 @@ namespace Mono.CSharp {
                                                if ((fp.ModFlags & Parameter.Modifier.CallerLineNumber) != 0) {
                                                        e = new IntLiteral (ec.BuiltinTypes, loc.Row, loc);
                                                } else if ((fp.ModFlags & Parameter.Modifier.CallerFilePath) != 0) {
-                                                       e = new StringLiteral (ec.BuiltinTypes, loc.NameFullPath, loc);
+                                                       e = new StringLiteral (ec.BuiltinTypes, loc.SourceFile.GetFullPathName (ec.Module.Compiler.Settings.PathMap), loc);
                                                } else if (ec.MemberContext.CurrentMemberDefinition != null) {
                                                        e = new StringLiteral (ec.BuiltinTypes, ec.MemberContext.CurrentMemberDefinition.GetCallerMemberName (), loc);
                                                }
@@ -5393,6 +5422,11 @@ namespace Mono.CSharp {
                                        if (arg_type == InternalType.VarOutType)
                                                return 0;
 
+                                       var ref_arg_type = arg_type as ReferenceContainer;
+                                       if (ref_arg_type != null) {
+                                               arg_type = ref_arg_type.Element;
+                                       }
+
                                        //
                                        // Do full equality check after quick path
                                        //
@@ -5425,10 +5459,8 @@ namespace Mono.CSharp {
 
                static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q)
                {
-                       if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
-                               return q;
-                       if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
-                               return p;
+                       if (p.IsGenericParameter != q.IsGenericParameter)
+                               return p.IsGenericParameter ? q : p;
 
                        var ac_p = p as ArrayContainer;
                        if (ac_p != null) {
@@ -5441,18 +5473,22 @@ namespace Mono.CSharp {
                                        return p;
                                if (specific == ac_q.Element)
                                        return q;
-                       } else if (p.IsGeneric && q.IsGeneric) {
-                               var pargs = TypeManager.GetTypeArguments (p);
-                               var qargs = TypeManager.GetTypeArguments (q);
+
+                               return null;
+                       }
+
+                       if (p.IsGeneric && q.IsGeneric) {
+                               var pargs = p.TypeArguments;
+                               var qargs = q.TypeArguments;
 
                                bool p_specific_at_least_once = false;
                                bool q_specific_at_least_once = false;
 
                                for (int i = 0; i < pargs.Length; i++) {
-                                       TypeSpec specific = MoreSpecific (pargs[i], qargs[i]);
-                                       if (specific == pargs[i])
+                                       TypeSpec specific = MoreSpecific (pargs [i], qargs [i]);
+                                       if (specific == pargs [i])
                                                p_specific_at_least_once = true;
-                                       if (specific == qargs[i])
+                                       if (specific == qargs [i])
                                                q_specific_at_least_once = true;
                                }
 
@@ -5632,7 +5668,7 @@ namespace Mono.CSharp {
                                                // Restore expanded arguments
                                                candidate_args = args;
                                        }
-                               } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
+                               } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType)) != null);
 
                                //
                                // We've found exact match
@@ -5956,13 +5992,13 @@ namespace Mono.CSharp {
                        int arg_count = args == null ? 0 : args.Count;
 
                        for (; a_idx < arg_count; a_idx++, ++a_pos) {
-                               a = args[a_idx];
+                               a = args [a_idx];
                                if (a == null)
                                        continue;
 
                                if (p_mod != Parameter.Modifier.PARAMS) {
                                        p_mod = cpd.FixedParameters [a_idx].ModFlags;
-                                       pt = ptypes[a_idx];
+                                       pt = ptypes [a_idx];
                                        has_unsafe_arg |= pt.IsPointer;
 
                                        if (p_mod == Parameter.Modifier.PARAMS) {
@@ -5992,6 +6028,14 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
+                                       var ref_arg_type = arg_type as ReferenceContainer;
+                                       if (ref_arg_type != null) {
+                                               if (ref_arg_type.Element != pt)
+                                                       break;
+
+                                               return true;
+                                       }
+
                                        if (!TypeSpecComparer.IsEqual (arg_type, pt))
                                                break;
                                }
@@ -6112,8 +6156,12 @@ namespace Mono.CSharp {
                                arg_count++;
                        }
 
-                       if (has_unsafe_arg && !ec.IsUnsafe) {
-                               Expression.UnsafeError (ec, loc);
+                       if (has_unsafe_arg) {
+                               if (ec.CurrentIterator != null) {
+                                       Expression.UnsafeInsideIteratorError (ec, loc);
+                               } else if (!ec.IsUnsafe) {
+                                       Expression.UnsafeError (ec, loc);
+                               }
                        }
 
                        //
@@ -6196,6 +6244,11 @@ namespace Mono.CSharp {
                        return constant.GetSignatureForError ();
                }
 
+               public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+               {
+                       constant.CheckObsoleteness (rc, expr.Location);
+               }
+
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
                        Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc);
@@ -6425,6 +6478,11 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+               {
+                       spec.CheckObsoleteness (rc, expr.Location);
+               }
+
                public void SetFieldAssigned (FlowAnalysisContext fc)
                {
                        if (!IsInstance)
@@ -6485,12 +6543,12 @@ namespace Mono.CSharp {
                                                GetSignatureForError ());
                                }
 
-                               return null;
+                               return ErrorExpression.Instance;
                        }
 
                        if (right_side == EmptyExpression.LValueMemberAccess) {
                                // Already reported as CS1648/CS1650
-                               return null;
+                               return ErrorExpression.Instance;
                        }
 
                        if (right_side == EmptyExpression.LValueMemberOutAccess) {
@@ -6501,7 +6559,7 @@ namespace Mono.CSharp {
                                        rc.Report.Error (1649, loc, "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
                                                GetSignatureForError ());
                                }
-                               return null;
+                               return ErrorExpression.Instance;
                        }
 
                        if (IsStatic) {
@@ -6512,7 +6570,7 @@ namespace Mono.CSharp {
                                        GetSignatureForError ());
                        }
 
-                       return null;
+                       return ErrorExpression.Instance;
                }
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
@@ -7032,7 +7090,7 @@ namespace Mono.CSharp {
                public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
                {
                        if (backing_field != null) {
-                               backing_field.EmitAssign (ec, source, false, false);
+                               backing_field.EmitAssign (ec, source, leave_copy, false);
                                return;
                        }
 
@@ -7195,6 +7253,14 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+               {
+                       if (!best_candidate.IsAccessible (rc))
+                               ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), expr.Location);
+
+                       best_candidate.CheckObsoleteness (rc, expr.Location);
+               }
+
                public void SetBackingFieldAssigned (FlowAnalysisContext fc)
                {
                        if (backing_field != null) {
@@ -7293,6 +7359,15 @@ namespace Mono.CSharp {
                                Error_NullPropagatingLValue (rc);
 
                        if (right_side == EmptyExpression.OutAccess) {
+                               if (best_candidate?.MemberType.Kind == MemberKind.ByRef) {
+                                       if (Arguments?.ContainsEmitWithAwait () == true) {
+                                               rc.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference",
+                                                       GetSignatureForError ());
+                                       }
+
+                                       return this;
+                               }
+
                                // TODO: best_candidate can be null at this point
                                INamedBlockVariable variable = null;
                                if (best_candidate != null && rc.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, rc.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
@@ -7319,6 +7394,11 @@ namespace Mono.CSharp {
                                if (ResolveAutopropertyAssignment (rc, right_side))
                                        return this;
 
+                               if (best_candidate.MemberType.Kind == MemberKind.ByRef) {
+                                       getter = CandidateToBaseOverride (rc, best_candidate.Get);
+                                       return ByRefDereference.Create(this).Resolve(rc);
+                               }
+
                                rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
                                        GetSignatureForError ());
                                return null;
@@ -7616,6 +7696,11 @@ namespace Mono.CSharp {
                        return TypeManager.CSharpSignature (spec);
                }
 
+               public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
+               {
+                       spec.CheckObsoleteness (rc, expr.Location);
+               }
+
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
                        Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc);
@@ -7764,13 +7849,14 @@ namespace Mono.CSharp {
                {
                }
 
-               public bool InferType (ResolveContext ec, Expression right_side)
+               public bool InferType (ResolveContext ec, Expression rhs)
                {
                        if (type != null)
                                throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
                        
-                       type = right_side.Type;
-                       if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+                       type = rhs.Type;
+
+                       if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || (rhs is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
                                ec.Report.Error (815, loc,
                                        "An implicitly typed local variable declaration cannot be initialized with `{0}'",
                                        type.GetSignatureForError ());