/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTests.cs
4 161 строка
150 KB
Jan Jones
Unsafe evolution: allow await in unsafe context (#84616)
11 авг 2026, 16:19
Не верифицирован
11 авг 2026, 16:19
461c2ef
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Generic; using System.Linq; using System.Threading; 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 = CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); var method = (SourceMemberMethodSymbol)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 = CreateCompilationWithMscorlib461(new SyntaxTree[] { tree }).VerifyDiagnostics(); var model = compilation.GetSemanticModel(tree); var simple = tree.GetCompilationUnitRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().Single(); Assert.True(((IMethodSymbol)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(((IMethodSymbol)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 = CreateCompilationWithMscorlib461(new SyntaxTree[] { tree }).VerifyDiagnostics(); var model = compilation.GetSemanticModel(tree); var del = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousMethodExpressionSyntax>().Single(); Assert.True(((IMethodSymbol)model.GetSymbolInfo(del).Symbol).IsAsync); } [Fact] public void BadAsyncConstructor() { var source = @" class C { async public C() { } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async")); } [Fact] public void BadAsyncDestructor() { var source = @" class C { async extern ~C(); }"; CreateCompilationWithMscorlib461(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; }"; CreateCompilationWithMscorlib461(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; }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "i").WithArguments("async")); } [Fact] public void BadAsyncClass() { var source = @" public async class C { }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("async")); } [Fact] public void BadAsyncStruct() { var source = @" internal async struct S { }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "S").WithArguments("async")); } [Fact] public void BadAsyncInterface() { var source = @" internal async interface I { }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "I").WithArguments("async")); } [Fact] public void BadAsyncDelegate() { var source = @" public async delegate void MyDelegate(); "; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async")); } [Fact] public void BadAsyncProperty() { var source = @" public async delegate void MyDelegate(); "; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( Diagnostic(ErrorCode.ERR_BadMemberFlag, "MyDelegate").WithArguments("async")); } [Fact] public void BadAsyncPropertyAccessor() { var source = @" public async delegate void MyDelegate(); "; CreateCompilationWithMscorlib461(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); }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (14,9): error CS1997: Since 'C.F1()' is an async method that returns 'System.Threading.Tasks.Task', a return keyword must not be followed by an object expression // return await Task.Factory.StartNew(() => 1); Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("C.F1()", "System.Threading.Tasks.Task").WithLocation(14, 9), // (19,79): error CS8030: Async lambda expression converted to a 'System.Threading.Tasks.Task' returning delegate cannot return a value // Func<Task> F2 = async () => { await Task.Factory.StartNew(() => { }); return 1; }; Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithArguments("System.Threading.Tasks.Task").WithLocation(19, 79), // (20,33): error CS8030: Async lambda expression converted to a 'System.Threading.Tasks.Task' returning delegate cannot return a value // InferTask(async () => { return await Task.Factory.StartNew(() => 1); }); Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithArguments("System.Threading.Tasks.Task").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(() => { }); } }"; CreateCompilationWithMscorlib461(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); }; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (9,33): error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'. // Func<int> f1 = async () => await Task.Factory.StartNew(() => 1); Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "=>").WithArguments("lambda expression", "System.Func<int>").WithLocation(9, 33), // (10,33): error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'. // Func<int> f2 = async () => { return await Task.Factory.StartNew(() => 1); }; Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "=>").WithArguments("lambda expression", "System.Func<int>").WithLocation(10, 33) ); } [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)); }); } }"; CreateCompilationWithMscorlib461(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", "System.Threading.Tasks.Task<int>").WithLocation(11, 42), // (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", "System.Threading.Tasks.Task<int>").WithLocation(12, 51), // (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", "System.Threading.Tasks.Task<int>").WithLocation(14, 33), // (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", "System.Threading.Tasks.Task<int>").WithLocation(15, 42)); } [Fact] public void BadAsyncReturnExpression_ValueTask() { var source = @" using System.Threading.Tasks; static async ValueTask<int> M() { await Task.Yield(); return new ValueTask<int>(); } await M(); "; CreateCompilationWithTasksExtensions(source).VerifyDiagnostics( // (6,12): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'ValueTask<int>' // return new ValueTask<int>(); Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "new ValueTask<int>()").WithArguments("int", "System.Threading.Tasks.ValueTask<int>").WithLocation(6, 12) ); } [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(() => { }); }); } }"; CreateCompilationWithMscorlib461(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); }); } }"; CreateCompilationWithMscorlib461(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; } }); } }"; CreateCompilationWithMscorlib461(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; } }); } }"; CreateCompilationWithMscorlib461(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; } }); } }"; CreateCompilationWithMscorlib461(source, new MetadataReference[] { LinqAssemblyRef, SystemRef }).VerifyDiagnostics( // (16,17): error CS8030: Async lambda expression converted to a 'System.Threading.Tasks.Task' returning delegate cannot return a value // return 1; Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequiredLambda, "return").WithArguments("System.Threading.Tasks.Task").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; } }); } }"; CreateCompilationWithMscorlib461(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() { } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [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; }); }; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void VarargsAsync() { var source = @" using System.Threading.Tasks; class Test { async static Task M1(__arglist) { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(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; } }"; CreateCompilationWithMscorlib461(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; } }"; CreateCompilationWithMscorlib461(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) { } }"; CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (6,38): error CS4005: Async methods cannot have pointer type parameters // unsafe async static Task M1(int* i) Diagnostic(ErrorCode.ERR_UnsafeAsyncArgType, "i")); } [Fact] public void UnsafeAsyncArgType_FunctionPointer() { var source = @" using System.Threading.Tasks; class Test { unsafe async static Task M1(delegate*<void> i) { } }"; CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (6,49): error CS4005: Async methods cannot have pointer type parameters // unsafe async static Task M1(delegate*<void> i) { } Diagnostic(ErrorCode.ERR_UnsafeAsyncArgType, "i").WithLocation(6, 49) ); } [Fact] public void UnsafeAsyncArgType_PointerArray() { var source = @" using System.Threading.Tasks; class Test { unsafe async static Task M1(int*[] i) { await Task.Yield(); } // 1 unsafe async static Task M2(delegate*<void>[] i) { await Task.Yield(); } // 2 async static Task M3(int*[] i) { await Task.Yield(); } // 3 async static Task M4(delegate*<void>[] i) { await Task.Yield(); } // 4 }"; CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular14) .VerifyDiagnostics( // (6,45): error CS8652: The feature 'updated memory safety rules' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // unsafe async static Task M1(int*[] i) { await Task.Yield(); } // 1 Diagnostic(ErrorCode.ERR_FeatureInPreview, "await").WithArguments("updated memory safety rules").WithLocation(6, 45), // (7,56): error CS8652: The feature 'updated memory safety rules' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // unsafe async static Task M2(delegate*<void>[] i) { await Task.Yield(); } // 2 Diagnostic(ErrorCode.ERR_FeatureInPreview, "await").WithArguments("updated memory safety rules").WithLocation(7, 56), // (8,26): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // async static Task M3(int*[] i) { await Task.Yield(); } // 3 Diagnostic(ErrorCode.ERR_UnsafeNeeded, "int*").WithLocation(8, 26), // (9,26): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context // async static Task M4(delegate*<void>[] i) { await Task.Yield(); } // 4 Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(9, 26) ); CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll) .VerifyEmitDiagnostics(); CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.RegularNext) .VerifyEmitDiagnostics(); } [Fact] public void Ref_and_UnsafeAsyncArgType() { var source = @" using System.Threading.Tasks; class Test { unsafe async static Task M1(ref int* i) { } }"; CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (6,42): error CS1988: Async methods cannot have ref, in or out parameters // unsafe async static Task M1(ref int* i) Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i")); } [Fact] public void RefAsyncArgType() { var source = @" using System.Threading.Tasks; class Test { async static Task M1(ref int i) { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (6,42): error CS1988: Async methods cannot have ref, in 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(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (6,34): error CS1988: Async methods cannot have ref, in or out parameters // async static Task M1(out int i) { } Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i")); } [Fact] public void InAsyncArgType() { var source = @" using System.Threading.Tasks; class Test { async static Task M1(in int i) { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (6,33): error CS1988: Async methods cannot have ref, in or out parameters // async static Task M1(in int i) Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i").WithLocation(6, 33) ); } [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; }"; CreateCompilationWithMscorlib461(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(() => { }); }; } }"; CreateCompilationWithMscorlib461(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); } }"; CreateCompilationWithMscorlib461(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 Goo(int[] arr = await t) { return arr.Length; } static int Main() { return 1; } }"; CreateCompilationWithMscorlib461(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 Goo(int[] arr = await t) Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await t").WithArguments("int").WithLocation(10, 32) ); } [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 { } } } }"; CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5)).VerifyDiagnostics( // (20,17): error CS1984: Cannot await in the body of a finally clause // await Task.Factory.StartNew(() => { }); Diagnostic(ErrorCode.ERR_BadAwaitInFinally, "await Task.Factory.StartNew(() => { })").WithLocation(20, 17), // (30,17): error CS1984: Cannot await in the body of a finally clause // await Task.Factory.StartNew(() => { }); Diagnostic(ErrorCode.ERR_BadAwaitInFinally, "await Task.Factory.StartNew(() => { })").WithLocation(30, 17) ); CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics(); } [Fact] public void BadAwaitInCatch() { var source = @" using System.Threading.Tasks; class Test { async static Task M1() { try { } catch { await Task.Factory.StartNew(() => { }); } finally { } } }"; CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5)).VerifyDiagnostics( // (12,13): error CS1985: Cannot await in a catch clause // await Task.Factory.StartNew(() => { }); Diagnostic(ErrorCode.ERR_BadAwaitInCatch, "await Task.Factory.StartNew(() => { })").WithLocation(12, 13) ); CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics(); } [Fact] public void BadAwaitInCatchFilter() { var source = @" using System.Threading.Tasks; class Test { async static Task M1() { try { } catch when (await Task.Factory.StartNew(() => false)) { } finally { } } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (11,19): error CS7094: Cannot await in the filter expression of a catch clause // catch when (await Task.Factory.StartNew(() => false)) Diagnostic(ErrorCode.ERR_BadAwaitInCatchFilter, "await Task.Factory.StartNew(() => false)").WithLocation(11, 21) ); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80331")] public void BadSpreadInCatchFilter() { var source = """ using System; using System.Collections; using System.Collections.Generic; public class C { // Use a custom list type to ensure that an AddRange isn't used public class MyList<T> : IEnumerable<T> { public void Add(T s) { throw null!; } public class MyEnumerator : IEnumerator<T> { public bool MoveNext() => false; public void Dispose() { } public void Reset() { } public T Current { get { throw null!; } } object IEnumerator.Current { get { throw null!; } } } public IEnumerator<T> GetEnumerator() { throw null!; } IEnumerator IEnumerable.GetEnumerator() { throw null!; } public int Count; } public class MyException : Exception { public IEnumerable<String> Strings = []; } public bool A(MyList<string> s) { return false; } public void M() { try { throw new Exception(); } catch (MyException e) when (A([.. e.Strings, "foo"])) { } } } """; CreateCompilation(source).VerifyEmitDiagnostics( // (38,40): error CS9332: Cannot use '..' spread operator in the filter expression of a catch clause // catch (MyException e) when (A([.. e.Strings, "foo"])) Diagnostic(ErrorCode.ERR_BadSpreadInCatchFilter, ".. e.Strings").WithLocation(38, 40) ); } [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(() => { }); } } } }"; CreateCompilationWithMscorlib461(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(); } }"; CreateCompilationWithMscorlib461(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() { } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [WorkItem(611150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611150")] [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(() => { }); }); } } }"; CreateCompilationWithMscorlib461(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 } } }"; CreateCompilationWithMscorlib461(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular14).VerifyDiagnostics( // (7,9): error CS8652: The feature 'updated memory safety rules' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // await Task.Factory.StartNew(() => { }); // not OK Diagnostic(ErrorCode.ERR_FeatureInPreview, "await").WithArguments("updated memory safety rules").WithLocation(7, 9), // (16,13): error CS8652: The feature 'updated memory safety rules' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // await Task.Factory.StartNew(() => { }); // not OK Diagnostic(ErrorCode.ERR_FeatureInPreview, "await").WithArguments("updated memory safety rules").WithLocation(16, 13)); } [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(() => { }); } } }"; CreateCompilationWithMscorlib461(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular14).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 CS8652: The feature 'updated memory safety rules' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // await Task.Factory.StartNew(() => { }); Diagnostic(ErrorCode.ERR_FeatureInPreview, "await").WithArguments("updated memory safety rules").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() { } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void AsyncInterfaceMember() { var source = @" interface IInterface { async void F(); }"; CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular7).VerifyDiagnostics( // (4,16): error CS8503: The modifier 'async' is not valid for this item in C# 7. Please use language version 'preview' or greater. // async void F(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F").WithArguments("async", "7.0", "8.0").WithLocation(4, 16), // (4,16): error CS1994: The 'async' modifier can only be used in methods that have a body. // async void F(); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "F").WithLocation(4, 16) ); } [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; } }"; CreateCompilationWithMscorlib461(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; } }"; CreateCompilationWithMscorlib461(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(); } }"; CreateCompilationWithMscorlib461(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); } }"; CreateCompilationWithMscorlib461(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); } }"; CreateCompilationWithMscorlib461(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>> F1() { return await Task.Factory.StartNew(() => new List<int>() { 1, 2, 3 }); } static void F2() { var ls = new List<int>() { 1, 2, 3 }; unsafe { 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); } } }"; var c = CreateCompilationWithMscorlib461( source, new MetadataReference[] { SystemRef, LinqAssemblyRef }, TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular14); c.VerifyDiagnostics( // (22,41): error CS8652: The feature 'updated memory safety rules' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // join l3 in await F1() on l2 equals l3 Diagnostic(ErrorCode.ERR_FeatureInPreview, "await").WithArguments("updated memory safety rules").WithLocation(22, 41), // (22,41): 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 BadAwaitWithoutAsyncInQuery() { 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 }); } static void F2() { 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); } }"; CreateCompilationWithMscorlib461( source, new MetadataReference[] { SystemRef, LinqAssemblyRef }, TestOptions.ReleaseDll).VerifyDiagnostics( // (22,41): 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 BadAwaitWithoutAsyncInLegalQueryRegion() { 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 }); } static void F2() { var ls = new List<int>() { 1, 2, 3 }; var xs = from l in await F1() where l > 1 select l; } }"; CreateCompilationWithMscorlib461(source, new MetadataReference[] { SystemRef, LinqAssemblyRef }).VerifyDiagnostics( // (17,28): 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'. // var xs = from l in await F1() Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await F1()")); } [Fact] public void AsyncLacksAwaits() { var source = @" using System; using System.Threading.Tasks; class Test { async static Task M() { } static void Main() { Action f1 = async () => new Action(() => { })(); Action f2 = async () => { }; Func<Task<int>> f3 = async () => { return 1; }; Action f4 = async delegate () { }; Func<Task<int>> f5 = async delegate () { return 1; }; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void UnobservedAwaitableExpression() { var source = @" using System.Threading.Tasks; class Test { public static async Task F1() { await Task.Factory.StartNew(() => 1); } public static async Task<int> F2(bool truth) { for (F1(); truth; F1()) ; for (F1(), F1(); truth; F1(), F1()) ; return await Task.Factory.StartNew(() => 1); } static void Main() { F2(false); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (F1(); truth; F1()) ; Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"), // (13,27): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (F1(); truth; F1()) ; Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"), // (15,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (F1(), F1(); truth; F1(), F1()) ; Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"), // (15,20): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (F1(), F1(); truth; F1(), F1()) ; Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"), // (15,33): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (F1(), F1(); truth; F1(), F1()) ; Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"), // (15,39): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (F1(), F1(); truth; F1(), F1()) ; Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F1()"), // (22,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // F2(false); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "F2(false)")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait01() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; class Test { public async void Meth() { await Task.Delay(10); Goo(); } public async Task<int> Goo() { await Task.Delay(10); return 1; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (16,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait02() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; class Test { public async Task Meth() { Goo(); foreach (var x in new int[] { 1, 2 }) { Goo(); } while (await Goo()) { Goo(); } } public async Task<dynamic> Goo() { return 1; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics( // (19,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (22,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (27,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait03() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; public delegate Task<decimal?> Bar(); class Test { static async Task<object> Meth() { Goo(); Bar bar = Goo; bar(); return (object)""""; } static async Task<decimal?> Goo() { return null; } static Task Meth2() { Goo(); Bar bar = Goo; bar(); return Task.Run(async () => { await Task.Delay(10); }); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (21,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (24,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // bar(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "bar()"), // (36,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait04() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; class C1{} static class Extension { public static Task<C1> MethExt(this int i) { return Task.Run(async () => new C1()); } } class Test { static async Task<T> Meth<T>(T t) { int i = 0; i.MethExt(); Goo(1); return t; } static Task<T> Goo<T>(T t) { return Task.Run(async () => { return t; }); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (19,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.MethExt(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MethExt()").WithLocation(19, 9), // (20,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo(1)").WithLocation(20, 9)); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait05() { // invoke a method that returns an awaitable type in an async method var source = @" using System; using System.Threading.Tasks; class Test { static async Task<dynamic> Meth1() { throw new EntryPointNotFoundException(); Goo(); return """"; } static async Task<decimal?> Meth2() { Goo(); throw new DuplicateWaitObjectException(); return null; } static async Task<decimal?> Goo() { return null; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics( // (23,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (23,9): warning CS0162: Unreachable code detected // Goo(); Diagnostic(ErrorCode.WRN_UnreachableCode, "Goo"), // (29,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (31,9): warning CS0162: Unreachable code detected // return null; Diagnostic(ErrorCode.WRN_UnreachableCode, "return")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait05_b() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; class Test { static async Task<dynamic> Meth1() { return """"; Goo(); } static int Meth2() { return 2; Goo(); } static async Task<double?> Goo() { return null; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics( // (22,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (22,9): warning CS0162: Unreachable code detected // Goo(); Diagnostic(ErrorCode.WRN_UnreachableCode, "Goo"), // (28,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (28,9): warning CS0162: Unreachable code detected // Goo(); Diagnostic(ErrorCode.WRN_UnreachableCode, "Goo")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait06() { // invoke a method that returns an awaitable type in an async method var source = @" using System; using System.Threading.Tasks; class Test { static async Task<T> Meth<T>(T t) { await Task.Delay(10); return t; } static async Task<T> Goo<T>(T t) { Func<Task<int>> f = async () => { await Task.Delay(10); Meth(1); return 2; }; f(); Func<Task<Func<Task<int>>>> ff = async delegate() { Meth((dynamic)5.1); await Task.Delay(10); return (Func<Task<int>>)(async () => { Meth(""""); await Task.Delay(10); return 3; }); }; ff(); (await ff())(); return t; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (30,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"), // (33,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // f(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "f()"), // (41,25): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(""); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"), // (47,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // ff(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "ff()"), // (49,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // (await ff())(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "(await ff())()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait07() { // invoke a method that returns an awaitable type in an async method var source = @" using System; using System.Threading; using System.Threading.Tasks; struct MyDisp : IDisposable { public static int DisposeCalledCount; public void Dispose() { DisposeCalledCount++; TestCase.DisposeCalled++; } public MyDisp(int Count = 0) { DisposeCalledCount = 0; } } class TestCase { private int tests; public static int DisposeCalled; public async Task Meth(MyDisp x) { await Task.Delay(10); } public async void Run() { this.tests = 0; TestCase.DisposeCalled = 0; //using statement inside async void sub tests++; using (var x = new MyDisp()) { Meth(x); } if (MyDisp.DisposeCalledCount == TestCase.DisposeCalled) Driver.Count++; //using statement inside Task returning lambda this.tests++; Func<Task> f = async () => { await Task.Delay(10); using (var x = new MyDisp()) { Meth(x); } }; f(); await f(); if (MyDisp.DisposeCalledCount == TestCase.DisposeCalled) Driver.Count++; //using statement inside Task<decimal> returning lambda this.tests++; Func<Task<decimal>> g = async () => { await Task.Delay(10); Meth(new MyDisp()); using (var x = new MyDisp()) { Task.Run(async () => { new Action<MyDisp>((y) => { })(x); await Task.Delay(10); }); } return 1; }; var t = await g(); if (MyDisp.DisposeCalledCount == TestCase.DisposeCalled && t == 1) Driver.Count++; Driver.Result = Driver.Count - this.tests; //When test complete, set the flag. Driver.CompletedSignal.Set(); } } class Driver { public static int Result = -1; public static int Count = 0; public static AutoResetEvent CompletedSignal = new AutoResetEvent(false); static int Main() { var t = new TestCase(); t.Run(); CompletedSignal.WaitOne(); // 0 - success // 1 - failed (test completed) // -1 - failed (test incomplete - deadlock, etc) return Driver.Result; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (55,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(x); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(x)"), // (67,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(x); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(x)"), // (70,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // f(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "f()"), // (80,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(new MyDisp()); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(new MyDisp())"), // (83,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Task.Run(async () => Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Task.Run(async () => { new Action<MyDisp>((y) => { })(x); await Task.Delay(10); })")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait08() { // invoke a method that returns an awaitable type in an async method var source = @" using System; using System.Threading.Tasks; class Test { static async Task<T> Meth<T>(T t) { await Task.Delay(10); return t; } static async Task Goo() { try { Meth(1); } catch (Exception) { Meth(""""); } finally { Meth((decimal?)2); } } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (28,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"), // (32,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(""); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"), // (36,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth((decimal?)2); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((decimal?)2)")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait09() { // invoke a method that returns an awaitable type in an async method var source = @" using System; using System.Threading.Tasks; static class Extension { public static async Task Meth<T>(this int i, T t) { await Task.Delay(10); } } class Test { static async Task<T> Goo<T>(T t) { var i = 0; Func<Task> f = async delegate() { await Task.Delay(10); i.Meth(1); }; Func<Task<Func<Task<int>>>> ff = async () => { f(); await Task.Delay(10); return (Func<Task<int>>)(async delegate() { i.Meth(""""); await Task.Delay(10); return 3; }); }; ff(); (await ff())(); return t; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (33,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.Meth(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.Meth(1)"), // (38,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // f(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "f()"), // (42,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.Meth(""); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"i.Meth("""")"), // (48,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // ff(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "ff()"), // (50,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // (await ff())(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "(await ff())()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait10() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; class Test { async Task<T> Meth<T>(T t) { await Task.Delay(10); return t; } private Task field; public Task Prop { get { Meth(1); return @field; } set { Bar(); Meth(""""); @field = value; } } public async Task Goo() { await Bar(); Bar(); //the callee return type is dynamic, it will not give warning Meth((decimal?)null); } public dynamic Bar() { return Task.Run<int>(async () => { await Task.Delay(10); return 2; }); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics( // (30,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"), // (36,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(""); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"), // (45,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth((decimal?)null); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((decimal?)null)")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait11() { // invoke a method that returns an awaitable type in an async method var source = @" using System.Threading.Tasks; partial class Test { partial void Bar(); public async Task<T> Meth<T>(params T[] t) { await Task.Delay(10); return t[0]; } } partial class Test { async partial void Bar() { await Task.Delay(10); Meth("""", null); } async public Task Goo() { Bar(); Meth(Task.Run(async () => 1), Meth(1)); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (19,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth("", null); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""", null)").WithLocation(19, 9), // (25,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(Task.Run(async () => 1), Meth(1)); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(Task.Run(async () => 1), Meth(1))").WithLocation(25, 9) ); } [WorkItem(611150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611150")] [Fact] public void UnobservedAwaitableExpression_ForgetAwait12() { var source = @" using System.Threading.Tasks; class Test { static async Task<T> Meth<T>(T t) { await Task.Delay(10); return t; } static async Task Goo() { checked { Meth(await Meth(int.MaxValue) + 1); } unchecked { Meth(long.MinValue - 1); } var str = """"; lock (str) { Meth((int?)null); } lock (Meth("""")) { Task.Run(async () => { await Task.Delay(10); return """"; }); } } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (16,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(await Meth(int.MaxValue) + 1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(await Meth(int.MaxValue) + 1)"), // (20,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(long.MinValue - 1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(long.MinValue - 1)"), // (26,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth((int?)null); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((int?)null)")); } [WorkItem(611150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/611150")] [Fact] public void UnobservedAwaitableExpression_ForgetAwait12_breaking() { // The native compiler gives a warning on the un-awaited async invocation. However, awaiting inside the lock // would escalate the warning to an error. Roslyn does not give a warning. var source = @" using System.Threading.Tasks; class Test { static async Task Goo() { await Task.Factory.StartNew(() => { }); lock (new object()) { Task.Run(async () => { await Task.Delay(10); return """"; }); } } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait13() { // invoke a method that returns an awaitable type in an async method // 1. the callee is a property/indexer that returns Task/Task<T> // 2. invoke the method in the constructor var source = @" using System.Threading.Tasks; class Test { public Task Prop { get { return Task.Run(async () => { await Task.Delay(10); }); } } public Task<int> this[dynamic index] { get { return Task.Run<int>(async () => { await Task.Delay(10); return index; }); } } public async Task<T> Meth<T>(T t) { await Task.Delay(10); return t; } public Test() { Meth(1); //warning CS4014 } public async Task Goo() { var test = new Test(); test.Prop; //error CS0201 test[1]; //error CS0201 } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics( // (41,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(1); //warning CS4014 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"), // (47,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // test.Prop; //error CS0201 Diagnostic(ErrorCode.ERR_IllegalStatement, "test.Prop"), // (48,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // test[1]; //error CS0201 Diagnostic(ErrorCode.ERR_IllegalStatement, "test[1]") ); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait14() { // invoke a method that returns an awaitable type in async/non-async method var source = @" using System.Threading.Tasks; class Test { static async Task<T> Meth<T>(T t) { await Task.Delay(10); return t; } static async Task Goo() { for (Meth(""""); await Meth(false); Meth((float?)null)) { Meth(1); } } static Task<int> Bar() { for (Meth(5m); ; Meth("""")) { Meth((string)null); } } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (27,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (Meth(""); await Meth(false); Meth((float?)null)) Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"), // (27,43): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (Meth(""); await Meth(false); Meth((float?)null)) Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((float?)null)"), // (29,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(1)"), // (35,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (Meth(5m); ; Meth("")) Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth(5m)"), // (35,26): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (Meth(5m); ; Meth("")) Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, @"Meth("""")"), // (37,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Meth((string)null); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Meth((string)null)")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait15() { // invoke a method that returns an awaitable type in async/non-async method var source = @" using System.Threading.Tasks; public class TestB { public async Task<T> Meth<T>(T t = default(T)) { await Task.Delay(10); return t; } public async Task Meth2() { await Task.Delay(10); } } public class Test { public async Task Goo() { var testB = new TestB(); for (testB.Meth2(); await testB.Meth(false); testB.Meth((float?)null)) { testB.Meth(1); } } public void Bar() { //if the awaitable method was compiled into a library, the warning will not give var testB = new TestB(); testB.Meth<decimal>(); testB.Meth2(); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (33,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (testB.Meth2(); await testB.Meth(false); testB.Meth((float?)null)) Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth2()"), // (33,54): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // for (testB.Meth2(); await testB.Meth(false); testB.Meth((float?)null)) Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth((float?)null)"), // (35,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // testB.Meth(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth(1)"), // (43,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // testB.Meth<decimal>(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth<decimal>()"), // (44,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // testB.Meth2(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "testB.Meth2()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait16() { // invoke a method that returns an awaitable type in a non-async method var source = @" using System.Threading.Tasks; class Test { public void Meth() { Goo(); } public async Task<int> Goo() { await Task.Delay(10); return 1; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (15,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait17() { // invoke a method that returns an awaitable type in a non-async method var source = @" using System; using System.Threading.Tasks; static class Extension { public static async Task<int> ExMeth(this string str) { await Task.Delay(10); return str.Length; } } class Test:IDisposable { public void Dispose() { } static int Main() { using (Test test = new Test()) { string s=""abc""; s.ExMeth(); } return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (29,14): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // s.ExMeth(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "s.ExMeth()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait18() { // invoke a method that returns an awaitable type in a non-async method var source = @" using System.Threading.Tasks; class Test { public delegate T Del<T>(T item); public T Meth<T>(T t) { Goo(); Del<int> del = x => { Goo(); return 1; }; return t; } static async Task<Task> Goo() { await Task.Delay(10); return new Task(() => { Task.Delay(10); }); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (18,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (21,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait19() { // invoke a method that returns an awaitable type in a non-async method var source = @" using System.Threading.Tasks; class Test { public delegate T Del<T>(); public T Meth<T>(T t) { Goo(); Del<Task<string>> del =async delegate() { await Task.Delay(10); Goo(); Del<int> del2 = () => { Goo(); return 1; }; return """"; }; del(); return t; } public Task Goo() { return Task.Run(async() => { await Task.Delay(10); }); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (21,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait20() { // invoke a method that returns an awaitable type in a non-async method var source = @" using System; using System.Threading.Tasks; class Test { } class Testcase { static Test test = null; public void Meth() { Goo(); Func<Task<Test>> fun = () => { return Goo(); }; } public Task<Test> Goo() { return Task.Run<Test>( () => { if (test == null) test = new Test(); return test; } ); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait21() { var source = @" using System; using System.Threading.Tasks; class Test { delegate Task<dynamic> Del(dynamic d = null); public void Meth() { Del del = async x => { await Task.Delay(10); return 1; }; del(); Func<int,Task<Func<dynamic>>> func =async y => { await Task.Delay(10); del(y); return (delegate() { return 1; }); }; func(1); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }).VerifyDiagnostics( // (27,17): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // del(y); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "del(y)")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait22() { var source = @" using System; using System.Threading.Tasks; class Test { public void Meth() { Func<Task<string>> Goo = async () => { await Task.Delay(10); return """"; }; Goo(); Task.Run(() => { Goo(); Func<Task<Task>> fun = async () => { await Task.Delay(10); return Task.Run(() => { Goo(); }); }; }); } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait23() { var source = @" using System.Threading.Tasks; class Test { delegate Task<string> Del(); delegate void Del2(); public void Meth() { Del del = async delegate() { await Task.Delay(10); return """"; }; del(); Del2 del2 = delegate() { del(); Del del3 = async () => { await Task.Delay(10); Del2 del4 = delegate() { del(); }; return """"; }; del3(); }; } static int Main() { return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait24() { var source = @" using System; using System.Threading.Tasks; static class Extension { public static Task<int> ExMeth(this int i) { Func<Task<int>> Goo = async () => { await Task.Delay(10); return ++i; }; return (Task<int>) Goo(); } } class Test { public static int amount=0; static int Main() { lock (amount.ExMeth()) { amount.ExMeth(); } return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait25() { var source = @" using System.Threading.Tasks; class Test { public async Task<int> Meth() { await Task.Delay(10); return int.MaxValue; } public Task<int> Goo() { int i = int.MaxValue; return Task.Run(async () => { return i; }); } static int Main() { Test test = new Test(); checked { test.Meth(); test.Goo(); } unchecked { test.Meth(); test.Goo(); } return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (21,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // test.Meth(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "test.Meth()").WithLocation(21, 13), // (26,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // test.Meth(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "test.Meth()").WithLocation(26, 13)); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait26() { var source = @" using System; using System.Threading.Tasks; class Testcase { ~Testcase() { Goo(); Goo2(); } public async Task<string> Goo() { await Task.Delay(10); return ""Goo""; } public Task Goo2() { return Task.Run(() => { }); } } class Test { static int Main() { Object obj = new Testcase(); obj = null; GC.Collect(); GC.WaitForPendingFinalizers(); return 0; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (17,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()")); } [Fact] public void UnobservedAwaitableExpression_ForgetAwait27() { var source = @" using System; using System.Threading.Tasks; class Test : IDisposable { public async Task Goo() { await Task.Delay(10); } public void Dispose() { Goo(); } static int Main() { using (Test test = new Test()) { test.Goo(); } return 0; } } "; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (22,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Goo()"), // (28,13): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // test.Goo(); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "test.Goo()")); } [Fact] public void UnobservedAwaitableExpression_Script() { var source = @"using System.Threading.Tasks; Task.FromResult(1); Task.FromResult(2);"; var compilation = CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Script); compilation.VerifyDiagnostics( // (2,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Task.FromResult(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(1)").WithLocation(2, 1), // (3,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Task.FromResult(2); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(2)").WithLocation(3, 1)); } [Fact] public void UnobservedAwaitableExpression_Submission() { var source0 = @"using System.Threading.Tasks; Task.FromResult(1); Task.FromResult(2)"; var submission = CSharpCompilation.CreateScriptCompilation( "s0.dll", syntaxTree: SyntaxFactory.ParseSyntaxTree(source0, options: TestOptions.Script), references: new[] { MscorlibRef_v4_0_30316_17626 }); submission.VerifyDiagnostics( // (2,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Task.FromResult(1); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(1)").WithLocation(2, 1), // (3,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Task.FromResult(2); Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "Task.FromResult(2)").WithLocation(3, 1)); } [Fact] public void BadAsyncMethodWithNoStatementBody() { var source = @" using System.Threading.Tasks; static class Test { static async Task M1(); }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (6,23): error CS1994: The 'async' modifier can only be used in methods that have a body // static async Task M1(); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M1")); } [Fact] public void BadAsyncMethodWithVarargsAndNoStatementBody() { var source = @" using System.Threading.Tasks; static class Test { static async Task M1(__arglist); }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (6,23): error CS1994: The 'async' modifier can only be used in methods that have a body // static async Task M1(__arglist); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M1")); } [Fact] public void BadSpecialByRefParameter() { var source = @" using System.Threading.Tasks; using System; class Test { async Task M1(TypedReference tr) { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (7,34): error CS4012: Parameters of type 'System.TypedReference' cannot be declared in async methods or async lambda expressions // async Task M1(TypedReference tr) Diagnostic(ErrorCode.ERR_BadSpecialByRefParameter, "tr").WithArguments("System.TypedReference")); } [Fact] public void BadSpecialByRefLocal() { var source = @" using System.Threading.Tasks; using System; class Test { async Task M1() { TypedReference tr; await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyEmitDiagnostics( // (9,24): warning CS0168: The variable 'tr' is declared but never used // TypedReference tr; Diagnostic(ErrorCode.WRN_UnreferencedVar, "tr").WithArguments("tr")); } [Fact] public void BadSpecialByRefVarDeclLocal() { var source = @" using System.Threading.Tasks; using System; class Test { async Task M1(bool truth) { var tr = new TypedReference(); // 1 await Task.Factory.StartNew(() => { }); } async Task M2(bool truth) { var tr = new TypedReference(); await Task.Factory.StartNew(() => { }); var tr2 = tr; // 2 } async Task M3() { var tr = new TypedReference(); await Task.Factory.StartNew(() => { }); tr = default; var tr2 = tr; } }"; CreateCompilationWithMscorlib461(source).VerifyEmitDiagnostics( // (9,13): warning CS0219: The variable 'tr' is assigned but its value is never used // var tr = new TypedReference(); // 1 Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "tr").WithArguments("tr").WithLocation(9, 13), // (17,19): error CS4007: Instance of type 'System.TypedReference' cannot be preserved across 'await' or 'yield' boundary. // var tr2 = tr; // 2 Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "tr").WithArguments("System.TypedReference").WithLocation(17, 19)); } [Fact] public void BadFixedSpecialByRefLocal() { var source = @" using System; public class MyClass { unsafe async public static void F() { fixed (TypedReference tr) { } } }"; CreateCompilationWithMscorlib461(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( // (8,31): error CS0209: The type of a local declared in a fixed statement must be a pointer type // fixed (TypedReference tr) { } Diagnostic(ErrorCode.ERR_BadFixedInitType, "tr"), // (8,31): error CS0210: You must provide an initializer in a fixed or using statement declaration // fixed (TypedReference tr) { } Diagnostic(ErrorCode.ERR_FixedMustInit, "tr") ); } [Fact] public void AsyncInSecurityCriticalClass() { var source = @" using System.Security; using System.Threading.Tasks; [SecurityCritical] public class C { public async void M() { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (8,23): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute. // public async void M() Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M")); } [Fact] public void AsyncInSecuritySafeCriticalClass() { var source = @" using System.Security; using System.Threading.Tasks; [SecuritySafeCritical] public class C { public async void M() { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (8,23): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute. // public async void M() Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M")); } [Fact] public void AsyncInSecuritySafeCriticalAndSecurityCriticalClass() { var source = @" using System.Security; using System.Threading.Tasks; [SecurityCritical] [SecuritySafeCritical] public class C { public async void M() { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (9,23): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute. // public async void M() Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M")); } [Fact] public void AsyncInDoublyNestedSecuritySafeCriticalAndSecurityCriticalClasses() { var source = @" using System.Security; using System.Threading.Tasks; [SecurityCritical] [SecuritySafeCritical] public class C { [SecuritySafeCritical] public class D { public async void M() { await Task.Factory.StartNew(() => { }); } } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (12,27): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute. // public async void M() Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "M")); } [Fact] public void SecurityCriticalOnAsync() { var source = @" using System.Security; using System.Threading.Tasks; public class D { [SecurityCritical] public async void M() { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (7,6): error CS4030: Security attribute 'SecurityCritical' cannot be applied to an Async method. // [SecurityCritical] Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecurityCritical").WithArguments("SecurityCritical")); } [Fact] public void SecuritySafeCriticalOnAsync() { var source = @" using System.Security; using System.Threading.Tasks; public class D { [SecuritySafeCritical] public async void M() { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (7,6): error CS4030: Security attribute 'SecuritySafeCritical' cannot be applied to an Async method. // [SecuritySafeCritical] Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecuritySafeCritical").WithArguments("SecuritySafeCritical")); } [Fact] public void SecuritySafeCriticalAndSecurityCriticalOnAsync() { var source = @" using System.Security; using System.Threading.Tasks; public class D { [SecurityCritical] [SecuritySafeCritical] public async void M() { await Task.Factory.StartNew(() => { }); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (7,6): error CS4030: Security attribute 'SecurityCritical' cannot be applied to an Async method. // [SecurityCritical] Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecurityCritical").WithArguments("SecurityCritical"), // (8,6): error CS4030: Security attribute 'SecuritySafeCritical' cannot be applied to an Async method. // [SecuritySafeCritical] Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsync, "SecuritySafeCritical").WithArguments("SecuritySafeCritical")); } [Fact, WorkItem(547077, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547077")] public void Repro_17880() { var source = @" class Program { async void Meth() { } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact, WorkItem(547079, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547079")] public void Repro_17883() { var source = @" abstract class Base { public async abstract void M1(); } class Test { public static int Main() { return 1; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (4,32): error CS1994: The 'async' modifier can only be used in methods that have a body. // public async abstract void M1(); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M1")); } [Fact, WorkItem(547081, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547081")] public void Repro_17885_CSharp_71() { var source = @" using System.Threading.Tasks; class Test { async public static Task Main() { } }"; CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_1)).VerifyDiagnostics(); } [Fact, WorkItem(547081, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547081")] public void Repro_17885_CSharp7() { var source = @" using System.Threading.Tasks; class Test { async public static Task Main() { } }"; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); comp.VerifyDiagnostics( // (5,25): error CS8107: Feature 'async main' is not available in C# 7.0. Please use language version 7.1 or greater. // async public static Task Main() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "Task").WithArguments("async main", "7.1").WithLocation(5, 25), // error CS5001: Program does not contain a static 'Main' method suitable for an entry point Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1) ); } [Fact, WorkItem(547088, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547088")] public void Repro_17914() { var source = @" class Driver { static int Main() { return 1; } public async void Goo(ref int x) { } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (9,35): error CS1988: Async methods cannot have ref, in or out parameters // public async void Goo(ref int x) Diagnostic(ErrorCode.ERR_BadAsyncArgType, "x") ); } [Fact] public void BadAsync_MethodImpl_Synchronized() { var source = @" using System.Runtime.CompilerServices; using System.Threading.Tasks; public class C { [MethodImpl(MethodImplOptions.Synchronized)] async Task<int> F1() { return await Task.Factory.StartNew(() => 1); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (9,21): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an Async method. // async Task<int> F1() Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "F1")); } [Fact, WorkItem(66530, "https://github.com/dotnet/roslyn/issues/66530")] public void BadAsync_MethodImpl_Synchronized_Lambda() { var source = @" using System.Runtime.CompilerServices; using System.Threading.Tasks; public class C { void M() { var a = [MethodImpl(MethodImplOptions.Synchronized)] async Task<int> () => { await Task.Yield(); return 42; }; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (9,81): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an async method // var a = [MethodImpl(MethodImplOptions.Synchronized)] async Task<int> () => Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "=>").WithLocation(9, 81)); } [Fact] public void BadAsync_MethodImpl_Synchronized_LocalFunction() { var source = @" using System.Runtime.CompilerServices; using System.Threading.Tasks; public class C { void M() { [MethodImpl(MethodImplOptions.Synchronized)] async Task<int> local() { return await Task.Factory.StartNew(() => 1); } } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (10,25): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an async method // async Task<int> local() Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "local").WithLocation(10, 25), // (10,25): warning CS8321: The local function 'local' is declared but never used // async Task<int> local() Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(10, 25)); } [Fact] public void Async_MethodImplSynchronized_BadReturn_SecurityCritical() { var source = @" using System.Runtime.CompilerServices; using System.Security; using System.Threading.Tasks; [SecurityCritical] public class C { [MethodImpl(MethodImplOptions.Synchronized)] async int F1() { return await Task.Factory.StartNew(() => 1); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (10,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"), // (10,15): error CS4031: Async methods are not allowed in an Interface, Class, or Structure which has the 'SecurityCritical' or 'SecuritySafeCritical' attribute. // async int F1() Diagnostic(ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct, "F1"), // (10,15): error CS4015: 'MethodImplOptions.Synchronized' cannot be applied to an Async method. // async int F1() Diagnostic(ErrorCode.ERR_SynchronizedAsyncMethod, "F1")); } [Fact] [WorkItem(552382, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/552382")] public void GetAwaiterIsExtension() { var source = @"using System; using A; namespace A { public class IAS<T> { } public class Awaiter<T> : System.Runtime.CompilerServices.INotifyCompletion { public bool IsCompleted { get { return true; } } public T GetResult() { return default(T); } public void OnCompleted(Action continuation) { } } public static class IAS_Extensions { public static Awaiter<T> GetAwaiter<T>(this IAS<T> self) { return null; } } } namespace B { public class Program { static async void M(IAS<int> i) { int i1 = await i; int i2 = i.GetAwaiter().GetResult(); } public static void Main(string[] args) { } } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics(); } [Fact] [WorkItem(576311, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/576311")] public void BadDelegateTypeForAsync() { var source = @"using System; class C { static void Main() { Func<int> x = async delegate { throw null; }; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (6,29): error CS4010: Cannot convert async anonymous method to delegate type 'Func<int>'. An async anonymous method may return void, Task or Task<T>, none of which are convertible to 'Func<int>'. // Func<int> x = async delegate { throw null; }; Diagnostic(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, "delegate").WithArguments("anonymous method", "System.Func<int>") ); } [WorkItem(588706, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/588706")] [Fact] public void AsyncAsLambdaParameter() { var source = @"using System; using System.Threading.Tasks; class C { async void Goo() { Action<int> x = (await) => { }; // should be a syntax error await Task.Delay(1); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (8,26): error CS4003: 'await' cannot be used as an identifier within an async method or lambda expression // Action<int> x = (await) => { }; // should be a syntax error Diagnostic(ErrorCode.ERR_BadAwaitAsIdentifier, "await").WithLocation(8, 26) ); } [Fact] [WorkItem(629368, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/629368")] public void GetAwaiterFieldUsedLikeMethod() { string source = @" using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; public class C { public Func<TaskAwaiter<int>> GetAwaiter; public async Task<int> F(C x) { return await x; } } "; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (12,17): error CS0118: 'GetAwaiter' is a field but is used like a method Diagnostic(ErrorCode.ERR_BadSKknown, "await x").WithArguments("GetAwaiter", "field", "method")); } [Fact] [WorkItem(629368, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/629368")] public void GetAwaiterPropertyUsedLikeMethod() { string source = @" using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; public class C { public Func<TaskAwaiter<int>> GetAwaiter { get; set; } public async Task<int> F(C x) { return await x; } } "; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (12,16): error CS0118: 'GetAwaiter' is a property but is used like a method Diagnostic(ErrorCode.ERR_BadSKknown, "await x").WithArguments("GetAwaiter", "property", "method")); } [Fact] [WorkItem(628619, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/628619")] public void ReturnExpressionNotConvertible() { string source = @" using System.Threading.Tasks; class Program { static async Task<T> Goo<T>() { await Task.Delay(1); return 1; } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (9,16): error CS0029: Cannot implicitly convert type 'int' to 'T' // return 1; Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "T") ); } [Fact] [WorkItem(632824, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/632824")] public void RefParameterOnAsyncLambda() { string source = @" using System; using System.Threading.Tasks; delegate Task D(ref int x); class C { static void Main() { D d = async delegate(ref int i) { await Task.Delay(500); Console.WriteLine(i++); }; int x = 5; d(ref x).Wait(); Console.WriteLine(x); } }"; CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (11,38): error CS1988: Async methods cannot have ref, in or out parameters // D d = async delegate(ref int i) Diagnostic(ErrorCode.ERR_BadAsyncArgType, "i") ); } [Fact] [WorkItem(858059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/858059")] public void UnawaitedVersusLambda() { string source = @"using System; using System.Threading.Tasks; public class Program { public static void Main(string[] args) { } void X() { Action x1 = () => XAsync(); // warn Action y1 = () => YAsync(); // ok Action x2 = async () => XAsync(); // warn Action y2 = async () => YAsync(); // warn XAsync(); // warn YAsync(); // ok } async Task XAsync() { await Task.Delay(1); } Task YAsync() { return Task.Delay(1); } }"; // The rules for when we give a warning may seem quirky, but we aim to precisely replicate // the diagnostics produced by the native compiler. CreateCompilationWithMscorlib461(source).VerifyDiagnostics( // (12,27): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action x1 = () => XAsync(); // warn Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "XAsync()"), // (14,33): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action x2 = async () => XAsync(); // warn Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "XAsync()"), // (15,33): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action y2 = async () => YAsync(); // warn Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "YAsync()"), // (17,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // XAsync(); // warn Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "XAsync()") ); } [Fact()] public void DelegateTypeWithNoInvokeMethod() { // Delegate type with no Invoke method. var ilSource = @".class public auto ansi sealed D`1<T> extends [mscorlib]System.MulticastDelegate { .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed { } }"; var source = @"using System; using System.Threading.Tasks; class C { static void F(D<Task> d) { } static void F<T>(D<Task<T>> d) { } static void F(Func<Task> f) { } static void F<T>(Func<Task<T>> f) { } static void M() { F(async () => { }); F(async () => { return 3; }); } }"; var reference = CompileIL(ilSource); var compilation = CreateCompilationWithMscorlib461(source, references: new[] { reference }); compilation.VerifyEmitDiagnostics(); } [Theory, CombinatorialData, WorkItem(64964, "https://github.com/dotnet/roslyn/issues/64964")] public void UnobservedAwaitableExpression_AsyncTopLevelStatement(bool voidReturn) { var src = $$""" using System; using System.Threading.Tasks; await Task.Yield(); C c = new C(); c.M(); // 1 c.MAsync(); // 2 Action a1 = () => c.M(); Action a2 = async () => { await Task.Yield(); c.M(); }; // 3 Action a3 = () => c.MAsync(); // 4 Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 5 I i = new C(); i.M(); // 6 i.MAsync(); // 7 Action a5 = () => i.M(); Action a6 = async () => { await Task.Yield(); i.M(); }; // 8 Action a7 = () => i.MAsync(); Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 9 {{(voidReturn ? "" : "return 42;")}} public class D { public async Task M2() { await Task.Yield(); C c = new C(); c.M(); // 10 c.MAsync(); // 11 Action a1 = () => c.M(); Action a2 = async () => { await Task.Yield(); c.M(); }; // 12 Action a3 = () => c.MAsync(); // 13 Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 14 I i = new C(); i.M(); // 15 i.MAsync(); // 16 Action a5 = () => i.M(); Action a6 = async () => { await Task.Yield(); i.M(); }; // 17 Action a7 = () => i.MAsync(); Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 18 } } public interface I { Task M(); Task MAsync(); } public class C : I { public Task M() => throw null; public async Task MAsync() => await Task.Yield(); } """; var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (7,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.M(); // 1 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(7, 1), // (8,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.MAsync(); // 2 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(8, 1), // (10,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a2 = async () => { await Task.Yield(); c.M(); }; // 3 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(10, 47), // (11,19): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a3 = () => c.MAsync(); // 4 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(11, 19), // (12,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 5 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(12, 47), // (15,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.M(); // 6 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(15, 1), // (16,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.MAsync(); // 7 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(16, 1), // (18,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a6 = async () => { await Task.Yield(); i.M(); }; // 8 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(18, 47), // (20,47): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 9 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(20, 47), // (31,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.M(); // 10 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(31, 9), // (32,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.MAsync(); // 11 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(32, 9), // (34,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a2 = async () => { await Task.Yield(); c.M(); }; // 12 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(34, 55), // (35,27): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a3 = () => c.MAsync(); // 13 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(35, 27), // (36,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a4 = async () => { await Task.Yield(); c.MAsync(); }; // 14 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(36, 55), // (39,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.M(); // 15 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(39, 9), // (40,9): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.MAsync(); // 16 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(40, 9), // (42,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a6 = async () => { await Task.Yield(); i.M(); }; // 17 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(42, 55), // (44,55): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a8 = async () => { await Task.Yield(); i.MAsync(); }; // 18 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(44, 55) ); var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp); Assert.Equal(voidReturn ? "System.Threading.Tasks.Task" : "System.Threading.Tasks.Task<System.Int32>", entryPoint.ReturnType.ToTestDisplayString()); } [Theory, CombinatorialData, WorkItem(64964, "https://github.com/dotnet/roslyn/issues/64964")] public void UnobservedAwaitableExpression_NonAsyncTopLevelStatements_Task(bool voidReturn) { var src = $$""" using System; using System.Threading.Tasks; C c = new C(); c.M(); // 1 c.MAsync(); // 2 Action a1 = () => c.M(); Action a2 = () => c.MAsync(); // 3 I i = new C(); i.M(); // 4 i.MAsync(); // 5 Action a3 = () => i.M(); Action a4 = () => i.MAsync(); object o = null; lock(o) { c.M(); c.MAsync(); // 6 } {{(voidReturn ? "" : "return 42;")}} public interface I { Task M(); Task MAsync(); } public class C : I { public Task M() => throw null; public async Task MAsync() => await Task.Yield(); } """; var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (5,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.M(); // 1 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(5, 1), // (6,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.MAsync(); // 2 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(6, 1), // (8,19): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a2 = () => c.MAsync(); // 3 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(8, 19), // (11,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.M(); // 4 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(11, 1), // (12,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.MAsync(); // 5 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(12, 1), // (20,5): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.MAsync(); // 6 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(20, 5) ); var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp); Assert.Equal(voidReturn ? "System.Void" : "System.Int32", entryPoint.ReturnType.ToTestDisplayString()); } [Theory, CombinatorialData, WorkItem(64964, "https://github.com/dotnet/roslyn/issues/64964")] public void UnobservedAwaitableExpression_NonAsyncTopLevelStatements_TaskT(bool voidReturn) { var src = $$""" using System; using System.Threading.Tasks; C c = new C(); c.M(); // 1 c.MAsync(); // 2 Action a1 = () => c.M(); Action a2 = () => c.MAsync(); // 3 I i = new C(); i.M(); // 4 i.MAsync(); // 5 Action a3 = () => i.M(); Action a4 = () => i.MAsync(); // 6 {{(voidReturn ? "" : "return 42;")}} public interface I { Task<int> M(); Task<int> MAsync(); } public class C : I { public Task<int> M() => throw null; public async Task<int> MAsync() { await Task.Yield(); throw null; } } """; var comp = CreateCompilation(src); comp.VerifyDiagnostics( // (5,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.M(); // 1 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.M()").WithLocation(5, 1), // (6,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // c.MAsync(); // 2 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(6, 1), // (8,19): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // Action a2 = () => c.MAsync(); // 3 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "c.MAsync()").WithLocation(8, 19), // (11,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.M(); // 4 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.M()").WithLocation(11, 1), // (12,1): warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. // i.MAsync(); // 5 Diagnostic(ErrorCode.WRN_UnobservedAwaitableExpression, "i.MAsync()").WithLocation(12, 1) ); var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp); Assert.Equal(voidReturn ? "System.Void" : "System.Int32", entryPoint.ReturnType.ToTestDisplayString()); } } }