Better check for missing dependencies for method overloads. Fixes #4457
authorMarek Safar <marek.safar@gmail.com>
Wed, 18 Apr 2012 17:51:09 +0000 (18:51 +0100)
committerMarek Safar <marek.safar@gmail.com>
Thu, 19 Apr 2012 09:44:57 +0000 (10:44 +0100)
mcs/errors/CS0012-16-lib.il [new file with mode: 0644]
mcs/errors/Makefile
mcs/errors/cs0012-14.cs
mcs/errors/cs0012-16.cs [new file with mode: 0644]
mcs/errors/cs0453-8.cs [new file with mode: 0644]
mcs/mcs/decl.cs
mcs/mcs/ecore.cs
mcs/mcs/generic.cs
mcs/mcs/import.cs
mcs/mcs/method.cs
mcs/mcs/typespec.cs

diff --git a/mcs/errors/CS0012-16-lib.il b/mcs/errors/CS0012-16-lib.il
new file mode 100644 (file)
index 0000000..fc95fe3
--- /dev/null
@@ -0,0 +1,36 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly extern 'CS0012-lib-missing'
+{
+}
+
+.assembly 'CS0012-16-lib'
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+
+.module 'CS0012-16-lib.dll'
+
+.class public auto ansi beforefieldinit B
+       extends [mscorlib]System.Object
+{
+  .method public hidebysig static void  Foo(object o) cil managed
+  {
+    ret
+  }
+
+  .method public hidebysig static void  Foo(class ['CS0012-lib-missing']AA t) cil managed
+  {
+    ret
+  }
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    ret
+  }
+
+}
index 106b90afdef942ea533d855046daaa7ded51ab64..57ff9ef44909738d6632f1a0b9f7145c014f8eeb 100644 (file)
@@ -21,7 +21,7 @@ DISTFILES = \
        $(wildcard dlls/second/*.cs)
 
 TEST_SUPPORT_FILES = \
-       CS0012-lib.dll CS0012-2-lib.dll CS0012-3-lib.dll CS0012-4-lib.dll CS0012-5-lib.dll CS0012-6-lib.dll CS0012-9-lib.dll CS0012-10-lib.dll CS0012-11-lib.dll CS0012-12-lib.dll CS0012-13-lib.dll CS0012-14-lib.dll CS0012-15-lib.dll CS0029-26-lib.dll \
+       CS0012-lib.dll CS0012-2-lib.dll CS0012-3-lib.dll CS0012-4-lib.dll CS0012-5-lib.dll CS0012-6-lib.dll CS0012-9-lib.dll CS0012-10-lib.dll CS0012-11-lib.dll CS0012-12-lib.dll CS0012-13-lib.dll CS0012-14-lib.dll CS0012-15-lib.dll CS0012-16-lib.dll CS0029-26-lib.dll \
        CS0103-2-lib.dll CS0118-2-lib.dll CS0122-10-lib.dll CS0122-14-lib.dll CS0122-15-lib.dll CS0122-19-lib.dll CS0122-35-lib.dll CS0122-36-lib.dll CS0143-lib.dll CS0144-3-lib.dll CS0165-19-lib.dll \
        CS0205-3-lib.dll CS0229-3-lib.dll CS0229-4-lib.dll CS0266-25-lib.dll \
        CS0315-2-lib.dll \
index 83009b108b7ae5d27174c0185c7a7d4998145239..d6c858ae149d95636176195c4b109c58472b4d75 100644 (file)
@@ -1,4 +1,4 @@
-// CS0012: The type `A1' is defined in an assembly that is not referenced. Consider adding a reference to assembly `CS0012-lib-missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+// CS0012: The type `AA' is defined in an assembly that is not referenced. Consider adding a reference to assembly `CS0012-lib-missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
 // Line: 9
 // Compiler options: -r:CS0012-14-lib.dll
 
@@ -6,6 +6,6 @@ class Test
 {
        public static void Main ()
        {
-               B.Foo (null);
+               B.Foo (new Test ());
        }
 }
diff --git a/mcs/errors/cs0012-16.cs b/mcs/errors/cs0012-16.cs
new file mode 100644 (file)
index 0000000..bf71e94
--- /dev/null
@@ -0,0 +1,11 @@
+// CS0012: The type `AA' is defined in an assembly that is not referenced. Consider adding a reference to assembly `CS0012-lib-missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+// Line: 9
+// Compiler options: -r:CS0012-16-lib.dll
+
+class Test
+{
+       public static void Main ()
+       {
+               B.Foo (new Test ());
+       }
+}
diff --git a/mcs/errors/cs0453-8.cs b/mcs/errors/cs0453-8.cs
new file mode 100644 (file)
index 0000000..f94f320
--- /dev/null
@@ -0,0 +1,16 @@
+// CS0453: The type `dynamic' must be a non-nullable value type in order to use it as type parameter `T' in the generic type or method `Tester.Foo<T>(T)'
+// Line: 10
+
+class Tester
+{
+       static void Foo<T> (T t) where T : struct
+       {
+       }
+       
+       public static int Main ()
+       {
+               dynamic d = 1;
+               Foo<dynamic>(d);
+               return 0;
+       }
+}
index fdfb20c59cf6c9833e580bbf1e64dc03b6a2aaf3..703cd949bf75bf2756949d4690fdc95de07285b4 100644 (file)
@@ -939,6 +939,15 @@ namespace Mono.CSharp {
                        GenericTask = 1 << 22
                }
 
+               //
+               // Some flags can be copied directly from other member
+               //
+               protected const StateFlags SharedStateFlags =
+                       StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected |
+                       StateFlags.Obsolete | StateFlags.Obsolete_Undetected |
+                       StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected |
+                       StateFlags.HasDynamicElement;
+
                protected Modifiers modifiers;
                public StateFlags state;
                protected IMemberDefinition definition;
index 2ae9bcd2f9a471397b4dda4c82234bda19baedd5..bdf67dc2b617812488b99514da559ea2757a3814 100644 (file)
@@ -4046,6 +4046,7 @@ namespace Mono.CSharp {
                //
                // A return value rates candidate method compatibility,
                // 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)
                {
@@ -4167,6 +4168,18 @@ namespace Mono.CSharp {
                                arg_count = arguments.Count;
                        }
 
+                       //
+                       // Don't do any expensive checks when the candidate cannot succeed
+                       //
+                       if (arg_count != param_count && !cpd.HasParams)
+                               return (param_count - arg_count) * 2 + 1;
+
+                       var dep = candidate.GetMissingDependencies ();
+                       if (dep != null) {
+                               ImportedTypeDefinition.Error_MissingDependency (ec, dep, loc);
+                               return -1;
+                       }
+
                        //
                        // 1. Handle generic method using type arguments when specified or type inference
                        //
@@ -4559,6 +4572,11 @@ namespace Mono.CSharp {
                                                // How does it score compare to others
                                                //
                                                if (candidate_rate < best_candidate_rate) {
+
+                                                       // Fatal error (missing dependency), cannot continue
+                                                       if (candidate_rate < 0)
+                                                               return null;
+
                                                        best_candidate_rate = candidate_rate;
                                                        best_candidate = member;
                                                        best_candidate_args = candidate_args;
@@ -4739,11 +4757,6 @@ namespace Mono.CSharp {
                        if (oa != null && !rc.IsObsolete)
                                AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report);
 
-                       var dep = best_candidate.GetMissingDependencies ();
-                       if (dep != null) {
-                               ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc);
-                       }
-
                        best_candidate.MemberDefinition.SetIsUsed ();
 
                        args = best_candidate_args;
index 1a3c646ae3631a3282d14f30431544dbd8eafbe9..ee40532d258940fdcebd8e33eafb874913774beb 100644 (file)
@@ -1482,7 +1482,9 @@ namespace Mono.CSharp {
                        if (targs == null)
                                throw new ArgumentNullException ("targs");
 
-//                     this.state = openType.state;
+                       this.state &= ~SharedStateFlags;
+                       this.state |= (openType.state & SharedStateFlags);
+
                        this.context = context;
                        this.open_type = openType;
                        this.targs = targs;
@@ -2332,15 +2334,6 @@ namespace Mono.CSharp {
                        // Check the class constraint
                        //
                        if (tparam.HasTypeConstraint) {
-                               var dep = tparam.BaseType.GetMissingDependencies ();
-                               if (dep != null) {
-                                       if (mc == null)
-                                               return false;
-
-                                       ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
-                                       ok = false;
-                               }
-
                                if (!CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc)) {
                                        if (mc == null)
                                                return false;
@@ -2354,19 +2347,6 @@ namespace Mono.CSharp {
                        //
                        if (tparam.Interfaces != null) {
                                foreach (TypeSpec iface in tparam.Interfaces) {
-                                       var dep = iface.GetMissingDependencies ();
-                                       if (dep != null) {
-                                               if (mc == null)
-                                                       return false;
-
-                                               ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
-                                               ok = false;
-
-                                               // return immediately to avoid duplicate errors because we are scanning
-                                               // expanded interface list
-                                               return false;
-                                       }
-
                                        if (!CheckConversion (mc, context, atype, tparam, iface, loc)) {
                                                if (mc == null)
                                                        return false;
index bcf5a68c7a366d79f76b291b8624794b2a945d33..da3e3d7c708b58de7621518b23a541139a05049d 100644 (file)
@@ -1802,7 +1802,15 @@ namespace Mono.CSharp
                        // or referenced from the user core in which case compilation error has to
                        // be reported because compiler cannot continue anyway
                        //
-                       foreach (var t in types) {
+                       for (int i = 0; i < types.Count; ++i) {
+                               var t = types [i];
+
+                               //
+                               // Report missing types only once per type
+                               //
+                               if (i > 0 && types.IndexOf (t) < i)
+                                       continue;
+
                                string name = t.GetSignatureForError ();
 
                                if (t.MemberDefinition.DeclaringAssembly == ctx.Module.DeclaringAssembly) {
index b00f3f0bc070abffdff2e929894e7c3ac819c229..193b9565b392831dfa95f85514784b90dfcabf49 100644 (file)
@@ -496,6 +496,20 @@ namespace Mono.CSharp {
                                missing.AddRange (m);
                        }
 
+                       if (Arity > 0) {
+                               foreach (var tp in GenericDefinition.TypeParameters) {
+                                       var m = tp.GetMissingDependencies ();
+
+                                       if (m == null)
+                                               continue;
+
+                                       if (missing == null)
+                                               missing = new List<TypeSpec> ();
+
+                                       missing.AddRange (m);
+                               }
+                       }
+
                        return missing;                 
                }
 
index 7ad55a4be453bc8664a28c5ff286a488994a9e48..5df85f770f981db1648a67ee55becf6fe0aa5c4d 100644 (file)
@@ -721,6 +721,18 @@ namespace Mono.CSharp
                                }
                        }
 
+                       if (MemberDefinition.TypeParametersCount > 0) {
+                               foreach (var tp in MemberDefinition.TypeParameters) {
+                                       var tp_missing = tp.GetMissingDependencies ();
+                                       if (tp_missing != null) {
+                                               if (missing == null)
+                                                       missing = new List<TypeSpec> ();
+
+                                               missing.AddRange (tp_missing);
+                                       }
+                               }
+                       }
+
                        if (missing != null || BaseType == null)
                                return missing;
 
@@ -1333,7 +1345,7 @@ namespace Mono.CSharp
                        cache = MemberCache.Empty;
 
                        // Make all internal types CLS-compliant, non-obsolete
-                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant;
+                       state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant;
                }
 
                #region Properties
@@ -1454,11 +1466,8 @@ namespace Mono.CSharp
                {
                        this.Element = element;
 
-                       // Some flags can be copied directly from the element
-                       const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected
-                               | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement;
-                       state &= ~shared_flags;
-                       state |= (element.state & shared_flags);
+                       state &= ~SharedStateFlags;
+                       state |= (element.state & SharedStateFlags);
 
                        if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
                                state |= StateFlags.HasDynamicElement;