Enable await expressions to work with dynamic binder
[mono.git] / mcs / mcs / class.cs
index f19eaab3e10a6f5bb2e8af00364ce3a0dcb47bc8..c9dd88543849db374d6986df6c4a343541ed7461 100644 (file)
@@ -78,10 +78,6 @@ namespace Mono.CSharp
                                get { return tc; }
                        }
 
-                       public bool HasUnresolvedConstraints {
-                               get { return true; }
-                       }
-
                        public bool IsObsolete {
                                get { return tc.IsObsolete; }
                        }
@@ -103,7 +99,7 @@ namespace Mono.CSharp
                                return tc.GetSignatureForError ();
                        }
 
-                       public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
+                       public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
                        {
                                return null;
                        }
@@ -742,7 +738,7 @@ namespace Mono.CSharp
                                        ExpressionStatement s = fi.ResolveStatement (ec);
                                        if (s == null) {
                                                s = EmptyExpressionStatement.Instance;
-                                       } else if (fi.IsComplexInitializer) {
+                                       } else if (!fi.IsSideEffectFree) {
                                                has_complex_initializer |= true;
                                        }
 
@@ -1134,16 +1130,19 @@ namespace Mono.CSharp
 
                                GenericMethod generic_method;
                                MemberName member_name;
+                               TypeArguments targs = null;
                                if (method.IsGeneric) {
                                        //
                                        // Copy all base generic method type parameters info
                                        //
                                        var hoisted_tparams = method.GenericDefinition.TypeParameters;
-                                       var targs = new TypeArguments ();
                                        var type_params = new TypeParameter[hoisted_tparams.Length];
+                                       targs = new TypeArguments ();
+                                       targs.Arguments = new TypeSpec[type_params.Length];
                                        for (int i = 0; i < type_params.Length; ++i) {
                                                var tp = hoisted_tparams[i];
                                                targs.Add (new TypeParameterName (tp.Name, null, Location));
+                                               targs.Arguments[i] = tp;
                                                type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null);
                                        }
 
@@ -1164,6 +1163,8 @@ namespace Mono.CSharp
 
                                var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
                                mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
+                               if (targs != null)
+                                       mg.SetTypeArguments (rc, targs);
 
                                // Get all the method parameters and pass them as arguments
                                var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
@@ -1219,20 +1220,6 @@ namespace Mono.CSharp
                                        if (!spec.AddInterface (iface_type))
                                                continue;
 
-                                       if (iface_type.IsGeneric && spec.Interfaces != null) {
-                                               foreach (var prev_iface in iface_exprs) {
-                                                       if (prev_iface == iface_type)
-                                                               break;
-
-                                                       if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
-                                                               continue;
-
-                                                       Report.Error (695, Location,
-                                                               "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
-                                                               GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
-                                               }
-                                       }
-
                                        TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
 
                                        // Ensure the base is always setup
@@ -1558,26 +1545,44 @@ namespace Mono.CSharp
                                                // TODO: passing `this' is wrong, should be base type iface instead
                                                TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
 
-                                               // TODO: Location is wrong, it should be unresolved iface expr location
-                                               ConstraintChecker.Check (this, iface_type, Location);
-
                                                if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
                                                        Report.Error (1966, Location,
                                                                "`{0}': cannot implement a dynamic interface `{1}'",
                                                                GetSignatureForError (), iface_type.GetSignatureForError ());
                                                        return false;
                                                }
+
+                                               if (spec.Interfaces != null) {
+                                                       foreach (var prev_iface in iface_exprs) {
+                                                               if (prev_iface == iface_type)
+                                                                       break;
+
+                                                               if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
+                                                                       continue;
+
+                                                               Report.Error (695, Location,
+                                                                       "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
+                                                                       GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
+                                                       }
+                                               }
                                        }
                                }
                        }
 
                        if (base_type != null) {
+                               //
+                               // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
+                               //
                                if (base_type_expr != null) {
                                        ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
                                        if (obsolete_attr != null && !IsObsolete)
                                                AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
 
-                                       ConstraintChecker.Check (this, base_type, base_type_expr.Location);
+                                       if (IsGeneric && base_type.IsAttribute) {
+                                               Report.Error (698, base_type_expr.Location,
+                                                       "A generic type cannot derive from `{0}' because it is an attribute class",
+                                                       base_type.GetSignatureForError ());
+                                       }
                                }
 
                                if (base_type.Interfaces != null) {
@@ -1597,12 +1602,6 @@ namespace Mono.CSharp
                                }
                        }
 
-                       if (type_params != null) {
-                               foreach (var tp in type_params) {
-                                       tp.CheckGenericConstraints ();
-                               }
-                       }
-
                        DefineContainerMembers (constants);
                        DefineContainerMembers (fields);
 
@@ -1744,6 +1743,9 @@ namespace Mono.CSharp
                                if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE)
                                        continue;
 
+                               if ((mc.ModFlags & Modifiers.PARTIAL) != 0)
+                                       continue;
+
                                if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
                                        Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
                                }
@@ -1782,14 +1784,14 @@ namespace Mono.CSharp
                                                        continue;
                                                }
                                                
+                                               if ((f.caching_flags & Flags.IsAssigned) != 0)
+                                                       continue;
+
                                                //
                                                // Only report 649 on level 4
                                                //
                                                if (Report.WarningLevel < 4)
                                                        continue;
-                                               
-                                               if ((f.caching_flags & Flags.IsAssigned) != 0)
-                                                       continue;
 
                                                //
                                                // Don't be pendatic over serializable attributes
@@ -1798,8 +1800,24 @@ namespace Mono.CSharp
                                                        continue;
                                                
                                                Constant c = New.Constantify (f.MemberType, f.Location);
-                                               Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
-                                                       f.GetSignatureForError (), c == null ? "null" : c.GetValueAsLiteral ());
+                                               string value;
+                                               if (c != null) {
+                                                       value = c.GetValueAsLiteral ();
+                                               } else if (TypeSpec.IsReferenceType (f.MemberType)) {
+                                                       value = "null";
+                                               } else {
+                                                       // Ignore this warning for struct value fields (they are always initialized)
+                                                       if (f.MemberType.IsStruct)
+                                                               continue;
+
+                                                       value = null;
+                                               }
+
+                                               if (value != null)
+                                                       value = " `" + value + "'";
+
+                                               Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
+                                                       f.GetSignatureForError (), value);
                                        }
                                }
                        }
@@ -1809,7 +1827,8 @@ namespace Mono.CSharp
                {
                        if (!IsTopLevel) {
                                MemberSpec candidate;
-                               var conflict_symbol = MemberCache.FindBaseMember (this, out candidate);
+                               bool overrides = false;
+                               var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
                                if (conflict_symbol == null && candidate == null) {
                                        if ((ModFlags & Modifiers.NEW) != 0)
                                                Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
@@ -1826,13 +1845,31 @@ namespace Mono.CSharp
                                }
                        }
 
+                       // Run constraints check on all possible generic types
+                       if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
+                               if (base_type != null && base_type_expr != null) {
+                                       ConstraintChecker.Check (this, base_type, base_type_expr.Location);
+                               }
+
+                               if (iface_exprs != null) {
+                                       foreach (var iface_type in iface_exprs) {
+                                               if (iface_type == null)
+                                                       continue;
+
+                                               ConstraintChecker.Check (this, iface_type, Location);   // TODO: Location is wrong
+                                       }
+                               }
+                       }
+
                        if (all_tp_builders != null) {
                                int current_starts_index = CurrentTypeParametersStartIndex;
                                for (int i = 0; i < all_tp_builders.Length; i++) {
                                        if (i < current_starts_index) {
                                                TypeParameters[i].EmitConstraints (all_tp_builders [i]);
                                        } else {
-                                               CurrentTypeParameters [i - current_starts_index].Emit ();
+                                               var tp = CurrentTypeParameters [i - current_starts_index];
+                                               tp.CheckGenericConstraints (!IsObsolete);
+                                               tp.Emit ();
                                        }
                                }
                        }
@@ -1941,7 +1978,7 @@ namespace Mono.CSharp
                        }
 
                        if (pending != null)
-                               pending.VerifyPendingMethods (Report);
+                               pending.VerifyPendingMethods ();
 
                        if (Report.Errors > 0)
                                return;
@@ -2400,18 +2437,19 @@ namespace Mono.CSharp
                        }
                }
 
-               public override IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
+               public override ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
                {
                        DeclSpace top_level = Parent;
                        if (top_level != null) {
-                               var candidates = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity);
-                               if (candidates != null) {
-                                       scope = NamespaceEntry;
-                                       return candidates;
+                               var methods = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity);
+                               if (methods != null) {
+                                       return new ExtensionMethodCandidates (methods, NamespaceEntry, NamespaceEntry.NS) {
+                                               HasUninspectedMembers = true
+                                       };
                                }
                        }
 
-                       return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, ref scope);
+                       return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity);
                }
 
                protected override TypeAttributes TypeAttr {
@@ -2582,10 +2620,6 @@ namespace Mono.CSharp
                                if (base_type.IsGenericParameter){
                                        Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
                                                GetSignatureForError (), base_type.GetSignatureForError ());
-                               } else if (IsGeneric && base_type.IsAttribute) {
-                                       Report.Error (698, base_class.Location,
-                                               "A generic type cannot derive from `{0}' because it is an attribute class",
-                                               base_type.GetSignatureForError ());
                                } else if (base_type.IsStatic) {
                                        Report.SymbolRelatedToPreviousError (base_type);
                                        Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
@@ -2866,7 +2900,7 @@ namespace Mono.CSharp
                /// <summary>
                ///   Modifiers allowed in a class declaration
                /// </summary>
-               public const Modifiers AllowedModifiers =
+               const Modifiers AllowedModifiers =
                        Modifiers.NEW       |
                        Modifiers.PUBLIC    |
                        Modifiers.PROTECTED |
@@ -3034,7 +3068,8 @@ namespace Mono.CSharp
                                return true;
 
                        MemberSpec candidate;
-                       var base_member = FindBaseMember (out candidate);
+                       bool overrides = false;
+                       var base_member = FindBaseMember (out candidate, ref overrides);
 
                        if ((ModFlags & Modifiers.OVERRIDE) != 0) {
                                if (base_member == null) {
@@ -3062,6 +3097,22 @@ namespace Mono.CSharp
                                        return false;
                                }
 
+                               //
+                               // Handles ambiguous overrides
+                               //
+                               if (candidate != null) {
+                                       Report.SymbolRelatedToPreviousError (candidate);
+                                       Report.SymbolRelatedToPreviousError (base_member);
+
+                                       // Get member definition for error reporting
+                                       var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
+                                       var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
+
+                                       Report.Error (462, Location,
+                                               "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
+                                               GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
+                               }
+
                                if (!CheckOverrideAgainstBase (base_member))
                                        return false;
 
@@ -3109,7 +3160,7 @@ namespace Mono.CSharp
                                        }
                                }
 
-                               if (!IsInterface && base_member.IsAbstract && candidate == null) {
+                               if (!IsInterface && base_member.IsAbstract && !overrides) {
                                        Report.SymbolRelatedToPreviousError (base_member);
                                        Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
                                                GetSignatureForError (), base_member.GetSignatureForError ());
@@ -3344,9 +3395,9 @@ namespace Mono.CSharp
                /// <summary>
                /// Gets base method and its return type
                /// </summary>
-               protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate)
+               protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
                {
-                       return MemberCache.FindBaseMember (this, out bestCandidate);
+                       return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
                }
 
                //