Adds async type inference of void return type. Fixes #15238
authorMarek Safar <marek.safar@gmail.com>
Tue, 8 Oct 2013 17:30:32 +0000 (19:30 +0200)
committerMarek Safar <marek.safar@gmail.com>
Tue, 8 Oct 2013 17:30:32 +0000 (19:30 +0200)
mcs/mcs/anonymous.cs
mcs/mcs/generic.cs
mcs/mcs/statement.cs
mcs/tests/test-async-52.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index ce83e7674c14d88cc1b6c60145409209a83def58..94ab2796880cfbd4c02a288553567bd605d68374 100644 (file)
@@ -1535,10 +1535,14 @@ namespace Mono.CSharp {
 
                                //
                                // If e is synchronous the inferred return type is T
-                               // If e is asynchronous the inferred return type is Task<T>
+                               // If e is asynchronous and the body of F is either an expression classified as nothing
+                               // or a statement block where no return statements have expressions, the inferred return type is Task
+                               // If e is async and has an inferred result type T, the inferred return type is Task<T>
                                //
                                if (block.IsAsync && ReturnType != null) {
-                                       ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
+                                       ReturnType = ReturnType.Kind == MemberKind.Void ?
+                                               ec.Module.PredefinedTypes.Task.TypeSpec :
+                                               ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
                                }
                        }
 
index 203290b70b6092282ca14670561e9f89a5960c5f..13836984421c838a1ebb27f52be72b66091c30d6 100644 (file)
@@ -2948,15 +2948,20 @@ namespace Mono.CSharp {
 
                public void AddCommonTypeBound (TypeSpec type)
                {
-                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0);
+                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0, false);
                }
 
-               void AddToBounds (BoundInfo bound, int index)
+               public void AddCommonTypeBoundAsync (TypeSpec type)
+               {
+                       AddToBounds (new BoundInfo (type, BoundKind.Lower), 0, true);
+               }
+
+               void AddToBounds (BoundInfo bound, int index, bool voidAllowed)
                {
                        //
                        // Some types cannot be used as type arguments
                        //
-                       if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
+                       if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
                                bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod)
                                return;
 
@@ -3030,7 +3035,7 @@ namespace Mono.CSharp {
                        if (pos == -1)
                                return 0;
 
-                       AddToBounds (new BoundInfo (u, BoundKind.Exact), pos);
+                       AddToBounds (new BoundInfo (u, BoundKind.Exact), pos, false);
                        return 1;
                }
 
@@ -3361,7 +3366,7 @@ namespace Mono.CSharp {
                        // If V is one of the unfixed type arguments
                        int pos = IsUnfixed (v);
                        if (pos != -1) {
-                               AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos);
+                               AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos, false);
                                return 1;
                        }                       
 
index 9b0b7daafe009b56bd49fdda1f0b0201874bfdc2..b3bd8861cefb49f5bb124085bec8058581656802 100644 (file)
@@ -902,7 +902,7 @@ namespace Mono.CSharp {
                                                var async_type = storey.ReturnType;
 
                                                if (async_type == null && async_block.ReturnTypeInference != null) {
-                                                       async_block.ReturnTypeInference.AddCommonTypeBound (expr.Type);
+                                                       async_block.ReturnTypeInference.AddCommonTypeBoundAsync (expr.Type);
                                                        return true;
                                                }
 
diff --git a/mcs/tests/test-async-52.cs b/mcs/tests/test-async-52.cs
new file mode 100644 (file)
index 0000000..36230ac
--- /dev/null
@@ -0,0 +1,23 @@
+using System;
+using System.Threading.Tasks;
+
+public delegate T ActualValueDelegate<T> ();
+
+class X
+{
+       public static void Main ()
+       {
+               Matches (async () => await Throw());
+       }
+
+       static bool Matches<T>(ActualValueDelegate<T> del) where T : Task
+       {
+               del ().Wait ();
+               return true;
+       }
+
+       static async Task Throw()
+       {
+               await Task.Delay (1);
+       }
+}
\ No newline at end of file
index 148f940ecbef07ebf9522ca2ffc0ec2d9879cdbf..9f34ffa45749249d7db29701e68f57f2e3cb5d1a 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-async-52.cs">\r
+    <type name="ActualValueDelegate`1[T]">\r
+      <method name="T Invoke()" attrs="454">\r
+        <size>0</size>\r
+      </method>\r
+      <method name="IAsyncResult BeginInvoke(System.AsyncCallback, System.Object)" attrs="454">\r
+        <size>0</size>\r
+      </method>\r
+      <method name="T EndInvoke(IAsyncResult)" attrs="454">\r
+        <size>0</size>\r
+      </method>\r
+      <method name="Void .ctor(Object, IntPtr)" attrs="6278">\r
+        <size>0</size>\r
+      </method>\r
+    </type>\r
+    <type name="X">\r
+      <method name="Void Main()" attrs="150">\r
+        <size>37</size>\r
+      </method>\r
+      <method name="Boolean Matches[T](ActualValueDelegate`1[T])" attrs="145">\r
+        <size>30</size>\r
+      </method>\r
+      <method name="System.Threading.Tasks.Task Throw()" attrs="145">\r
+        <size>33</size>\r
+      </method>\r
+      <method name="System.Threading.Tasks.Task &lt;Main&gt;m__0()" attrs="145">\r
+        <size>33</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="X+&lt;Throw&gt;c__async0">\r
+      <method name="Void MoveNext()" attrs="486">\r
+        <size>157</size>\r
+      </method>\r
+      <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
+        <size>13</size>\r
+      </method>\r
+    </type>\r
+    <type name="X+&lt;Main&gt;c__async3">\r
+      <method name="Void MoveNext()" attrs="486">\r
+        <size>160</size>\r
+      </method>\r
+      <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
+        <size>13</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-cls-00.cs">\r
     <type name="CLSCLass_6">\r
       <method name="Void add_Disposed(Delegate)" attrs="2182">\r