/Src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs
C# | 3780 lines | 3195 code | 137 blank | 448 comment | 1 complexity | 093c3e2421baa2837e93dde09d6dbcc9 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- // Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
- using System.Collections.Generic;
- using System.Linq;
- using Microsoft.CodeAnalysis.CSharp.Symbols;
- using Microsoft.CodeAnalysis.CSharp.Syntax;
- using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
- using Microsoft.CodeAnalysis.Text;
- using Roslyn.Test.Utilities;
- using Xunit;
- namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
- {
- public class BindingAsyncTests : CompilingTestBase
- {
- [Fact]
- public void AsyncMethod()
- {
- var source = @"
- using System.Threading.Tasks;
- class C
- {
- async void M(Task t)
- {
- await t;
- }
- }";
- var compilation = CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- var method = (SourceMethodSymbol)compilation.GlobalNamespace.GetTypeMembers("C").Single().GetMembers("M").Single();
- Assert.True(method.IsAsync);
- }
- [Fact]
- public void AsyncLambdas()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- public static void Main()
- {
- Action<Task> f1 = async (Task t) => { await t; };
- Action<Task> f2 = async t => { await t; };
- Action<Task> f3 = async (t) => { await t; };
- }
- }";
- var tree = SyntaxFactory.ParseSyntaxTree(source);
- var compilation = CreateCompilationWithMscorlib45(new SyntaxTree[] {tree}).VerifyDiagnostics();
- var model = compilation.GetSemanticModel(tree);
- var simple = tree.GetCompilationUnitRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().Single();
- Assert.True(((LambdaSymbol)model.GetSymbolInfo(simple).Symbol).IsAsync);
- var parens = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>();
- Assert.True(parens.Count() == 2, "Expect exactly two parenthesized lambda expressions in the syntax tree.");
- foreach (var paren in parens)
- {
- Assert.True(((LambdaSymbol)model.GetSymbolInfo(paren).Symbol).IsAsync);
- }
- }
- [Fact]
- public void AsyncDelegates()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- public static void Main()
- {
- Action<Task> f4 = async delegate(Task t) { await t; };
- }
- }";
- var tree = SyntaxFactory.ParseSyntaxTree(source);
- var compilation = CreateCompilationWithMscorlib45(new SyntaxTree[] { tree }).VerifyDiagnostics();
- var model = compilation.GetSemanticModel(tree);
- var del = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousMethodExpressionSyntax>().Single();
- Assert.True(((LambdaSymbol)model.GetSymbolInfo(del).Symbol).IsAsync);
- }
- [Fact]
- public void BadAsyncConstructor()
- {
- var source = @"
- class C {
- async public C() { }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncDestructor()
- {
- var source = @"
- class C
- {
- async extern ~C();
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async"),
- Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "C").WithArguments("C.~C()"));
- }
- [Fact]
- public void BadAsyncEvent()
- {
- var source = @"
- public delegate void MyDelegate();
- class C
- {
- public C() {
- MyEvent.Invoke();
- }
- async event MyDelegate MyEvent;
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyEvent").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncField()
- {
- var source = @"
- class C
- {
- public C(int i)
- {
- this.i = i;
- }
- async int i;
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "i").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncClass()
- {
- var source = @"
- public async class C
- {
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncStruct()
- {
- var source = @"
- internal async struct S
- {
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "S").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncInterface()
- {
- var source = @"
- internal async interface I
- {
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "I").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncDelegate()
- {
- var source = @"
- public async delegate void MyDelegate();
- ";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncProperty()
- {
- var source = @"
- public async delegate void MyDelegate();
- ";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async"));
- }
- [Fact]
- public void BadAsyncPropertyAccessor()
- {
- var source = @"
- public async delegate void MyDelegate();
- ";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async"));
- }
- [Fact]
- public void TaskRetNoObjectRequired()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void InferTask(Func<Task> x) { }
-
- static void InferTaskOrTaskT(Func<Task> x) { }
- static void InferTaskOrTaskT(Func<Task<int>> x) { }
- static async Task F1()
- {
- return await Task.Factory.StartNew(() => 1);
- }
- static void Main()
- {
- Func<Task> F2 = async () => { await Task.Factory.StartNew(() => { }); return 1; };
- InferTask(async () => { return await Task.Factory.StartNew(() => 1); });
- InferTaskOrTaskT(async () => { return await Task.Factory.StartNew(() => 1); });
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (14,9): error CS1997: Since 'C.F1()' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task<T>'?
- // return await Task.Factory.StartNew(() => 1);
- Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("C.F1()").WithLocation(14, 9),
- // (19,79): error CS8030: Async lambda expression converted to a 'Task' returning delegate cannot return a value. Did you intend to return 'Task<T>'?
- // Func<Task> F2 = async () => { await Task.Factory.StartNew(() => { }); return 1; };
- Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithLocation(19, 79),
- // (20,33): error CS8030: Async lambda expression converted to a 'Task' returning delegate cannot return a value. Did you intend to return 'Task<T>'?
- // InferTask(async () => { return await Task.Factory.StartNew(() => 1); });
- Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithLocation(20, 33)
- );
- }
- [Fact]
- public void BadAsyncReturn()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class MyTask : Task
- {
- public MyTask(Action a) : base(a) { }
- }
- class C
- {
- async int F1()
- {
- await Task.Factory.StartNew(() => { });
- }
- async MyTask F2()
- {
- await Task.Factory.StartNew(() => { });
- }
- async T F3<T>()
- {
- await Task.Factory.StartNew(() => { });
- }
- async T F4<T>() where T : Task
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (17,18): error CS1983: The return type of an async method must be void, Task or Task<T>
- // async MyTask F2()
- Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F2"),
- // (22,13): error CS1983: The return type of an async method must be void, Task or Task<T>
- // async T F3<T>()
- Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F3"),
- // (27,13): error CS1983: The return type of an async method must be void, Task or Task<T>
- // async T F4<T>() where T : Task
- Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F4"),
- // (12,15): error CS1983: The return type of an async method must be void, Task or Task<T>
- // async int F1()
- Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F1"),
- // (12,15): error CS0161: 'C.F1()': not all code paths return a value
- // async int F1()
- Diagnostic(ErrorCode.ERR_ReturnExpected, "F1").WithArguments("C.F1()"),
- // (17,18): error CS0161: 'C.F2()': not all code paths return a value
- // async MyTask F2()
- Diagnostic(ErrorCode.ERR_ReturnExpected, "F2").WithArguments("C.F2()"),
- // (22,13): error CS0161: 'C.F3<T>()': not all code paths return a value
- // async T F3<T>()
- Diagnostic(ErrorCode.ERR_ReturnExpected, "F3").WithArguments("C.F3<T>()"),
- // (27,13): error CS0161: 'C.F4<T>()': not all code paths return a value
- // async T F4<T>() where T : Task
- Diagnostic(ErrorCode.ERR_ReturnExpected, "F4").WithArguments("C.F4<T>()"));
- }
- [Fact]
- public void CantConvAsyncAnonFuncReturns()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void Main()
- {
- Func<int> f1 = async () => await Task.Factory.StartNew(() => 1);
- Func<int> f2 = async () => { return await Task.Factory.StartNew(() => 1); };
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (9,24): error CS4010: Cannot convert async lambda expression to delegate type 'System.Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'System.Func<int>'.
- // Func<int> f1 = async () => await Task.Factory.StartNew(() => 1);
- Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "async () => await Task.Factory.StartNew(() => 1)").WithArguments("lambda expression", "System.Func<int>").WithLocation(9, 24),
- // (10,24): error CS4010: Cannot convert async lambda expression to delegate type 'System.Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'System.Func<int>'.
- // Func<int> f2 = async () => { return await Task.Factory.StartNew(() => 1); };
- Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "async () => { return await Task.Factory.StartNew(() => 1); }").WithArguments("lambda expression", "System.Func<int>").WithLocation(10, 24)
- );
- }
- [Fact]
- public void BadAsyncReturnExpression()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void InferTask_T(Func<Task<int>> x) { }
- static void Main()
- {
- Func<Task<int>> f1 = async () => await Task.Factory.StartNew(() => new Task<int>(null));
- Func<Task<int>> f2 = async () => { return await Task.Factory.StartNew(() => new Task<int>(null)); };
- InferTask_T(async () => await Task.Factory.StartNew(() => new Task<int>(() => 1)));
- InferTask_T(async () => { return await Task.Factory.StartNew(() => new Task<int>(() => 1)); });
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (11,42): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
- // Func<Task<int>> f1 = async () => await Task.Factory.StartNew(() => new Task<int>(null));
- Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(null))").WithArguments("int"),
- // (12,51): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
- // Func<Task<int>> f2 = async () => { return await Task.Factory.StartNew(() => new Task<int>(null)); };
- Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(null))").WithArguments("int"),
- // (14,33): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
- // InferTask_T(async () => await Task.Factory.StartNew(() => new Task<int>(() => 1)));
- Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(() => 1))").WithArguments("int"),
- // (15,42): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>'
- // InferTask_T(async () => { return await Task.Factory.StartNew(() => new Task<int>(() => 1)); });
- Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "await Task.Factory.StartNew(() => new Task<int>(() => 1))").WithArguments("int"));
- }
- [Fact]
- public void AsyncCantReturnVoid()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void InferVoid(Action x) { }
- static void InferTask_T<T>(Func<Task<T>> x) { }
- static void Infer_T<T>(Func<T> x) { }
- static void Main()
- {
- InferVoid(async () => { return await Task.Factory.StartNew(() => { }); });
- InferTask_T(async () => { return await Task.Factory.StartNew(() => { }); });
- Infer_T(async () => { return await Task.Factory.StartNew(() => { }); });
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
- // (13,33): error CS8029: Anonymous function converted to a void returning delegate cannot return a value
- // InferVoid(async () => { return await Task.Factory.StartNew(() => { }); });
- Diagnostic(ErrorCode.ERR_RetNoObjectRequiredLambda, "return").WithLocation(13, 33),
- // (14,42): error CS4029: Cannot return an expression of type 'void'
- // InferTask_T(async () => { return await Task.Factory.StartNew(() => { }); });
- Diagnostic(ErrorCode.ERR_CantReturnVoid, "await Task.Factory.StartNew(() => { })").WithLocation(14, 42),
- // (15,38): error CS4029: Cannot return an expression of type 'void'
- // Infer_T(async () => { return await Task.Factory.StartNew(() => { }); });
- Diagnostic(ErrorCode.ERR_CantReturnVoid, "await Task.Factory.StartNew(() => { })").WithLocation(15, 38)
- );
- }
- [Fact]
- public void InferAsyncReturn()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void InferVoid(Action x) { }
- static void InferTask(Func<Task> x) { }
- static void InferTask_T<T>(Func<Task<T>> x) { }
- static void Main()
- {
- InferVoid(async () => { await Task.Factory.StartNew(() => { }); });
- InferTask(async () => { await Task.Factory.StartNew(() => { return; }); });
- InferTask_T(async () => { return await Task.Factory.StartNew(() => 1); });
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics();
- }
- [Fact]
- public void BadInferAsyncReturn_T()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void Infer<T>(Func<bool, T> x) { }
- static void Main()
- {
- Infer(async (x) =>
- {
- await Task.Factory.StartNew(() => { });
- if (x)
- {
- return 1;
- }
- else
- {
- return;
- }
- });
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
- // (19,17): error CS0126: An object of a type convertible to 'int' is required
- // return;
- Diagnostic(ErrorCode.ERR_RetObjectRequired, "return").WithArguments("int"));
- }
- [Fact]
- public void BadInferAsyncReturnVoid()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void Infer(Action<bool> x) { }
- static void Main()
- {
- Infer(async (x) =>
- {
- await Task.Factory.StartNew(() => { });
- if (x)
- {
- return 1;
- }
- else
- {
- return;
- }
- });
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
- // (16,17): error CS8029: Anonymous function converted to a void returning delegate cannot return a value
- // return 1;
- Diagnostic(ErrorCode.ERR_RetNoObjectRequiredLambda, "return").WithLocation(16, 17)
- );
- }
- [Fact]
- public void BadInferAsyncReturnTask()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void Infer(Func<bool, Task> x) { }
- static void Main()
- {
- Infer(async (x) =>
- {
- await Task.Factory.StartNew(() => { });
- if (x)
- {
- return 1;
- }
- else
- {
- return;
- }
- });
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
- // (16,17): error CS8030: Async lambda expression converted to a 'Task' returning delegate cannot return a value. Did you intend to return 'Task<T>'?
- // return 1;
- Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithLocation(16, 17)
- );
- }
- [Fact]
- public void BadInferAsyncReturnTask_T()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- static void Infer<T>(Func<bool, Task<T>> x) { }
- static void Main()
- {
- Infer(async (x) =>
- {
- await Task.Factory.StartNew(() => { });
- if (x)
- {
- return 1;
- }
- else
- {
- return;
- }
- });
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics(
- // (19,17): error CS0126: An object of a type convertible to 'int' is required
- // return;
- Diagnostic(ErrorCode.ERR_RetObjectRequired, "return").WithArguments("int"));
- }
- [Fact]
- public void TaskReturningAsyncWithoutReturn()
- {
- var source = @"
- using System.Threading.Tasks;
- class C
- {
- async static Task F()
- {
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (6,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
- // async static Task F()
- Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "F"));
- }
- [Fact]
- public void TestAsyncReturnsNullableT()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- async static Task<int?> F()
- {
- await Task.Factory.StartNew(() => { });
- return null;
- }
- static void Main()
- {
- Func<Task<int?>> f1 = async () => await Task.Factory.StartNew<int?>(() => { return null; });
- Func<Task<int?>> f2 = async () => { return await Task.Factory.StartNew<int?>(() => { return null; }); };
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- }
- [Fact]
- public void VarargsAsync()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1(__arglist)
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (6,23): error CS4006: __arglist is not allowed in the parameter list of async methods
- // async static Task M1(__arglist)
- Diagnostic(ErrorCode.ERR_VarargsAsync, "M1"));
- }
- [Fact]
- public void VarargsAsyncGeneric()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1<T>(__arglist)
- {
- await Task.Factory.StartNew(() => { });
- return;
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (6,23): error CS0224: A method with vararg cannot be generic, be in a generic type, or have a params parameter
- // async static Task M1<T>(__arglist)
- Diagnostic(ErrorCode.ERR_BadVarargs, "M1"));
- }
- [Fact]
- public void VarargsAsyncInGenericClass()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1<T>(__arglist)
- {
- await Task.Factory.StartNew(() => { });
- return;
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (6,23): error CS0224: A method with vararg cannot be generic, be in a generic type, or have a params parameter
- // async static Task M1<T>(__arglist)
- Diagnostic(ErrorCode.ERR_BadVarargs, "M1"));
- }
- [Fact]
- public void UnsafeAsyncArgType()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- unsafe async static Task M1(int* i) { }
- }";
- CreateCompilationWithMscorlib45(source, null, TestOptions.Dll.WithAllowUnsafe(true)).VerifyDiagnostics(
- // (6,38): error CS4005: Async methods cannot have unsafe parameters or return types
- // unsafe async static Task M1(int* i)
- Diagnostic(ErrorCode.ERR_UnsafeAsyncArgType, "i"),
- // (6,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
- // unsafe async static Task M1(ref int* i)
- Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M1"));
- }
- [Fact]
- public void Ref_and_UnsafeAsyncArgType()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- unsafe async static Task M1(ref int* i) { }
- }";
- CreateCompilationWithMscorlib45(source, null, TestOptions.UnsafeDll).VerifyDiagnostics(
- // (6,42): error CS1988: Async methods cannot have ref or out parameters
- // unsafe async static Task M1(ref int* i)
- Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i"),
- // (6,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
- // unsafe async static Task M1(ref int* i)
- Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M1"));
- }
- [Fact]
- public void RefAsyncArgType()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1(ref int i)
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (6,42): error CS1988: Async methods cannot have ref or out parameters
- // unsafe async static Task M1(ref int* i) { }
- Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i"));
- }
- [Fact]
- public void OutAsyncArgType()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1(out int i)
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (6,34): error CS1988: Async methods cannot have ref or out parameters
- // async static Task M1(out int i) { }
- Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i"));
- }
- [Fact]
- public void BadAwaitWithoutAsync()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class MyAttribute : Attribute {
- public MyAttribute(int i) { }
- }
- [MyAttribute(await C.t)]
- class C
- {
- public static Task<int> t = new Task<int>(() => 1);
- int i = await t;
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (9,14): error CS1992: The 'await' operator can only be used when contained within a method or lambda expression marked with the 'async' modifier
- // [MyAttribute(await C.t)]
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsync, "await C.t"),
- // (14,13): error CS1992: The 'await' operator can only be used when contained within a method or lambda expression marked with the 'async' modifier
- // int i = await t;
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsync, "await t"));
- }
- [Fact]
- public void BadAwaitWithoutAsync_AnonMeth_Lambda()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- public static void Main()
- {
- Action f1 = delegate() { await Task.Factory.StartNew(() => { }); };
- Action f2 = () => await Task.Factory.StartNew(() => { });
- Action f3 = () => { await Task.Factory.StartNew(() => { }); };
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (9,34): error CS4034: The 'await' operator can only be used within an async anonymous method. Consider marking this anonymous method with the 'async' modifier.
- // Action f1 = delegate() { await Task.Factory.StartNew(() => { }); };
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await Task.Factory.StartNew(() => { })").WithArguments("anonymous method"),
- // (10,27): error CS4034: The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
- // Action f2 = () => await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await Task.Factory.StartNew(() => { })").WithArguments("lambda expression"),
- // (11,29): error CS4034: The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
- // Action f3 = () => { await Task.Factory.StartNew(() => { }); };
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await Task.Factory.StartNew(() => { })").WithArguments("lambda expression"));
- }
- [Fact]
- public void IDS_BadAwaitWithoutAsyncMethod_VoidMethod()
- {
- var source = @"
- using System.Threading.Tasks;
- class C
- {
- public static void F()
- {
- await Task.Factory.StartNew(() => { });
- }
- public static int G()
- {
- return await Task.Factory.StartNew(() => 1);
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (8,9): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await Task.Factory.StartNew(() => { })"),
- // (13,16): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<int>'.
- // return await Task.Factory.StartNew(() => 1);
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => 1)").WithArguments("int"));
- }
- [Fact]
- public void IDS_BadAwaitAsDefaultParam()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- static Task t = new Task(null);
- class await { }
- static int Foo(int[] arr = await t)
- {
- return arr.Length;
- }
- static int Main()
- {
- return 1;
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- /// (10,32): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<int>'.
- // static int Foo(int[] arr = await t)
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await t").WithArguments("int"),
- // (10,26): error CS1750: A value of type '?' cannot be used as a default parameter because there are no standard conversions to type 'int[]'
- // static int Foo(int[] arr = await t)
- Diagnostic(ErrorCode.ERR_NoConversionForDefaultParam, "arr").WithArguments("?", "int[]"));
- }
- [Fact]
- public void BadAwaitInFinally()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1() {
- try
- {
- }
- catch
- {
- try
- {
- }
- catch
- {
- }
- finally
- {
- await Task.Factory.StartNew(() => { });
- }
- }
- finally
- {
- try
- {
- }
- catch
- {
- await Task.Factory.StartNew(() => { });
- }
- finally
- {
- }
- }
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- }
- [Fact]
- public void BadAwaitInCatch()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1() {
- try
- {
- }
- catch
- {
- await Task.Factory.StartNew(() => { });
- }
- finally
- {
- }
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- }
- [Fact]
- public void BadAwaitInCatchFilter()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1()
- {
- try
- {
- }
- catch if (await Task.Factory.StartNew(() => false))
- {
- }
- finally
- {
- }
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (11,19): error CS7094: Cannot await in the filter expression of a catch clause
- // catch if (await Task.Factory.StartNew(() => false))
- Diagnostic(ErrorCode.ERR_BadAwaitInCatchFilter, "await Task.Factory.StartNew(() => false)").WithLocation(11, 19)
- );
- }
- [Fact]
- public void BadAwaitInLock()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- async static Task M1() {
- lock (new object())
- {
- await Task.Factory.StartNew(() => { });
- try
- {
- }
- catch
- {
- await Task.Factory.StartNew(() => { });
- }
- finally
- {
- await Task.Factory.StartNew(() => { });
- }
- }
- try
- {
- }
- catch
- {
- lock (new object())
- {
- await Task.Factory.StartNew(() => { });
- }
- }
- finally
- {
- lock (new object())
- {
- await Task.Factory.StartNew(() => { });
- }
- }
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (10,13): error CS1996: Cannot await in the body of a lock statement
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
- // (17,17): error CS1996: Cannot await in the body of a lock statement
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
- // (21,17): error CS1996: Cannot await in the body of a lock statement
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
- // (32,17): error CS1996: Cannot await in the body of a lock statement
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"),
- // (39,17): error CS1996: Cannot await in the body of a lock statement
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await Task.Factory.StartNew(() => { })"));
- }
- [Fact]
- public void BadAwaitInLock2()
- {
- var source = @"
- using System.Threading.Tasks;
- class Program
- {
- async void Test()
- {
- lock(await M()) // fine, not in body of lock
- lock (await M()) // error, in body of outer lock
- {
- await M(); // error, in body of inner lock
- }
- }
- async Task<object> M()
- {
- return await M();
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (9,19): error CS1996: Cannot await in the body of a lock statement
- // lock (await M()) // error, in body of outer lock
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await M()"),
- // (11,17): error CS1996: Cannot await in the body of a lock statement
- // await M(); // error, in body of inner lock
- Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await M()"));
- }
- [Fact]
- public void AwaitingInLockExpressionsIsActuallyOK()
- {
- var source = @"
- using System.Threading.Tasks;
- class Driver
- {
- public static async void F()
- {
- object o = new object();
- lock(await Task.Factory.StartNew(() => o))
- {
-
- }
- }
- static void Main() { }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- }
- [WorkItem(611150, "DevDiv")]
- [Fact]
- public void AwaitInLambdaInLock()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- static void Main()
- {
- lock (new object())
- {
- Task.Run(async () => { await Task.Factory.StartNew(() => { }); });
- Task.Run(async () => await Task.Factory.StartNew(() => { }));
- Task.Run(async delegate () { await Task.Factory.StartNew(() => { }); });
- }
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- }
- [Fact]
- public void BadAwaitInUnsafeContext()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- unsafe async static Task M1() {
- await Task.Factory.StartNew(() => { }); // not OK
- }
- async static Task M2()
- {
- await Task.Factory.StartNew(() => { }); // OK
- unsafe
- {
- await Task.Factory.StartNew(() => { }); // not OK
- }
- }
- }";
- CreateCompilationWithMscorlib45(source, compOptions: TestOptions.UnsafeDll).VerifyDiagnostics(
- // (7,9): error CS4004: Cannot await in an unsafe context
- // await Task.Factory.StartNew(() => { }); // not OK
- Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Factory.StartNew(() => { })"),
- // (16,13): error CS4004: Cannot await in an unsafe context
- // await Task.Factory.StartNew(() => { }); // not OK
- Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Factory.StartNew(() => { })"));
- }
- [Fact]
- public void BadAwaitWithoutAsyncInBadContext()
- {
- var source = @"
- using System.Threading.Tasks;
- class Test
- {
- static Task M2()
- {
- await Task.Factory.StartNew(() => { });
- unsafe
- {
- await Task.Factory.StartNew(() => { });
- }
- try
- {
- }
- catch
- {
- await Task.Factory.StartNew(() => { });
- }
- finally
- {
- await Task.Factory.StartNew(() => { });
- }
- }
- }";
- CreateCompilationWithMscorlib45(source, compOptions: TestOptions.UnsafeDll).VerifyDiagnostics(
- // (8,9): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(8, 9),
- // (12,13): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(12, 13),
- // (12,13): error CS4004: Cannot await in an unsafe context
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await Task.Factory.StartNew(() => { })").WithLocation(12, 13),
- // (20,13): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(20, 13),
- // (24,13): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<System.Threading.Tasks.Task>'.
- // await Task.Factory.StartNew(() => { });
- Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await Task.Factory.StartNew(() => { })").WithArguments("System.Threading.Tasks.Task").WithLocation(24, 13),
- // (6,17): error CS0161: 'Test.M2()': not all code paths return a value
- // static Task M2()
- Diagnostic(ErrorCode.ERR_ReturnExpected, "M2").WithArguments("Test.M2()").WithLocation(6, 17)
- );
- }
- [Fact]
- public void AsyncExplicitInterfaceImplementation()
- {
- var source = @"
- using System.Threading.Tasks;
- interface IInterface
- {
- void F();
- }
- class C : IInterface
- {
- async void IInterface.F()
- {
- await Task.Factory.StartNew(() => { });
- }
- static void Main()
- {
-
- }
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
- }
- [Fact]
- public void AsyncInterfaceMember()
- {
- var source = @"
- interface IInterface
- {
- async void F();
- }";
- CreateCompilationWithMscorlib45(source).VerifyDiagnostics(
- // (4,16): error CS0106: The modifier 'async' is not valid for this item
- // async void F();
- Diagnostic(ErrorCode.ERR_BadMemberFlag, "F").WithArguments("async"));
- }
- [Fact]
- public void MainCantBeAsync()
- {
- var source = @"
- using System.Threading.Tasks;
- class A
- {
- async static void Main()
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source, compOptions: TestOptions.Exe).VerifyDiagnostics(
- // (4,23): error CS4009: 'A.Main()': an entry point cannot be marked with the 'async' modifier
- // async static void Main()
- Diagnostic(ErrorCode.ERR_MainCantBeAsync, "Main").WithArguments("A.Main()"));
- }
- [Fact]
- public void MainCantBeAsync_AndGeneric()
- {
- var source = @"
- using System.Threading.Tasks;
- class A
- {
- async static void Main<T>()
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source, compOptions: TestOptions.Exe).VerifyDiagnostics(
- // (4,23): warning CS0402: 'A.Main<T>()': an entry point cannot be generic or in a generic type
- // async static void Main<T>()
- Diagnostic(ErrorCode.WRN_MainCantBeGeneric, "Main").WithArguments("A.Main<T>()"),
- // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
- Diagnostic(ErrorCode.ERR_NoEntryPoint));
- }
- [Fact]
- public void MainCantBeAsync_AndBadSig()
- {
- var source = @"
- using System.Threading.Tasks;
- class A
- {
- async static void Main(bool truth)
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source, compOptions: TestOptions.Exe).VerifyDiagnostics(
- // (4,23): warning CS0028: 'A.Main(bool)' has the wrong signature to be an entry point
- // async static void Main(bool truth)
- Diagnostic(ErrorCode.WRN_InvalidMainSig, "Main").WithArguments("A.Main(bool)"),
- // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
- Diagnostic(ErrorCode.ERR_NoEntryPoint));
- }
- [Fact]
- public void MainCantBeAsync_AndGeneric_AndBadSig()
- {
- var source = @"
- using System.Threading.Tasks;
- class A
- {
- async static void Main<T>(bool truth)
- {
- await Task.Factory.StartNew(() => { });
- }
- }";
- CreateCompilationWithMscorlib45(source, compOptions: TestOptions.Exe).VerifyDiagnostics(
- // (4,23): warning CS0028: 'A.Main<T>(bool)' has the wrong signature to be an entry point
- // async static void Main<T>(bool truth)
- Diagnostic(ErrorCode.WRN_InvalidMainSig, "Main").WithArguments("A.Main<T>(bool)"),
- // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
- Diagnostic(ErrorCode.ERR_NoEntryPoint));
- }
- [Fact]
- public void AwaitInQuery_FirstCollectionExpressionOfInitialFrom()
- {
- var source = @"
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- async static Task<List<int>> F1()
- {
- return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
- }
- async static void F2()
- {
- await Task.Factory.StartNew(() => { });
- var ls = new List<int>() {1, 2, 3};
- var xs = from l in await F1() where l > 1 select l;
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics();
- }
- [Fact]
- public void AwaitInQuery_CollectionExpressionOfJoin()
- {
- var source = @"
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- async static Task<List<int>> F1()
- {
- return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
- }
- async static void F2()
- {
- await Task.Factory.StartNew(() => { });
- var ls = new List<int>() {1, 2, 3};
- var xs = from l in ls
- join l2 in await F1() on l equals l2
- where l > 1 select l;
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics();
- }
- [Fact]
- public void BadAwaitInQuery_QueryBody()
- {
- var source = @"
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- async static Task<List<int>> F1()
- {
- return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
- }
- async static void F2()
- {
- await Task.Factory.StartNew(() => { });
- var ls = new List<int>() {1, 2, 3};
- var xs = from l in ls
- where l > 1 select await F1();
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[]{ SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
- // (20,37): error 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
- // where l > 1 select await F1();
- Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
- }
- [Fact]
- public void BadAwaitInQuery_FirstCollectionExpressionOfInitialFrom_InsideQueryBody()
- {
- var source = @"
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- async static Task<List<int>> F1()
- {
- return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
- }
- async static void F2()
- {
- await Task.Factory.StartNew(() => { });
- var ls = new List<int>() { 1, 2, 3 };
- var xs = from l in ls
- where l > 1
- select (from l2 in await F1() where l2 > 1 select l2);
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
- // (21,37): error 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
- // select (from l2 in await F1() where l2 > 1 select l2);
- Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
- }
- [Fact]
- public void BadAwaitInQuery_CollectionExpressionOfJoin_InsideQueryBody()
- {
- var source = @"
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- async static Task<List<int>> F1()
- {
- return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 });
- }
- async static void F2()
- {
- await Task.Factory.StartNew(() => { });
- var ls = new List<int>() { 1, 2, 3 };
- var xs = from l in ls
- where l > 1
- select (from l2 in ls
- join l3 in await F1() on l2 equals l3
- where l2 > 1
- select l2);
- }
- }";
- CreateCompilationWithMscorlib45(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics(
- // (22,37): error 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
- // join l3 in await F1() on l2 equals l3
- Diagnostic(ErrorCode.ERR_BadAwaitInQuery, "await F1()"));
- }
- [Fact]
- public void BadAwaitWithoutAsyncInUnsafeQuery()
- {
- var source = @"
- using System.Linq;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- async static Task<List<int>>…
Large files files are truncated, but you can click here to view the full file