Prefer dynamic over other types when used with type inference.
authorMarek Safar <marek.safar@gmail.com>
Fri, 20 Aug 2010 14:12:38 +0000 (15:12 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 20 Aug 2010 15:49:57 +0000 (16:49 +0100)
mcs/mcs/class.cs
mcs/mcs/generic.cs
mcs/mcs/statement.cs
mcs/tests/dtest-008.cs
mcs/tests/dtest-implicitarray-01.cs [new file with mode: 0644]
mcs/tests/ver-il-dmcs.xml

index 089c0e105176318e91e7b38a993462f673c55fdd..796b3585920452dbe05b07a6de06cd331d57d729 100644 (file)
@@ -121,7 +121,7 @@ namespace Mono.CSharp {
                {
                        public DynamicSiteClass (DeclSpace parent)
                                : base (parent, new MemberName (CompilerGeneratedClass.MakeName (null, "c", "DynamicSite", 0)),
-                                       Modifiers.INTERNAL | Modifiers.STATIC)
+                                       Modifiers.PRIVATE | Modifiers.STATIC)
                        {
                        }
                }
index 95458ba723373588de3fd69fc38c8cb35cea5ebe..e6761c3c796202e6a80d6ed7fee2ae7129f162d6 100644 (file)
@@ -2328,17 +2328,13 @@ namespace Mono.CSharp {
                        Upper   = 2
                }
 
-               class BoundInfo
+               class BoundInfo : IEquatable<BoundInfo>
                {
                        public readonly TypeSpec Type;
                        public readonly BoundKind Kind;
 
                        public BoundInfo (TypeSpec type, BoundKind kind)
                        {
-                               // Unify dynamic and object to simplify best candidate resolution
-                               if (type == InternalType.Dynamic)
-                                       type = TypeManager.object_type;
-
                                this.Type = type;
                                this.Kind = kind;
                        }
@@ -2348,11 +2344,14 @@ namespace Mono.CSharp {
                                return Type.GetHashCode ();
                        }
 
-                       public override bool Equals (object obj)
+                       #region IEquatable<BoundInfo> Members
+
+                       public bool Equals (BoundInfo other)
                        {
-                               BoundInfo a = (BoundInfo) obj;
-                               return Type == a.Type && Kind == a.Kind;
+                               return Type == other.Type && Kind == other.Kind;
                        }
+
+                       #endregion
                }
 
                readonly TypeSpec[] unfixed_types;
@@ -2643,8 +2642,19 @@ namespace Mono.CSharp {
                                if (cii != candidates_count)
                                        continue;
 
-                               if (best_candidate != null && best_candidate != bound.Type)
-                                       return false;
+                               //
+                               // We already have the best candidate, break if thet are different
+                               //
+                               // Dynamic is never ambiguous as we prefer dynamic over other best candidate types
+                               //
+                               if (best_candidate != null) {
+
+                                       if (best_candidate == InternalType.Dynamic)
+                                               continue;
+
+                                       if (bound.Type != InternalType.Dynamic && best_candidate != bound.Type)
+                                               return false;
+                               }
 
                                best_candidate = bound.Type;
                        }
index d6fd3a2536c421d037f57bb55e7c3b065343cacd..5ee1cae16dc97246aa360dd11f9dd31d60d1e160 100644 (file)
@@ -5455,8 +5455,13 @@ namespace Mono.CSharp {
 
                                VarExpr ve = var_type as VarExpr;
                                if (ve != null) {
-                                       // Infer implicitly typed local variable from foreach enumerable type
-                                       var_type = new TypeExpression (current_pe.Type, var_type.Location);
+                                       if (is_dynamic) {
+                                               // Source type is dynamic, set element type to dynamic too
+                                               var_type = new TypeExpression (InternalType.Dynamic, var_type.Location);
+                                       } else {
+                                               // Infer implicitly typed local variable from foreach enumerable type
+                                               var_type = new TypeExpression (current_pe.Type, var_type.Location);
+                                       }
                                }
 
                                var_type = var_type.ResolveAsTypeTerminal (ec, false);
index e2d8e7e35167bc96932f2f55905913d230c942cf..e234ac990ec5860174ec459b05f7619d5c485109 100644 (file)
@@ -30,6 +30,18 @@ public class Test
                Console.WriteLine (res);
                return res == 31;
        }
+       
+       bool ForEachTest_2()
+       {
+               dynamic c = new int [2] { 5, 7 };
+               int total = 0;
+               foreach (var v in c)
+               {
+                       total += v;
+               }
+               
+               return total == 12;
+       }
 
        bool UsingTest ()
        {
@@ -61,8 +73,11 @@ public class Test
                if (!t.ForEachTest ())
                        return 1;
 
-               if (!t.UsingTest ())
+               if (!t.ForEachTest_2 ())
                        return 2;
+               
+               if (!t.UsingTest ())
+                       return 3;
 
                Console.WriteLine ("ok");
                return 0;
diff --git a/mcs/tests/dtest-implicitarray-01.cs b/mcs/tests/dtest-implicitarray-01.cs
new file mode 100644 (file)
index 0000000..b14e374
--- /dev/null
@@ -0,0 +1,14 @@
+public class C
+{
+       void Method ()
+       {
+       }
+       
+       public static int Main ()
+       {
+               dynamic d = new C ();
+               var a = new [] { d, (object) null };
+               a[0].Method();
+               return 0;
+       }
+}
\ No newline at end of file
index a3f24ac34098e4ff5354d5627c828cfe58e55811..4c57ef02dd82ca290d08ad8084c6db223c2f3ed1 100644 (file)
         <size>1</size>
       </method>
       <method name="Void ConvertImplicitTest()">
-        <size>1017</size>
+        <size>1331</size>
       </method>
       <method name="Int32 ConvertImplicitReturnTest()">
         <size>75</size>
         <size>862</size>
       </method>
       <method name="Int32 Main()">
-        <size>44</size>
+        <size>57</size>
       </method>
       <method name="Void .ctor()">
         <size>7</size>
       </method>
+      <method name="Boolean ForEachTest_2()">
+        <size>300</size>
+      </method>
     </type>
   </test>
   <test name="dtest-009.cs">
       </method>
     </type>
   </test>
+  <test name="dtest-implicitarray-01.cs">
+    <type name="C">
+      <method name="Void Method()">
+        <size>1</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>104</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="dtest-iter-01.cs">
     <type name="Program">
       <method name="IEnumerable`1 D1()">