Update lower/upper type inference fixing to match the latest C# standard. Fixes ...
authorMarek Safar <marek.safar@gmail.com>
Sun, 27 Oct 2013 20:37:34 +0000 (21:37 +0100)
committerMarek Safar <marek.safar@gmail.com>
Sun, 27 Oct 2013 20:37:34 +0000 (21:37 +0100)
mcs/mcs/generic.cs
mcs/tests/gtest-variance-11.cs
mcs/tests/ver-il-net_4_5.xml

index 96d88b544f2fc70bf7467d2389a25582e07b0169..5a24c6898b5f8d0744eef1d11519e4320171d818 100644 (file)
@@ -3142,87 +3142,100 @@ namespace Mono.CSharp {
                        }
 
                        //
-                       // Determines a unique type from which there is
-                       // a standard implicit conversion to all the other
-                       // candidate types.
+                       // The set of candidate types Uj starts out as the set of
+                       // all types in the set of bounds for Xi
                        //
-                       TypeSpec best_candidate = null;
-                       int cii;
-                       int candidates_count = candidates.Count;
-                       for (int ci = 0; ci < candidates_count; ++ci) {
-                               BoundInfo bound = candidates [ci];
-                               for (cii = 0; cii < candidates_count; ++cii) {
-                                       if (cii == ci)
-                                               continue;
+                       var applicable = new bool [candidates.Count];
+                       for (int ci = 0; ci < applicable.Length; ++ci)
+                               applicable [ci] = true;
+
+                       for (int ci = 0; ci < applicable.Length; ++ci) {
+                               var bound = candidates [ci];
+                               int cii = 0;
+
+                               switch (bound.Kind) {
+                               case BoundKind.Exact:
+                                       for (; cii != applicable.Length; ++cii) {
+                                               if (ci == cii)
+                                                       continue;
 
-                                       BoundInfo cbound = candidates[cii];
-                                       
-                                       // Same type parameters with different bounds
-                                       if (cbound.Type == bound.Type) {
-                                               if (bound.Kind != BoundKind.Exact)
-                                                       bound = cbound;
+                                               if (!applicable[cii])
+                                                       break;
 
-                                               continue;
+                                               //
+                                               // For each exact bound U of Xi all types Uj which are not identical
+                                               // to U are removed from the candidate set
+                                               //
+                                               if (candidates [cii].Type != bound.Type)
+                                                       applicable[cii] = false;
                                        }
 
-                                       if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) {
-                                               if (cbound.Kind == BoundKind.Lower) {
-                                                       if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
-                                                               break;
-                                                       }
-
+                                       break;
+                               case BoundKind.Lower:
+                                       for (; cii != applicable.Length; ++cii) {
+                                               if (ci == cii)
                                                        continue;
-                                               }
-                                               if (cbound.Kind == BoundKind.Upper) {
-                                                       if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                               break;
-                                                       }
 
-                                                       continue;
+                                               if (!applicable[cii])
+                                                       break;
+
+                                               //
+                                               // For each lower bound U of Xi all types Uj to which there is not an implicit conversion
+                                               // from U are removed from the candidate set
+                                               //
+                                               if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), candidates [cii].Type)) {
+                                                       applicable[cii] = false;
                                                }
-                                               
-                                               if (bound.Kind != BoundKind.Exact) {
-                                                       if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                               break;
-                                                       }
+                                       }
+
+                                       break;
 
-                                                       bound = cbound;
+                               case BoundKind.Upper:
+                                       for (; cii != applicable.Length; ++cii) {
+                                               if (ci == cii)
                                                        continue;
-                                               }
-                                               
-                                               break;
+
+                                               if (!applicable[cii])
+                                                       break;
+
+                                               //
+                                               // For each upper bound U of Xi all types Uj from which there is not an implicit conversion
+                                               // to U are removed from the candidate set
+                                               //
+                                               if (!Convert.ImplicitConversionExists (ec, candidates[cii].GetTypeExpression (), bound.Type))
+                                                       applicable[cii] = false;
                                        }
 
-                                       if (bound.Kind == BoundKind.Lower) {
-                                               if (cbound.Kind == BoundKind.Lower) {
-                                                       if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
-                                                               break;
-                                                       }
-                                               } else {
-                                                       if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                               break;
-                                                       }
+                                       break;
+                               }
+                       }
 
-                                                       bound = cbound;
-                                               }
+                       TypeSpec best_candidate = null;
+                       for (int ci = 0; ci < applicable.Length; ++ci) {
+                               if (!applicable[ci])
+                                       continue;
 
+                               var bound = candidates [ci];
+                               if (bound.Type == best_candidate)
+                                       continue;
+
+                               int cii = 0;
+                               for (; cii < applicable.Length; ++cii) {
+                                       if (ci == cii)
                                                continue;
-                                       }
 
-                                       if (bound.Kind == BoundKind.Upper) {
-                                               if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
-                                                       break;
-                                               }
-                                       } else {
-                                               throw new NotImplementedException ("variance conversion");
-                                       }
+                                       if (!applicable[cii])
+                                               continue;
+
+                                       if (!Convert.ImplicitConversionExists (ec, candidates[cii].GetTypeExpression (), bound.Type))
+                                               break;
                                }
 
-                               if (cii != candidates_count)
+                               if (cii != applicable.Length)
                                        continue;
 
                                //
-                               // We already have the best candidate, break if thet are different
+                               // We already have the best candidate, break if it's different (non-unique)
                                //
                                // Dynamic is never ambiguous as we prefer dynamic over other best candidate types
                                //
index 35c2b77448896e1da9b527fde8f848ee9a16ec6d..110044f0a5d8d87f4a3bfddf3da316ffcd4d10e1 100644 (file)
@@ -22,8 +22,27 @@ class D
                return typeof (T) == typeof (object);
        }
        
+       public static bool CovContCont<T> (ICovariant<T> e1, IContravariant<T> e2, IContravariant<T> e3)
+       {
+               Console.WriteLine (typeof (T));
+               return typeof (T) == typeof (string);
+       }
+
+       public static bool ContCovContCov<T> (IContravariant<T> e1, ICovariant<T> e2, IContravariant<T> e3, ICovariant<T> e4)
+       {
+               Console.WriteLine (typeof (T));
+               return typeof (T) == typeof (string);
+       }
+       
+       public static bool CovCovCont<T> (ICovariant<T> e1, ICovariant<T> e2, IContravariant<T> e3)
+       {
+               Console.WriteLine (typeof (T));
+               return typeof (T) == typeof (string);
+       }
+       
        public static int Main ()
        {
+               
                ICovariant<object> a = null;
                ICovariant<string> b = null;
                if (!Covariant (a, b))
@@ -34,6 +53,20 @@ class D
                if (!Contra (a_1, b_1))
                        return 2;
                
+               ICovariant<string> a_2 = null;
+               IContravariant<object> b_2 = null;
+               IContravariant<string> c_2 = null;
+               if (!CovContCont (a_2, b_2, c_2))
+                       return 3;
+               
+               IContravariant<object> a_3 = null;
+               ICovariant<string> b_3 = null;
+               IContravariant<string> c_3 = null;
+               ICovariant<string> d_3 = null;
+               if (!ContCovContCov (a_3, b_3, c_3, d_3))
+                       return 4;
+               
+               Console.WriteLine ("ok");
                return 0;
        }
 }
index 480713219ddecad7195b94b4d61a269b53fd1031..44afaf1727b51498aeb65172dc8ae60b732aba28 100644 (file)
   <test name="gtest-variance-11.cs">\r
     <type name="D">\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>58</size>\r
+        <size>137</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
       <method name="Boolean Covariant[T](ICovariant`1[T], ICovariant`1[T])" attrs="150">\r
         <size>49</size>\r
       </method>\r
+      <method name="Boolean CovContCont[T](ICovariant`1[T], IContravariant`1[T], IContravariant`1[T])" attrs="150">\r
+        <size>49</size>\r
+      </method>\r
+      <method name="Boolean ContCovContCov[T](IContravariant`1[T], ICovariant`1[T], IContravariant`1[T], ICovariant`1[T])" attrs="150">\r
+        <size>49</size>\r
+      </method>\r
+      <method name="Boolean CovCovCont[T](ICovariant`1[T], ICovariant`1[T], IContravariant`1[T])" attrs="150">\r
+        <size>49</size>\r
+      </method>\r
     </type>\r
   </test>\r
   <test name="gtest-variance-12.cs">\r