Add better errors for async
authorMarek Safar <marek.safar@gmail.com>
Wed, 7 Mar 2012 16:26:57 +0000 (16:26 +0000)
committerMarek Safar <marek.safar@gmail.com>
Thu, 8 Mar 2012 08:37:24 +0000 (08:37 +0000)
39 files changed:
mcs/errors/cs0127-2.cs [new file with mode: 0644]
mcs/errors/cs0201-2.cs
mcs/errors/cs0201-3.cs
mcs/errors/cs0201-4.cs
mcs/errors/cs0201-5.cs
mcs/errors/cs0201-6.cs
mcs/errors/cs0201-7.cs
mcs/errors/cs0201-8.cs
mcs/errors/cs0201.cs
mcs/errors/cs1979.cs
mcs/errors/cs1989-2.cs [new file with mode: 0644]
mcs/errors/cs1989.cs
mcs/errors/cs1992.cs [deleted file]
mcs/errors/cs1995.cs [new file with mode: 0644]
mcs/errors/cs1997.cs
mcs/errors/cs4008.cs [new file with mode: 0644]
mcs/errors/cs4014-2.cs [new file with mode: 0644]
mcs/errors/cs4014-3.cs [new file with mode: 0644]
mcs/errors/cs4014-4.cs [new file with mode: 0644]
mcs/errors/cs4014.cs [new file with mode: 0644]
mcs/errors/cs4015.cs [new file with mode: 0644]
mcs/errors/cs4016.cs [new file with mode: 0644]
mcs/errors/cs4033.cs [new file with mode: 0644]
mcs/errors/cs4034.cs [new file with mode: 0644]
mcs/errors/cs4035.cs [new file with mode: 0644]
mcs/errors/known-issues-net_4_5
mcs/mcs/anonymous.cs
mcs/mcs/async.cs
mcs/mcs/attribute.cs
mcs/mcs/context.cs
mcs/mcs/cs-parser.jay
mcs/mcs/ecore.cs
mcs/mcs/expression.cs
mcs/mcs/linq.cs
mcs/mcs/method.cs
mcs/mcs/report.cs
mcs/mcs/statement.cs
mcs/tests/test-async-05.cs
mcs/tests/ver-il-net_4_5.xml

diff --git a/mcs/errors/cs0127-2.cs b/mcs/errors/cs0127-2.cs
new file mode 100644 (file)
index 0000000..1b36551
--- /dev/null
@@ -0,0 +1,13 @@
+// CS0127: `C.GetValue()': A return keyword must not be followed by any expression when method returns void
+// Line: 11
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       public async void GetValue()
+       {
+               return await Task.FromResult(100);
+       }
+}
index bec9a4f946f6dfa20e276c626ab9d1911ab602e9..a590cbbc5debb0cc50b7a5b750a8b12d0604987d 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 7
 
 class T {
index b168d0e5bf3ccadc17ece0f3fa582cf090252d29..62c1f51fb9edbce6408c517902a8ab12ef9d558e 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 7
 
 class T {
index 35093e26f88e6ff28fb9a9d00aa663773f3b4fe4..6c3db68994078a702ce9096984cd391eb058e74d 100755 (executable)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 8
 
 class MainClass
index 308488de95fdf1600f968f759bb8f0abf1869f98..605ece3529f347aa89bda72dedabdfb78243fbdf 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 10
 
 class TestClass
index 48496892c4b885e9d8bfb21caac618bae95b7534..57733dad5730f1838e77129ac8b1fa8fda40bb12 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 13
 
 class C<T>
index e7ffdcb1bb354abe118ffe38474adee4acf999ac..1cefa3e7ec1267a520577aa490e8df663aae3c23 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 10
 
 using System.Linq;
index 14a25b4da793157ba48d4a148eed88489a3ed3e9..8fba571d3c5f0a318f3b1ecb97fd9b96f4251297 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 11
 
 using System;
index 70002ab9fabb2b01d45661732539423f5e725ba0..b62f45ea7b1036ad9f9bcdeaaa30ff3980a7d1c9 100644 (file)
@@ -1,4 +1,4 @@
-// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
 // Line: 11
 
 using System;
index 2a290e81281fe583e2d6f28d8648b698ec679141..c093a3d9f29b0fee9aa2791b81df8744030c9c43 100644 (file)
@@ -1,4 +1,4 @@
-// CS1977: Query expression with a source or join sequence of type `dynamic' is not allowed
+// CS1979: Query expressions with a source or join sequence of type `dynamic' are not allowed
 // Line: 11
 
 using System.Linq;
diff --git a/mcs/errors/cs1989-2.cs b/mcs/errors/cs1989-2.cs
new file mode 100644 (file)
index 0000000..e050236
--- /dev/null
@@ -0,0 +1,19 @@
+// CS1989: Async lambda expressions cannot be converted to expression trees
+// Line: 17
+
+using System;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+
+class C
+{
+       static Task Method ()
+       {
+               return null;
+       }
+       
+       public static void Main ()
+       {
+               Expression<Action<int>> a = async l => Method ();
+       }
+}
index 7c5a84952f7747ca67ca08e629d6d101f36b4996..ebbb9d1b277afaeae9c3be3919e9b1ac24f7ba9a 100644 (file)
@@ -1,4 +1,4 @@
-// CS1989: An expression tree cannot contain an await operator
+// CS1989: Async lambda expressions cannot be converted to expression trees
 // Line: 17
 
 using System;
diff --git a/mcs/errors/cs1992.cs b/mcs/errors/cs1992.cs
deleted file mode 100644 (file)
index ec0d44a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// CS1992: The `await' operator can only be used when its containing method or lambda expression is marked with the `async' modifier
-// Line: 10
-
-using System.Threading.Tasks;
-
-class Tester
-{
-       void Test ()
-       {
-               Task<int> x = null;
-               var a = await x;
-       }
-}
diff --git a/mcs/errors/cs1995.cs b/mcs/errors/cs1995.cs
new file mode 100644 (file)
index 0000000..52c8d3e
--- /dev/null
@@ -0,0 +1,14 @@
+// CS1995: The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause
+// Line: 12
+
+using System.Linq;
+using System.Threading.Tasks;
+
+class C
+{
+       public static async void Test ()
+       {
+               Task<int>[] d = null;
+               var r = from x in d select await x;
+       }
+}
index 6bb3a882296de6c7a890c2d7ad262174f1edfb0f..bcceb7e1576efd6a711d78b8916021d06f24800f 100644 (file)
@@ -1,4 +1,4 @@
-// CS1997: `C.Test()': A return keyword must not be followed by an expression when async method returns Task. Consider using Task<T>
+// CS1997: `C.Test()': A return keyword must not be followed by an expression when async method returns `Task'. Consider using `Task<T>' return type
 // Line: 12
 
 using System;
diff --git a/mcs/errors/cs4008.cs b/mcs/errors/cs4008.cs
new file mode 100644 (file)
index 0000000..f382fa4
--- /dev/null
@@ -0,0 +1,17 @@
+// CS4008: Cannot await void method `X.Foo()'. Consider changing method return type to `Task'
+// Line: 10
+
+using System.Threading.Tasks;
+
+class X
+{
+       static async void Test ()
+       {
+               await Foo ();
+       }
+       
+       static async void Foo ()
+       {
+               await Task.FromResult (1);
+       }
+}
diff --git a/mcs/errors/cs4014-2.cs b/mcs/errors/cs4014-2.cs
new file mode 100644 (file)
index 0000000..aa9afe4
--- /dev/null
@@ -0,0 +1,22 @@
+// CS4014: The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator
+// Line: 17
+// Compiler options: -warnaserror
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       static Task Method ()
+       {
+               return Task.FromResult (1);
+       }
+       
+       static void TestAsync ()
+       {
+               Func<Task> a = async () => {
+                       await Method ();
+                       Method ();
+               };
+       }
+}
diff --git a/mcs/errors/cs4014-3.cs b/mcs/errors/cs4014-3.cs
new file mode 100644 (file)
index 0000000..041137d
--- /dev/null
@@ -0,0 +1,16 @@
+// CS4014: The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator
+// Line: 18
+// Compiler options: -warnaserror
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       static async Task<int> TestAsync ()
+       {
+               Func<Task> f = null;
+               f ();
+               return await Task.FromResult (2);
+       }
+}
diff --git a/mcs/errors/cs4014-4.cs b/mcs/errors/cs4014-4.cs
new file mode 100644 (file)
index 0000000..c6bbf9d
--- /dev/null
@@ -0,0 +1,15 @@
+// CS4014: The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator
+// Line: 12
+// Compiler options: -warnaserror
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       static async Task<int> TestAsync ()
+       {
+               new Task (() => {});
+               return await Task.FromResult (2);
+       }
+}
diff --git a/mcs/errors/cs4014.cs b/mcs/errors/cs4014.cs
new file mode 100644 (file)
index 0000000..5ba2d04
--- /dev/null
@@ -0,0 +1,20 @@
+// CS4014: The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator
+// Line: 18
+// Compiler options: -warnaserror
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       static Task Method ()
+       {
+               return Task.FromResult (1);
+       }
+       
+       static async Task<int> TestAsync ()
+       {
+               Method ();
+               return await Task.FromResult (2);
+       }
+}
diff --git a/mcs/errors/cs4015.cs b/mcs/errors/cs4015.cs
new file mode 100644 (file)
index 0000000..6e0cb59
--- /dev/null
@@ -0,0 +1,14 @@
+// CS4015: `C.SynchronousCall(int)': Async methods cannot use `MethodImplOptions.Synchronized'
+// Line: 9
+
+using System.Threading.Tasks;
+using System.Runtime.CompilerServices;
+
+class C
+{
+       [MethodImplAttribute(MethodImplOptions.Synchronized)]
+       public static async Task SynchronousCall (int arg)
+       {
+               await Task.FromResult (1);
+       }
+}
diff --git a/mcs/errors/cs4016.cs b/mcs/errors/cs4016.cs
new file mode 100644 (file)
index 0000000..8d3d435
--- /dev/null
@@ -0,0 +1,14 @@
+// CS4016: `C.GetValue()': The return expression type of async method must be `int' rather than `Task<int>'
+// Line: 12
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       public async Task<int> GetValue()
+       {
+               await Task.FromResult (0);
+               return Task.FromResult (1);
+       }
+}
diff --git a/mcs/errors/cs4033.cs b/mcs/errors/cs4033.cs
new file mode 100644 (file)
index 0000000..0371f89
--- /dev/null
@@ -0,0 +1,13 @@
+// CS4033: The `await' operator can only be used when its containing method is marked with the `async' modifier
+// Line: 11
+
+using System.Threading.Tasks;
+
+class Tester
+{
+       void Test ()
+       {
+               Task<int> x = null;
+               var a = await x;
+       }
+}
diff --git a/mcs/errors/cs4034.cs b/mcs/errors/cs4034.cs
new file mode 100644 (file)
index 0000000..7d8afd1
--- /dev/null
@@ -0,0 +1,13 @@
+// CS4034: The `await' operator can only be used when its containing lambda expression is marked with the `async' modifier
+// Line: 11
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       public void Test ()
+       {
+               Action a = () => await Task.FromResult (1);
+       }
+}
diff --git a/mcs/errors/cs4035.cs b/mcs/errors/cs4035.cs
new file mode 100644 (file)
index 0000000..d50d5fe
--- /dev/null
@@ -0,0 +1,13 @@
+// CS4035: The `await' operator can only be used when its containing anonymous method is marked with the `async' modifier
+// Line: 11
+
+using System;
+using System.Threading.Tasks;
+
+class C
+{
+       public void Test ()
+       {
+               Action a = delegate { await Task.FromResult (1); };
+       }
+}
index 1aa065de994d4a18579f26446614cbdecbdc767e..be17f4068b5cb5b5831923c4a4db9bbbcd571100 100644 (file)
@@ -16,6 +16,3 @@ cs0162-7.cs NO ERROR
 # Operators
 cs0457-2.cs
 cs0457.cs
-
-# all the following are from bug #628673
-cs1979.cs
index e2361003ce8abef37a2b663a45b3e975cfeec0bb..1b169432e103694cef43b9a82a7cbffd05624bc4 100644 (file)
@@ -1075,6 +1075,10 @@ namespace Mono.CSharp {
                                        } else {
                                                int errors = ec.Report.Errors;
 
+                                               if (Block.IsAsync) {
+                                                       ec.Report.Error (1989, loc, "Async lambda expressions cannot be converted to expression trees");
+                                               }
+
                                                using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) {
                                                        am = body.Compatible (ec);
                                                }
index bea02cacba74e8c43e20659930e752e56cce2d96..408e215785d0e4c02d9846e0b06e0f2879182749 100644 (file)
@@ -64,11 +64,6 @@ namespace Mono.CSharp
                                        "The `await' operator cannot be used in the body of a lock statement");
                        }
 
-                       if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
-                               rc.Report.Error (1989, loc, "An expression tree cannot contain an await operator");
-                               return null;
-                       }
-
                        if (rc.IsUnsafe) {
                                rc.Report.Error (4004, loc,
                                        "The `await' operator cannot be used in an unsafe context");
@@ -134,7 +129,13 @@ namespace Mono.CSharp
 
                        protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type)
                        {
-                               rc.Report.Error (4001, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
+                               var invocation = LeftExpression as Invocation;
+                               if (invocation != null && invocation.MethodGroup != null && (invocation.MethodGroup.BestCandidate.Modifiers & Modifiers.ASYNC) != 0) {
+                                       rc.Report.Error (4008, loc, "Cannot await void method `{0}'. Consider changing method return type to `Task'",
+                                               invocation.GetSignatureForError ());
+                               } else {
+                                       rc.Report.Error (4001, loc, "Cannot await `{0}' expression", type.GetSignatureForError ());
+                               }
                        }
                }
 
@@ -297,6 +298,12 @@ namespace Mono.CSharp
 
                public override bool Resolve (BlockContext bc)
                {
+                       if (bc.CurrentBlock is Linq.QueryBlock) {
+                               bc.Report.Error (1995, loc,
+                                       "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause");
+                               return false;
+                       }
+
                        if (!base.Resolve (bc))
                                return false;
 
index efd753a5244bcc6d6e2b348bbc943758d30258a5..ae9627e93be4b709c507235b19a347622c154bc1 100644 (file)
@@ -897,6 +897,11 @@ namespace Mono.CSharp {
                // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
                // 
                public bool IsInternalCall ()
+               {
+                       return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
+               }
+
+               public MethodImplOptions GetMethodImplOptions ()
                {
                        MethodImplOptions options = 0;
                        if (pos_args.Count == 1) {
@@ -906,7 +911,7 @@ namespace Mono.CSharp {
                                options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
                        }
 
-                       return (options & MethodImplOptions.InternalCall) != 0;
+                       return options;
                }
 
                //
index 4a2318c2b5db4e69ff64216be2f98166f3a0d51a..5f309854bdabfabfd4924d6b96667d44c9e0561b 100644 (file)
@@ -481,7 +481,7 @@ namespace Mono.CSharp
                        // or it's a parameter
                        //
                        if (CurrentAnonymousMethod is AsyncInitializer)
-                               return CurrentBlock.Explicit.HasAwait;
+                               return local.IsParameter || CurrentBlock.Explicit.HasAwait;
 
                        return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
                }
index 2d204a78d9a282206edf82245595d74a98d3dc46..11aae39803ab588d456ae865283989dac4019da1 100644 (file)
@@ -3760,8 +3760,16 @@ unary_expression
        | AWAIT prefixed_unary_expression
          {
                if (!async_block) {
-                       report.Error (1992, GetLocation ($1),
-                               "The `await' operator can only be used when its containing method or lambda expression is marked with the `async' modifier");
+                        if (current_anonymous_method is LambdaExpression) {
+                               report.Error (4034, GetLocation ($1),
+                                       "The `await' operator can only be used when its containing lambda expression is marked with the `async' modifier");
+                       } else if (current_anonymous_method is AnonymousMethodExpression) {
+                               report.Error (4035, GetLocation ($1),
+                                       "The `await' operator can only be used when its containing anonymous method is marked with the `async' modifier");
+                       } else {
+                               report.Error (4033, GetLocation ($1),
+                                       "The `await' operator can only be used when its containing method is marked with the `async' modifier");
+                       }
                } else {
                        current_block.Explicit.RegisterAsyncAwait ();
                }
index cbccc0e40b519f3a910b5e98910f962d27f39794..d49a491571cc88c5d08b8f747a9806d15643f7ab 100644 (file)
@@ -222,8 +222,7 @@ namespace Mono.CSharp {
 
                public static void Error_InvalidExpressionStatement (Report Report, Location loc)
                {
-                       Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " +
-                                      "expressions can be used as a statement");
+                       Report.Error (201, loc, "Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement");
                }
                
                public void Error_InvalidExpressionStatement (BlockContext ec)
@@ -1025,6 +1024,12 @@ namespace Mono.CSharp {
                        if (es == null)
                                Error_InvalidExpressionStatement (ec);
 
+                       if (ec.CurrentAnonymousMethod is AsyncInitializer && !(e is Assign) &&
+                               (e.Type.IsGenericTask || e.Type == ec.Module.PredefinedTypes.Task.TypeSpec)) {
+                               ec.Report.Warning (4014, 1, e.Location,
+                                       "The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator");
+                       }
+
                        return es;
                }
 
index 0746a593f5a2ce51632b3c0e79b068b4d0c6779e..4f6fe1316779374fb288f5a0b3e263a544d28d15 100644 (file)
@@ -5235,6 +5235,12 @@ namespace Mono.CSharp
                                return expr;
                        }
                }
+
+               public MethodGroupExpr MethodGroup {
+                       get {
+                               return mg;
+                       }
+               }
                #endregion
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
index 37bf43622ac38702f5ab7b016f15d0893d11cd66..9c854a8fe9547612f500c1433cecd4c029fc3174 100644 (file)
@@ -85,6 +85,13 @@ namespace Mono.CSharp.Linq
                                return rmg;
                        }
 
+                       protected override Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
+                       {
+                               ec.Report.Error (1979, loc,
+                                       "Query expressions with a source or join sequence of type `dynamic' are not allowed");
+                               return null;
+                       }
+
                        #region IErrorHandler Members
 
                        bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous)
@@ -411,19 +418,6 @@ namespace Mono.CSharp.Linq
 
                public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter)
                {
-/*
-                       expr = expr.Resolve (ec);
-                       if (expr == null)
-                               return null;
-
-                       if (expr.Type == InternalType.Dynamic || expr.Type == TypeManager.void_type) {
-                               ec.Report.Error (1979, expr.Location,
-                                       "Query expression with a source or join sequence of type `{0}' is not allowed",
-                                       TypeManager.CSharpName (expr.Type));
-                               return null;
-                       }
-*/
-
                        if (IdentifierType != null)
                                expr = CreateCastExpression (expr);
 
index c66d81f33fd1ab0898ea9756b8622e322098810e..291ab2fca13f30b78258752a9d27fed5f7199ea5 100644 (file)
@@ -19,6 +19,7 @@ using System.Security.Permissions;
 using System.Text;
 using System.Linq;
 using Mono.CompilerServices.SymbolWriter;
+using System.Runtime.CompilerServices;
 
 #if NET_2_1
 using XmlElement = System.Object;
@@ -533,10 +534,13 @@ namespace Mono.CSharp {
                        }
 
                        if (a.Type == pa.MethodImpl) {
-                               is_external_implementation = a.IsInternalCall ();
-                       }
+                               if ((ModFlags & Modifiers.ASYNC) != 0 && (a.GetMethodImplOptions () & MethodImplOptions.Synchronized) != 0) {
+                                       Report.Error (4015, a.Location, "`{0}': Async methods cannot use `MethodImplOptions.Synchronized'",
+                                               GetSignatureForError ());
+                               }
 
-                       if (a.Type == pa.DllImport) {
+                               is_external_implementation = a.IsInternalCall ();
+                       } else if (a.Type == pa.DllImport) {
                                const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
                                if ((ModFlags & extern_static) != extern_static) {
                                        Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
index d8a2e2fc761dc56cd89afcbcfcbcb9346f315210..50d78f0071c39faa0b7e26e8ab8c871173a859d5 100644 (file)
@@ -55,7 +55,8 @@ namespace Mono.CSharp {
                        2002, 2023, 2029,
                        3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,
                        3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019,
-                       3021, 3022, 3023, 3024, 3026, 3027
+                       3021, 3022, 3023, 3024, 3026, 3027,
+                       4014
                };
 
                static HashSet<int> AllWarningsHashSet;
index ff12a7d9dae696ee03bde3a9c2c0fa8d754b8c05..b21b5532120a8e3ce2213b1f1b563f472c32e41b 100644 (file)
@@ -856,6 +856,8 @@ namespace Mono.CSharp {
                                        ec.Report.Error (127, loc,
                                                "`{0}': A return keyword must not be followed by any expression when method returns void",
                                                ec.GetSignatureForError ());
+
+                                       return false;
                                }
                        } else {
                                if (am.IsIterator) {
@@ -874,12 +876,21 @@ namespace Mono.CSharp {
                                                        return true;
                                                }
 
+                                               // TODO: Better error message
+                                               if (async_type.Kind == MemberKind.Void) {
+                                                       ec.Report.Error (127, loc,
+                                                               "`{0}': A return keyword must not be followed by any expression when method returns void",
+                                                               ec.GetSignatureForError ());
+
+                                                       return false;
+                                               }
+
                                                if (!async_type.IsGenericTask) {
                                                        if (this is ContextualReturn)
                                                                return true;
 
                                                        ec.Report.Error (1997, loc,
-                                                               "`{0}': A return keyword must not be followed by an expression when async method returns Task. Consider using Task<T>",
+                                                               "`{0}': A return keyword must not be followed by an expression when async method returns `Task'. Consider using `Task<T>' return type",
                                                                ec.GetSignatureForError ());
                                                        return false;
                                                }
@@ -887,7 +898,13 @@ namespace Mono.CSharp {
                                                //
                                                // The return type is actually Task<T> type argument
                                                //
-                                               block_return_type = async_type.TypeArguments[0];
+                                               if (expr.Type == async_type) {
+                                                       ec.Report.Error (4016, loc,
+                                                               "`{0}': The return expression type of async method must be `{1}' rather than `Task<{1}>'",
+                                                               ec.GetSignatureForError (), async_type.TypeArguments[0].GetSignatureForError ());
+                                               } else {
+                                                       block_return_type = async_type.TypeArguments[0];
+                                               }
                                        }
                                } else {
                                        var l = am as AnonymousMethodBody;
index daf58596b25047bfcf4573889641ac26ec84dba2..df57e8a3a5eb40026cd24ba2acf5bd6f837826ca 100644 (file)
@@ -1,19 +1,19 @@
-// Compiler options: -langversion:future
-
-using System;
-using System.Linq.Expressions;
 using System.Threading.Tasks;
 
 class C
 {
-       static Task Method ()
+       public async Task SynchronousCall (int arg)
+       {
+               AnotherTask (arg);
+       }
+       
+       Task AnotherTask (int arg)
        {
-               return null;
+               return Task.FromResult (arg);
        }
        
        public static void Main ()
        {
-               Expression<Action<int>> a = async l => Method ();
-               a.Compile () (1);
+               new C ().SynchronousCall (1);
        }
-}
+}
\ No newline at end of file
index d8b70b2ec34f2ec74345b7737fc70a90b34a241a..9a42eeee26762856451fab17e4e2659901ef6f51 100644 (file)
   </test>
   <test name="test-async-05.cs">
     <type name="C">
-      <method name="System.Threading.Tasks.Task Method()" attrs="145">
-        <size>10</size>
-      </method>
       <method name="Void Main()" attrs="150">
-        <size>72</size>
+        <size>14</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="System.Threading.Tasks.Task SynchronousCall(Int32)" attrs="134">
+        <size>38</size>
+      </method>
+      <method name="System.Threading.Tasks.Task AnotherTask(Int32)" attrs="129">
+        <size>15</size>
+      </method>
+    </type>
+    <type name="C+&lt;SynchronousCall&gt;c__async0">
+      <method name="Void MoveNext()" attrs="134">
+        <size>49</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>18</size>
+      </method>
     </type>
   </test>
   <test name="test-async-06.cs">
       </method>
     </type>
   </test>
+  <test name="test-async-28.cs">
+    <type name="C">
+      <method name="System.Threading.Tasks.Task Test()" attrs="150">
+        <size>24</size>
+      </method>
+      <method name="Void Main()" attrs="150">
+        <size>12</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C+&lt;Test&gt;c__async0">
+      <method name="Void MoveNext()" attrs="134">
+        <size>275</size>
+      </method>
+      <method name="Int32 &lt;&gt;m__0(Int32)" attrs="145">
+        <size>10</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>18</size>
+      </method>
+    </type>
+  </test>
   <test name="test-cls-00.cs">
     <type name="CLSCLass_6">
       <method name="Void add_Disposed(Delegate)" attrs="2182">