Fixed type inference between upper and lower bounds
authorMarek Safar <marek.safar@gmail.com>
Mon, 23 Aug 2010 21:29:29 +0000 (22:29 +0100)
committerMarek Safar <marek.safar@gmail.com>
Tue, 24 Aug 2010 07:26:21 +0000 (08:26 +0100)
mcs/mcs/generic.cs
mcs/tests/gtest-variance-15.cs [new file with mode: 0644]

index e6761c3c796202e6a80d6ed7fee2ae7129f162d6..2c118da3d5aedd383da4cec2c994c3b3e3daeb66 100644 (file)
@@ -2608,13 +2608,20 @@ namespace Mono.CSharp {
                                        }
 
                                        if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) {
-                                               if (cbound.Kind != BoundKind.Exact) {
+                                               if (cbound.Kind == BoundKind.Lower) {
                                                        if (!Convert.ImplicitConversionExists (ec, new TypeExpression (cbound.Type, Location.Null), bound.Type)) {
                                                                break;
                                                        }
 
                                                        continue;
                                                }
+                                               if (cbound.Kind == BoundKind.Upper) {
+                                                       if (!Convert.ImplicitConversionExists (ec, new TypeExpression (bound.Type, Location.Null), cbound.Type)) {
+                                                               break;
+                                                       }
+
+                                                       continue;
+                                               }
                                                
                                                if (bound.Kind != BoundKind.Exact) {
                                                        if (!Convert.ImplicitConversionExists (ec, new TypeExpression (bound.Type, Location.Null), cbound.Type)) {
@@ -2629,13 +2636,25 @@ namespace Mono.CSharp {
                                        }
 
                                        if (bound.Kind == BoundKind.Lower) {
-                                               if (!Convert.ImplicitConversionExists (ec, new TypeExpression (cbound.Type, Location.Null), bound.Type)) {
-                                                       break;
+                                               if (cbound.Kind == BoundKind.Lower) {
+                                                       if (!Convert.ImplicitConversionExists (ec, new TypeExpression (cbound.Type, Location.Null), bound.Type)) {
+                                                               break;
+                                                       }
+                                               } else {
+                                                       if (!Convert.ImplicitConversionExists (ec, new TypeExpression (bound.Type, Location.Null), cbound.Type)) {
+                                                               break;
+                                                       }
                                                }
-                                       } else {
+
+                                               continue;
+                                       }
+
+                                       if (bound.Kind == BoundKind.Upper) {
                                                if (!Convert.ImplicitConversionExists (ec, new TypeExpression (bound.Type, Location.Null), cbound.Type)) {
                                                        break;
                                                }
+                                       } else {
+                                               throw new NotImplementedException ("variance conversion");
                                        }
                                }
 
diff --git a/mcs/tests/gtest-variance-15.cs b/mcs/tests/gtest-variance-15.cs
new file mode 100644 (file)
index 0000000..7a357ff
--- /dev/null
@@ -0,0 +1,30 @@
+using System;
+
+public class C
+{
+       delegate void D<in T> (T t);
+       
+       static void M<T> (ref T t, D<T> a)
+       {
+               a (t);
+       }
+
+       static void M2<T> (T t, D<T> a)
+       {
+               a (t);
+       }
+       
+       static void MethodArg (object o)
+       {
+       }
+       
+       public static int Main ()
+       {
+               D<object> action = l => Console.WriteLine (l);
+               string s = "value";
+               
+               M (ref s, action);
+               M2 (s, action);
+               return 0;
+       }
+}