//
// 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 });
}
}
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;
if (pos == -1)
return 0;
- AddToBounds (new BoundInfo (u, BoundKind.Exact), pos);
+ AddToBounds (new BoundInfo (u, BoundKind.Exact), pos, false);
return 1;
}
// 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;
}
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;
}
--- /dev/null
+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
</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 <Main>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+<Throw>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+<Main>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