[mono/mono] b5bc9d75: Update lower/upper type inference fixing to match the latest C# standard. Fixes #15505

"Marek Safar ([email protected])" <[email protected]>
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <00000141fba4ce64-e5e11b01-17d2-4d77-8b1b-20b766ab1583-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/mono
  Compare: https://github.com/mono/mono/compare/ee09ac3bcf7f...b5bc9d75d52e

   Commit: b5bc9d75d52ea01ecb3ae6253554ca063806bd46
   Author: Marek Safar <[email protected]> (marek-safar)
     Date: 2013-10-27 20:37:34 GMT
      URL: https://github.com/mono/mono/commit/b5bc9d75d52ea01ecb3ae6253554ca063806bd46

Update lower/upper type inference fixing to match the latest C# standard. Fixes #15505

Changed paths:
  M mcs/mcs/generic.cs
  M mcs/tests/gtest-variance-11.cs
  M mcs/tests/ver-il-net_4_5.xml

Modified: mcs/mcs/generic.cs
===================================================================
@@ -3142,87 +3142,100 @@ public bool FixType (ResolveContext ec, int i)
 			}
 
 			//
-			// 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
 				//

Modified: mcs/tests/gtest-variance-11.cs
===================================================================
@@ -22,8 +22,27 @@ public static bool Covariant<T> (ICovariant<T> e1, ICovariant<T> e2)
 		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 @@ public static int Main ()
 		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;
 	}
 }

Modified: mcs/tests/ver-il-net_4_5.xml
===================================================================
@@ -28755,7 +28755,7 @@
   <test name="gtest-variance-11.cs">
     <type name="D">
       <method name="Int32 Main()" attrs="150">
-        <size>58</size>
+        <size>137</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
@@ -28766,6 +28766,15 @@
       <method name="Boolean Covariant[T](ICovariant`1[T], ICovariant`1[T])" attrs="150">
         <size>49</size>
       </method>
+      <method name="Boolean CovContCont[T](ICovariant`1[T], IContravariant`1[T], IContravariant`1[T])" attrs="150">
+        <size>49</size>
+      </method>
+      <method name="Boolean ContCovContCov[T](IContravariant`1[T], ICovariant`1[T], IContravariant`1[T], ICovariant`1[T])" attrs="150">
+        <size>49</size>
+      </method>
+      <method name="Boolean CovCovCont[T](ICovariant`1[T], ICovariant`1[T], IContravariant`1[T])" attrs="150">
+        <size>49</size>
+      </method>
     </type>
   </test>
   <test name="gtest-variance-12.cs">



_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.