diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index c740b4288f824..7319d2c333f87 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -150,9 +150,8 @@ private static TypeSymbol InferReturnType( var delegateReturnType = delegateType?.GetDelegateType()?.DelegateInvokeMethod?.ReturnType as NamedTypeSymbol; if ((object)delegateReturnType != null) { - NamedTypeSymbol builderType; - MethodSymbol createBuilderMethod; - if (delegateReturnType.IsCustomTaskType(out builderType, out createBuilderMethod)) + object builderType; + if (delegateReturnType.IsCustomTaskType(out builderType)) { taskType = delegateReturnType; } diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodBuilderMemberCollection.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodBuilderMemberCollection.cs index f4bdd24a95179..716d28c878943 100644 --- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodBuilderMemberCollection.cs +++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodBuilderMemberCollection.cs @@ -137,12 +137,19 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, { var returnType = (NamedTypeSymbol)method.ReturnType; NamedTypeSymbol builderType; - MethodSymbol createBuilderMethod; - PropertySymbol taskProperty; - bool customBuilder = returnType.IsCustomTaskType(out builderType, out createBuilderMethod); + MethodSymbol createBuilderMethod = null; + PropertySymbol taskProperty = null; + + object builderArgument; + bool customBuilder = returnType.IsCustomTaskType(out builderArgument); if (customBuilder) { - taskProperty = GetCustomTaskProperty(F, builderType); + builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric:false); + if ((object)builderType != null) + { + taskProperty = GetCustomTaskProperty(F, builderType); + createBuilderMethod = GetCustomCreateMethod(F, builderType); + } } else { @@ -161,7 +168,8 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, customBuilder, out taskProperty); } - if ((object)createBuilderMethod == null || + if ((object)builderType == null || + (object)createBuilderMethod == null || (object)taskProperty == null) { collection = default(AsyncMethodBuilderMemberCollection); @@ -197,21 +205,26 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, } returnType = returnType.ConstructedFrom.Construct(resultType); NamedTypeSymbol builderType; - MethodSymbol createBuilderMethod; - PropertySymbol taskProperty; - bool customBuilder = returnType.IsCustomTaskType(out builderType, out createBuilderMethod); - if (!customBuilder) - { - builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T); - Debug.Assert((object)builderType != null); - builderType = builderType.Construct(resultType); - } + MethodSymbol createBuilderMethod = null; + PropertySymbol taskProperty = null; + + object builderArgument; + bool customBuilder = returnType.IsCustomTaskType(out builderArgument); if (customBuilder) { - taskProperty = GetCustomTaskProperty(F, builderType); + builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric:true); + if ((object)builderType != null) + { + builderType = builderType.ConstructedFrom.Construct(resultType); + taskProperty = GetCustomTaskProperty(F, builderType); + createBuilderMethod = GetCustomCreateMethod(F, builderType); + } } else { + builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T); + Debug.Assert((object)builderType != null); + builderType = builderType.Construct(resultType); TryGetBuilderMember( F, WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Create, @@ -225,7 +238,8 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, customBuilder, out taskProperty); } - if ((object)taskProperty == null || + if ((object)builderType == null || + (object)taskProperty == null || (object)createBuilderMethod == null) { collection = default(AsyncMethodBuilderMemberCollection); @@ -250,6 +264,28 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, throw ExceptionUtilities.UnexpectedValue(method); } + private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F, object builderAttributeArgument, Accessibility desiredAccessibility, bool isGeneric) + { + var builderType = builderAttributeArgument as NamedTypeSymbol; + + if ((object)builderType != null && + !builderType.IsErrorType() && + builderType.SpecialType != SpecialType.System_Void && + builderType.DeclaredAccessibility == desiredAccessibility) + { + bool isArityOk = isGeneric + ? builderType.IsUnboundGenericType && builderType.ContainingType?.IsGenericType != true + : !builderType.IsGenericType; + if (isArityOk) + { + return builderType; + } + } + + F.Diagnostics.Add(ErrorCode.ERR_BadAsyncReturn, F.Syntax.Location); + return null; + } + private static bool TryCreate( SyntheticBoundNodeFactory F, bool customBuilder, @@ -341,6 +377,34 @@ private static bool TryGetBuilderMember( return true; } + private static MethodSymbol GetCustomCreateMethod( + SyntheticBoundNodeFactory F, + NamedTypeSymbol builderType) + { + // The Create method's return type is expected to be builderType. + // The WellKnownMembers routines aren't able to enforce that, which is why this method exists. + const string methodName = "Create"; + var members = builderType.GetMembers(methodName); + foreach (var member in members) + { + if (member.Kind != SymbolKind.Method) + { + continue; + } + var method = (MethodSymbol)member; + if ((method.DeclaredAccessibility == Accessibility.Public) && + method.IsStatic && + method.ParameterCount == 0 && + !method.IsGenericMethod && + method.ReturnType == builderType) + { + return method; + } + } + F.Diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, F.Syntax.Location, builderType, methodName); + return null; + } + private static PropertySymbol GetCustomTaskProperty( SyntheticBoundNodeFactory F, NamedTypeSymbol builderType) diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index 55b636f7448ed..09307ae4e59bd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -1273,9 +1273,8 @@ internal static bool IsNonGenericTaskType(this TypeSymbol type, CSharpCompilatio { return false; } - NamedTypeSymbol builderType; - MethodSymbol createBuilderMethod; - return namedType.IsCustomTaskType(out builderType, out createBuilderMethod); + object builderArgument; + return namedType.IsCustomTaskType(out builderArgument); } internal static bool IsGenericTaskType(this TypeSymbol type, CSharpCompilation compilation) @@ -1289,16 +1288,21 @@ internal static bool IsGenericTaskType(this TypeSymbol type, CSharpCompilation c { return true; } - NamedTypeSymbol builderType; - MethodSymbol createBuilderMethod; - return namedType.IsCustomTaskType(out builderType, out createBuilderMethod); + object builderArgument; + return namedType.IsCustomTaskType(out builderArgument); } /// - /// Returns true if the type is generic or non-generic task-like type. If so, the async - /// method builder type is returned along with the method to construct that type. + /// Returns true if the type is generic or non-generic custom task-like type due to the + /// [AsyncBuilder(typeof(B))] attribute. It returns the "B". /// - internal static bool IsCustomTaskType(this NamedTypeSymbol type, out NamedTypeSymbol builderType, out MethodSymbol createBuilderMethod) + /// + /// For the Task types themselves, this method might return true or false depending on mscorlib. + /// The definition of "custom task-like type" is one that has an [AsyncBuilder(typeof(B))] attribute, + /// no more, no less. Validation of builder type B is left for elsewhere. This method returns B + /// without validation of any kind. + /// + internal static bool IsCustomTaskType(this NamedTypeSymbol type, out object builderArgument) { Debug.Assert((object)type != null); Debug.Assert(type.SpecialType != SpecialType.System_Void); @@ -1306,34 +1310,20 @@ internal static bool IsCustomTaskType(this NamedTypeSymbol type, out NamedTypeSy var arity = type.Arity; if (arity < 2) { - // Find the public static CreateAsyncMethodBuilder method. - var members = type.GetMembers(WellKnownMemberNames.CreateAsyncMethodBuilder); - foreach (var member in members) + // Find the AsyncBuilder attribute. + foreach (var attr in type.GetAttributes()) { - if (member.Kind != SymbolKind.Method) - { - continue; - } - var method = (MethodSymbol)member; - if ((method.DeclaredAccessibility == Accessibility.Public) && - method.IsStatic && - (method.ParameterCount == 0) && - !method.IsGenericMethod) + if (attr.IsTargetAttribute(type, AttributeDescription.AsyncBuilderAttribute) + && attr.CommonConstructorArguments.Length == 1 + && attr.CommonConstructorArguments[0].Kind == TypedConstantKind.Type) { - var returnType = method.ReturnType as NamedTypeSymbol; - if ((object)returnType == null || returnType.Arity != arity) - { - break; - } - builderType = returnType; - createBuilderMethod = method; + builderArgument = attr.CommonConstructorArguments[0].Value; return true; } } } - builderType = null; - createBuilderMethod = null; + builderArgument = null; return false; } @@ -1412,9 +1402,8 @@ private static bool NormalizeTaskTypesInNamedType(CSharpCompilation compilation, typeArgumentsBuilder.Free(); } - NamedTypeSymbol builderType; - MethodSymbol createBuilderMethod; - if (type.OriginalDefinition.IsCustomTaskType(out builderType, out createBuilderMethod)) + object builderArgument; + if (type.OriginalDefinition.IsCustomTaskType(out builderArgument)) { int arity = type.Arity; Debug.Assert(arity < 2); diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs index b7cf7cfbee54a..38c430c421a80 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs @@ -3216,7 +3216,25 @@ class C Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> 3").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "SetStateMachine").WithLocation(4, 25)); } - [Fact] + private static string AsyncBuilderCode(string builderTypeName, string tasklikeTypeName, string genericTypeParameter = null, bool isStruct = false) + { + string ofT = genericTypeParameter == null ? "" : "<" + genericTypeParameter + ">"; + return $@" +public {(isStruct ? "struct" : "class")} {builderTypeName}{ofT} +{{ + public static {builderTypeName}{ofT} Create() => default({builderTypeName}{ofT}); + public {tasklikeTypeName}{ofT} Task {{ get; }} + public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine {{ }} + public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine {{ }} + public void SetException(System.Exception exception) {{ }} + public void SetResult({(genericTypeParameter == null ? "" : genericTypeParameter + " result")}) {{ }} + public void SetStateMachine(IAsyncStateMachine stateMachine) {{ }} + public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine {{ }} +}} +"; + } + + [Fact] public void PresentAsyncTasklikeBuilderMethod() { var source = @" @@ -3227,10 +3245,13 @@ class C async ValueTask f() { await (Task)null; } async ValueTask g() { await (Task)null; return 1; } } -struct ValueTask { public static ValueTaskMethodBuilder CreateAsyncMethodBuilder() => null; } -struct ValueTask { public static ValueTaskMethodBuilder CreateAsyncMethodBuilder() => null;} +[AsyncBuilder(typeof(ValueTaskMethodBuilder))] +struct ValueTask { } +[AsyncBuilder(typeof(ValueTaskMethodBuilder<>))] +struct ValueTask { } class ValueTaskMethodBuilder { + public static ValueTaskMethodBuilder Create() => null; public ValueTask Task { get; } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } @@ -3241,6 +3262,7 @@ public void Start(ref TStateMachine stateMachine) where TStateMac } class ValueTaskMethodBuilder { + public static ValueTaskMethodBuilder Create() => null; public ValueTask Task { get; } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } @@ -3249,6 +3271,7 @@ public void SetResult(T result) { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } } +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var v = CompileAndVerify(source, null, options: TestOptions.ReleaseDll); v.VerifyIL("C.g", @@ -3257,7 +3280,7 @@ public void Start(ref TStateMachine stateMachine) where TStateMac .maxstack 2 .locals init (C.d__1 V_0) IL_0000: ldloca.s V_0 - IL_0002: call ""ValueTaskMethodBuilder ValueTask.CreateAsyncMethodBuilder()"" + IL_0002: call ""ValueTaskMethodBuilder ValueTaskMethodBuilder.Create()"" IL_0007: stfld ""ValueTaskMethodBuilder C.d__1.<>t__builder"" IL_000c: ldloca.s V_0 IL_000e: ldc.i4.m1 @@ -3277,7 +3300,7 @@ .locals init (C.d__1 V_0) .maxstack 2 .locals init (C.d__0 V_0) IL_0000: ldloca.s V_0 - IL_0002: call ""ValueTaskMethodBuilder ValueTask.CreateAsyncMethodBuilder()"" + IL_0002: call ""ValueTaskMethodBuilder ValueTaskMethodBuilder.Create()"" IL_0007: stfld ""ValueTaskMethodBuilder C.d__0.<>t__builder"" IL_000c: ldloca.s V_0 IL_000e: ldc.i4.m1 @@ -3293,6 +3316,395 @@ .locals init (C.d__0 V_0) }"); } + [Fact] + public void AsyncTasklikeGenericBuilder() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +class N +{ + class BN { } + class BG { } + + [AsyncBuilder(typeof(N.BG))] class T_NIT { } + [AsyncBuilder(typeof(N.BG))] class T_NIN { } + [AsyncBuilder(typeof(N.BG<>))] class T_NOT { } + [AsyncBuilder(typeof(N.BG<>))] class T_NON { } + [AsyncBuilder(typeof(N.BN))] class T_NNT { } + [AsyncBuilder(typeof(N.BN))] class T_NNN { } + + async T_NIT f1() => await Task.FromResult(1); + async T_NIN f2() => await Task.FromResult(1); + async T_NOT f3() => await Task.FromResult(1); // ok builderType genericity (but missing members) + async T_NON f4() => await Task.FromResult(1); + async T_NNT f5() => await Task.FromResult(1); + async T_NNN f6() => await Task.FromResult(1); // ok builderType genericity (but missing members) +} + +class G +{ + class BN { } + class BG { } + + [AsyncBuilder(typeof(G.BG))] class T_IIT { } + [AsyncBuilder(typeof(G.BG))] class T_IIN { } + [AsyncBuilder(typeof(G.BN))] class T_INT { } + [AsyncBuilder(typeof(G.BN))] class T_INN { } + [AsyncBuilder(typeof(G<>.BG<>))] class T_OOT { } + [AsyncBuilder(typeof(G<>.BG<>))] class T_OON { } + [AsyncBuilder(typeof(G<>.BN))] class T_ONT { } + [AsyncBuilder(typeof(G<>.BN))] class T_ONN { } + + async T_IIT g1() => await Task.FromResult(1); + async T_IIN g2() => await Task.FromResult(1); + async T_INT g3() => await Task.FromResult(1); + async T_INN g4() => await Task.FromResult(1); // might have been ok builder genericity but we decided not + async T_OOT g5() => await Task.FromResult(1); + async T_OON g6() => await Task.FromResult(1); + async T_ONT g7() => await Task.FromResult(1); + async T_ONN g8() => await Task.FromResult(1); +} + +class Program { static void Main() { } } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (39,27): error CS1983: The return type of an async method must be void, Task or Task + // async T_IIT g1() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(39, 27), + // (17,27): error CS1983: The return type of an async method must be void, Task or Task + // async T_NIT f1() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(17, 27), + // (18,22): error CS1983: The return type of an async method must be void, Task or Task + // async T_NIN f2() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(18, 22), + // (40,22): error CS1983: The return type of an async method must be void, Task or Task + // async T_IIN g2() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(40, 22), + // (41,27): error CS1983: The return type of an async method must be void, Task or Task + // async T_INT g3() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(41, 27), + // (42,22): error CS1983: The return type of an async method must be void, Task or Task + // async T_INN g4() => await Task.FromResult(1); // might have been ok builder genericity but we decided not + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(42, 22), + // (43,27): error CS1983: The return type of an async method must be void, Task or Task + // async T_OOT g5() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(43, 27), + // (19,27): error CS0656: Missing compiler required member 'N.BG.Task' + // async T_NOT f3() => await Task.FromResult(1); // ok builderType genericity (but missing members) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.FromResult(1)").WithArguments("N.BG", "Task").WithLocation(19, 27), + // (19,27): error CS0656: Missing compiler required member 'N.BG.Create' + // async T_NOT f3() => await Task.FromResult(1); // ok builderType genericity (but missing members) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.FromResult(1)").WithArguments("N.BG", "Create").WithLocation(19, 27), + // (20,22): error CS1983: The return type of an async method must be void, Task or Task + // async T_NON f4() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(20, 22), + // (44,22): error CS1983: The return type of an async method must be void, Task or Task + // async T_OON g6() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(44, 22), + // (45,27): error CS1983: The return type of an async method must be void, Task or Task + // async T_ONT g7() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(45, 27), + // (21,27): error CS1983: The return type of an async method must be void, Task or Task + // async T_NNT f5() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(21, 27), + // (46,22): error CS1983: The return type of an async method must be void, Task or Task + // async T_ONN g8() => await Task.FromResult(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.FromResult(1)").WithLocation(46, 22), + // (22,22): error CS0656: Missing compiler required member 'N.BN.Task' + // async T_NNN f6() => await Task.FromResult(1); // ok builderType genericity (but missing members) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.FromResult(1)").WithArguments("N.BN", "Task").WithLocation(22, 22), + // (22,22): error CS0656: Missing compiler required member 'N.BN.Create' + // async T_NNN f6() => await Task.FromResult(1); // ok builderType genericity (but missing members) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.FromResult(1)").WithArguments("N.BN", "Create").WithLocation(22, 22) + ); + + } + + [Fact] + public void AsyncTasklikeBadAttributeArgument1() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(typeof(void))] class T { } + +class Program { + static void Main() { } + async T f() => await Task.Delay(1); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (9,17): error CS1983: The return type of an async method must be void, Task or Task + // async T f() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(1)").WithLocation(9, 17) + ); + } + + + [Fact] + public void AsyncTasklikeBadAttributeArgument2() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(""hello"")] class T { } + +class Program { + static void Main() { } + async T f() => await Task.Delay(1); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (5,15): error CS1503: Argument 1: cannot convert from 'string' to 'System.Type' + // [AsyncBuilder("hello")] class T { } + Diagnostic(ErrorCode.ERR_BadArgType, @"""hello""").WithArguments("1", "string", "System.Type").WithLocation(5, 15), + // (9,13): error CS1983: The return type of an async method must be void, Task or Task + // async T f() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "f").WithLocation(9, 13) + ); + } + + [Fact] + public void AsyncTasklikeBadAttributeArgument3() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(typeof(Nonexistent))] class T { } + +class Program { + static void Main() { } + async T f() => await Task.Delay(1); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (5,22): error CS0246: The type or namespace name 'Nonexistent' could not be found (are you missing a using directive or an assembly reference?) + // [AsyncBuilder(typeof(Nonexistent))] class T { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Nonexistent").WithArguments("Nonexistent").WithLocation(5, 22) + ); + } + + public void AsyncTasklikeBadAttributeArgument4() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(null)] class T { } + +class Program { + static void Main() { } + async T f() => await Task.Delay(1); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (9,17): error CS1983: The return type of an async method must be void, Task or Task + // async T f() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(1)").WithLocation(9, 17) + ); + } + + [Fact] + public void AsyncTasklikeMissingBuilderType() + { + // Builder + var libB = @"public class B { }"; + var cB = CreateCompilationWithMscorlib45(libB); + var rB = cB.EmitToImageReference(); + + // Tasklike + var libT = @" +using System.Runtime.CompilerServices; + +[AsyncBuilder(typeof(B))] public class T { } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; + var cT = CreateCompilationWithMscorlib45(libT, references: new[] { rB }); + var rT = cT.EmitToImageReference(); + + // Consumer, fails to reference builder + var source = @" +using System.Threading.Tasks; + +class Program { + static void Main() { } + async T f() => await Task.Delay(1); +} +"; + var c = CreateCompilationWithMscorlib45(source, references: new[] { rT }); + c.VerifyEmitDiagnostics( + // (6,17): error CS1983: The return type of an async method must be void, Task or Task + // async T f() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(1)").WithLocation(6, 17) + ); + } + + + [Fact] + public void AsyncTasklikeCreateMethod() + { + var source = $@" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +class Program {{ + static void Main() {{ }} + async T0 f0() => await Task.Delay(0); + async T1 f1() => await Task.Delay(1); + async T2 f2() => await Task.Delay(2); + async T3 f3() => await Task.Delay(3); + async T4 f4() => await Task.Delay(4); + async T5 f5() => await Task.Delay(5); + async T6 f6() => await Task.Delay(6); + async T7 f7() => await Task.Delay(7); + async T8 f8() => await Task.Delay(8); +}} + +[AsyncBuilder(typeof(B0))] public class T0 {{ }} +[AsyncBuilder(typeof(B1))] public class T1 {{ }} +[AsyncBuilder(typeof(B2))] public class T2 {{ }} +[AsyncBuilder(typeof(B3))] public class T3 {{ }} +[AsyncBuilder(typeof(B4))] public class T4 {{ }} +[AsyncBuilder(typeof(B5))] public class T5 {{ }} +[AsyncBuilder(typeof(B6))] public class T6 {{ }} +[AsyncBuilder(typeof(B7))] public class T7 {{ }} +[AsyncBuilder(typeof(B8))] public class T8 {{ }} + +{AsyncBuilderCode("B0", "T0").Replace("public static B0 Create()", "public static B0 Create()")} +{AsyncBuilderCode("B1", "T1").Replace("public static B1 Create()", "private static B1 Create()")} +{AsyncBuilderCode("B2", "T2").Replace("public static B2 Create() => default(B2);", "public static void Create() { }")} +{AsyncBuilderCode("B3", "T3").Replace("public static B3 Create() => default(B3);", "public static B1 Create() => default(B1);")} +{AsyncBuilderCode("B4", "T4").Replace("public static B4 Create()", "public static B4 Create(int i)")} +{AsyncBuilderCode("B5", "T5").Replace("public static B5 Create()", "public static B5 Create()")} +{AsyncBuilderCode("B6", "T6").Replace("public static B6 Create()", "public static B6 Create(object arg = null)")} +{AsyncBuilderCode("B7", "T7").Replace("public static B7 Create()", "public static B7 Create(params object[] arg)")} +{AsyncBuilderCode("B8", "T8").Replace("public static B8 Create()", "public B8 Create()")} + +namespace System.Runtime.CompilerServices {{ class AsyncBuilderAttribute : System.Attribute {{ public AsyncBuilderAttribute(System.Type t) {{ }} }} }} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (8,19): error CS0656: Missing compiler required member 'B1.Create' + // async T1 f1() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(1)").WithArguments("B1", "Create").WithLocation(8, 19), + // (9,19): error CS0656: Missing compiler required member 'B2.Create' + // async T2 f2() => await Task.Delay(2); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(2)").WithArguments("B2", "Create").WithLocation(9, 19), + // (10,19): error CS0656: Missing compiler required member 'B3.Create' + // async T3 f3() => await Task.Delay(3); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(3)").WithArguments("B3", "Create").WithLocation(10, 19), + // (11,19): error CS0656: Missing compiler required member 'B4.Create' + // async T4 f4() => await Task.Delay(4); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(4)").WithArguments("B4", "Create").WithLocation(11, 19), + // (12,19): error CS0656: Missing compiler required member 'B5.Create' + // async T5 f5() => await Task.Delay(5); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(5)").WithArguments("B5", "Create").WithLocation(12, 19), + // (13,19): error CS0656: Missing compiler required member 'B6.Create' + // async T6 f6() => await Task.Delay(6); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(6)").WithArguments("B6", "Create").WithLocation(13, 19), + // (14,19): error CS0656: Missing compiler required member 'B7.Create' + // async T7 f7() => await Task.Delay(7); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(7)").WithArguments("B7", "Create").WithLocation(14, 19), + // (15,19): error CS0656: Missing compiler required member 'B8.Create' + // async T8 f8() => await Task.Delay(8); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(8)").WithArguments("B8", "Create").WithLocation(15, 19) + ); + } + + [Fact] + public void AsyncInterfaceTasklike() + { + var source = $@" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +class Program {{ + static void Main() {{ }} + async I0 f0() => await Task.Delay(0); + async I1 f1() {{ await Task.Delay(1); return 1; }} +}} + +[AsyncBuilder(typeof(B0))] public interface I0 {{ }} +[AsyncBuilder(typeof(B1<>))] public interface I1 {{ }} + +{AsyncBuilderCode("B0", "I0", genericTypeParameter: null)} +{AsyncBuilderCode("B1", "I1", genericTypeParameter: "T")} + +namespace System.Runtime.CompilerServices {{ class AsyncBuilderAttribute : System.Attribute {{ public AsyncBuilderAttribute(System.Type t) {{ }} }} }} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + ); + } + + + [Fact] + public void AsyncTasklikeBuilderAccessibility() + { + var source = $@" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(typeof(B1))] public class T1 {{ }} +[AsyncBuilder(typeof(B2))] public class T2 {{ }} +[AsyncBuilder(typeof(B3))] internal class T3 {{ }} +[AsyncBuilder(typeof(B4))] internal class T4 {{ }} + +{AsyncBuilderCode("B1", "T1").Replace("public class B1", "public class B1")} +{AsyncBuilderCode("B2", "T2").Replace("public class B2", "internal class B2")} +{AsyncBuilderCode("B3", "T3").Replace("public class B3", "public class B3").Replace("public T3 Task { get; }", "internal T3 Task {get; }")} +{AsyncBuilderCode("B4", "T4").Replace("public class B4", "internal class B4")} + +class Program {{ + static void Main() {{ }} + async T1 f1() => await Task.Delay(1); + async T2 f2() => await Task.Delay(2); + async T3 f3() => await Task.Delay(3); + async T4 f4() => await Task.Delay(4); +}} + +namespace System.Runtime.CompilerServices {{ class AsyncBuilderAttribute : System.Attribute {{ public AsyncBuilderAttribute(System.Type t) {{ }} }} }} +"; + + var comp = CreateCompilation(source, options: TestOptions.DebugExe); + comp.VerifyEmitDiagnostics( + // (66,19): error CS1983: The return type of an async method must be void, Task or Task + // async T2 f2() => await Task.Delay(2); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(2)").WithLocation(66, 19), + // (67,19): error CS1983: The return type of an async method must be void, Task or Task + // async T3 f3() => await Task.Delay(3); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(3)").WithLocation(67, 19) + ); + } + + [Fact] public void AsyncTasklikeLambdaOverloads() { @@ -3313,9 +3725,11 @@ static void f(Func lambda) { } static void g(Func lambda) { } static void k(Func lambda) { } } -class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder))] +class MyTask { } class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult() { } @@ -3324,6 +3738,7 @@ public void SetException(Exception exception) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var v = CompileAndVerify(source, null, options: TestOptions.ReleaseDll); v.VerifyIL("C.Main", @" @@ -3377,23 +3792,30 @@ static void Main() { } async ValueTask1 g() { await Task.Delay(0); } async ValueTask2 h() { await Task.Delay(0); } } -struct ValueTask0 { public static ValueTaskMethodBuilder0 CreateAsyncMethodBuilder() => null; } -struct ValueTask1 { public static ValueTaskMethodBuilder1 CreateAsyncMethodBuilder() => null; } -struct ValueTask2 { public static ValueTaskMethodBuilder2 CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(ValueTaskMethodBuilder0))] +struct ValueTask0 { } +[AsyncBuilder(typeof(ValueTaskMethodBuilder1))] +struct ValueTask1 { } +[AsyncBuilder(typeof(ValueTaskMethodBuilder2))] +struct ValueTask2 { } class ValueTaskMethodBuilder0 { + public static ValueTaskMethodBuilder0 Create() => null; public ValueTask0 Task => default(ValueTask0); } class ValueTaskMethodBuilder1 { + public static ValueTaskMethodBuilder1 Create() => null; public ValueTask1 Task => default(ValueTask1); public void SetException(System.Exception ex) { } } class ValueTaskMethodBuilder2 { + public static ValueTaskMethodBuilder2 Create() => null; public ValueTask2 Task => default(ValueTask2); public void SetException(System.Exception ex) { } public void SetResult() { } } +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var comp = CreateCompilation(source, options: TestOptions.DebugExe); @@ -3420,19 +3842,28 @@ class C { async Mismatch1 f() { await (Task)null; return 1; } async Mismatch2 g() { await (Task)null; return 1; } } -struct Mismatch1 { public static Mismatch1MethodBuilder CreateAsyncMethodBuilder() => null; } -struct Mismatch2 { public static Mismatch2MethodBuilder CreateAsyncMethodBuilder() => null; } -class Mismatch1MethodBuilder { } -class Mismatch2MethodBuilder {} +[AsyncBuilder(typeof(Mismatch1MethodBuilder))] +struct Mismatch1 { } +[AsyncBuilder(typeof(Mismatch2MethodBuilder<>))] +struct Mismatch2 { } +class Mismatch1MethodBuilder +{ + public static Mismatch1MethodBuilder Create() => null; +} +class Mismatch2MethodBuilder +{ + public static Mismatch2MethodBuilder Create() => null; +} +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var comp = CreateCompilationWithMscorlib45(source); comp.VerifyEmitDiagnostics( - // (6,21): error CS1983: The return type of an async method must be void, Task or Task - // async Mismatch2 g() { await (Task)null; return 1; } - Diagnostic(ErrorCode.ERR_BadAsyncReturn, "g").WithLocation(6, 21), - // (5,26): error CS1983: The return type of an async method must be void, Task or Task + // (5,30): error CS1983: The return type of an async method must be void, Task or Task // async Mismatch1 f() { await (Task)null; return 1; } - Diagnostic(ErrorCode.ERR_BadAsyncReturn, "f").WithLocation(5, 26) + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "{ await (Task)null; return 1; }").WithLocation(5, 30), + // (6,45): error CS1997: Since 'C.g()' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'? + // async Mismatch2 g() { await (Task)null; return 1; } + Diagnostic(ErrorCode.ERR_TaskRetNoObjectRequired, "return").WithArguments("C.g()").WithLocation(6, 45) ); } @@ -3450,12 +3881,14 @@ static void Main() { } async MyTask f() { await (Task)null; } } -class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder))] +class MyTask { } interface I { } class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TSM stateMachine) where TSM : I { } public void AwaitOnCompleted(ref TA awaiter, ref TSM stateMachine) { } @@ -3464,6 +3897,8 @@ public void SetResult() { } public void SetException(Exception ex) { } public MyTask Task => null; } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var comp1 = CreateCompilation(source1, options: TestOptions.DebugExe); @@ -3483,10 +3918,12 @@ static void Main() { } async MyTask f() { await (Task)null; } } -class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder))] +class MyTask { } class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TSM stateMachine) where TSM : IAsyncStateMachine { } public void AwaitOnCompleted(ref TA awaiter, ref TSM stateMachine) where TA : INotifyCompletion where TSM : IAsyncStateMachine { } @@ -3495,6 +3932,8 @@ public void SetResult() { } public void SetException(Exception ex) { } public MyTask Task => null; } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var comp2 = CreateCompilation(source2, options: TestOptions.DebugExe); @@ -4390,5 +4829,6 @@ class C // async Task GetNumber(Task task) { await task; } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ await task; }").WithArguments("System.Runtime.CompilerServices.IAsyncStateMachine", "SetStateMachine").WithLocation(62, 37)); } + } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs index f9629b82328c8..84a91b7fef665 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs @@ -31,9 +31,9 @@ static void Main() Console.WriteLine(i); } } +[AsyncBuilder(typeof(MyTaskMethodBuilder))] struct MyTask { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(new MyTask()); internal Awaiter GetAwaiter() => new Awaiter(); internal class Awaiter : INotifyCompletion { @@ -42,10 +42,10 @@ public void OnCompleted(Action a) { } internal void GetResult() { } } } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] struct MyTask { internal T _result; - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(new MyTask()); public T Result => _result; internal Awaiter GetAwaiter() => new Awaiter(this); internal class Awaiter : INotifyCompletion @@ -60,6 +60,7 @@ public void OnCompleted(Action a) { } struct MyTaskMethodBuilder { private MyTask _task; + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(new MyTask()); internal MyTaskMethodBuilder(MyTask task) { _task = task; @@ -78,6 +79,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter struct MyTaskMethodBuilder { private MyTask _task; + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(new MyTask()); internal MyTaskMethodBuilder(MyTask task) { _task = task; @@ -92,7 +94,10 @@ public void SetException(Exception e) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public MyTask Task => _task; -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); var verifier = CompileAndVerify(compilation, expectedOutput: "3"); verifier.VerifyDiagnostics(); @@ -112,7 +117,7 @@ .locals init (C.d__0 V_0, IL_0000: newobj ""C.d__0..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - IL_0007: call ""MyTaskMethodBuilder MyTask.CreateAsyncMethodBuilder()"" + IL_0007: call ""MyTaskMethodBuilder MyTaskMethodBuilder.Create()"" IL_000c: stfld ""MyTaskMethodBuilder C.d__0.<>t__builder"" IL_0011: ldloc.0 IL_0012: ldc.i4.m1 @@ -140,7 +145,7 @@ .locals init (C.d__1 V_0, IL_0007: ldarg.0 IL_0008: stfld ""T C.d__1.t"" IL_000d: ldloc.0 - IL_000e: call ""MyTaskMethodBuilder MyTask.CreateAsyncMethodBuilder()"" + IL_000e: call ""MyTaskMethodBuilder MyTaskMethodBuilder.Create()"" IL_0013: stfld ""MyTaskMethodBuilder C.d__1.<>t__builder"" IL_0018: ldloc.0 IL_0019: ldc.i4.m1 @@ -170,16 +175,13 @@ class C static async MyTask F() { await (Task)null; } static async MyTask G(T t) { await (Task)null; return t; } } -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} +[AsyncBuilder(typeof(MyTaskMethodBuilder))] +struct MyTask { } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] +struct MyTask { } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -187,10 +189,14 @@ public void SetResult() { } } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public MyTask Task { get { return default(MyTask); } } -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyEmitDiagnostics( // (6,29): error CS0656: Missing compiler required member 'MyTaskMethodBuilder.Task' @@ -213,16 +219,13 @@ class C static async MyTask F() { } static async MyTask G() { return 3; } #pragma warning restore CS1998 - private class MyTask - { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; - } - private class MyTask - { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; - } + [AsyncBuilder(typeof(MyTaskMethodBuilder))] + private class MyTask { } + [AsyncBuilder(typeof(MyTaskMethodBuilder<>))] + private class MyTask { } private class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -233,6 +236,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter } private class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -241,7 +245,10 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public MyTask Task { get { return null; } } } -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); var verifier = CompileAndVerify(compilation); verifier.VerifyDiagnostics(); @@ -276,9 +283,9 @@ static void M() #pragma warning restore CS1998 } } +[AsyncBuilder(typeof(MyTaskMethodBuilder))] class MyTask { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -287,9 +294,9 @@ public void OnCompleted(Action a) { } internal void GetResult() { } } } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] class MyTask { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -300,6 +307,7 @@ public void OnCompleted(Action a) { } } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -310,6 +318,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -317,7 +326,10 @@ public void SetResult(T t) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public MyTask Task => default(MyTask); -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); var verifier = CompileAndVerify(compilation); verifier.VerifyDiagnostics(); @@ -350,9 +362,9 @@ async MyTask F() { } #pragma warning restore CS1998 } } +[AsyncBuilder(typeof(MyTaskMethodBuilder))] struct MyTask { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -361,9 +373,9 @@ public void OnCompleted(Action a) { } internal void GetResult() { } } } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] struct MyTask { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -374,6 +386,7 @@ public void OnCompleted(Action a) { } } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -384,6 +397,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -391,7 +405,10 @@ public void SetResult(T t) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public MyTask Task => default(MyTask); -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); var verifier = CompileAndVerify(compilation); verifier.VerifyDiagnostics(); @@ -425,9 +442,9 @@ static void M(object o) #pragma warning restore CS1998 } } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] class MyTask { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -438,6 +455,7 @@ public void OnCompleted(Action a) { } } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetException(Exception e) { } @@ -445,7 +463,10 @@ public void SetResult(T t) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public MyTask Task => default(MyTask); -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }); var verifier = CompileAndVerify( compilation, @@ -483,9 +504,9 @@ static async void M() #pragma warning restore CS1998 } } -struct MyTask +[AsyncBuilder(typeof(string))] +public struct MyTask { - public static string CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -493,12 +514,18 @@ public void OnCompleted(Action a) { } internal bool IsCompleted => true; internal void GetResult() { } } -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyEmitDiagnostics( // (8,26): error CS0656: Missing compiler required member 'string.Task' // async MyTask F() { }; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ }").WithArguments("string", "Task").WithLocation(8, 26)); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ }").WithArguments("string", "Task").WithLocation(8, 26), + // (8,26): error CS0656: Missing compiler required member 'string.Create' + // async MyTask F() { }; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ }").WithArguments("string", "Create").WithLocation(8, 26)); } [Fact] @@ -517,9 +544,9 @@ static async void M() #pragma warning restore CS1998 } } -struct MyTask +[AsyncBuilder(typeof(IEquatable<>))] +public struct MyTask { - public static IEquatable CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -527,12 +554,18 @@ public void OnCompleted(Action a) { } internal bool IsCompleted => true; internal T GetResult() => default(T); } -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyEmitDiagnostics( // (8,35): error CS0656: Missing compiler required member 'IEquatable.Task' // async MyTask F(T t) => t; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> t").WithArguments("System.IEquatable", "Task").WithLocation(8, 35)); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> t").WithArguments("System.IEquatable", "Task").WithLocation(8, 35), + // (8,35): error CS0656: Missing compiler required member 'IEquatable.Create' + // async MyTask F(T t) => t; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> t").WithArguments("System.IEquatable", "Create").WithLocation(8, 35)); } [Fact] @@ -551,9 +584,9 @@ static async void M() #pragma warning restore CS1998 } } +[AsyncBuilder(typeof(object[]))] struct MyTask { - public static object[] CreateAsyncMethodBuilder() => null; internal Awaiter GetAwaiter() => null; internal class Awaiter : INotifyCompletion { @@ -561,15 +594,76 @@ public void OnCompleted(Action a) { } internal bool IsCompleted => true; internal void GetResult() { } } -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyEmitDiagnostics( - // (8,22): error CS0161: 'F()': not all code paths return a value - // async MyTask F() { }; - Diagnostic(ErrorCode.ERR_ReturnExpected, "F").WithArguments("F()").WithLocation(8, 22), // (8,22): error CS1983: The return type of an async method must be void, Task or Task // async MyTask F() { }; - Diagnostic(ErrorCode.ERR_BadAsyncReturn, "F").WithLocation(8, 22)); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "{ }").WithLocation(8, 26)); + } + + [Fact] + static void AsyncBuilderAttributeMultipleParameters() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(typeof(B1),1)] class T1 { } +class B1 { } + +[AsyncBuilder(typeof(B2))] class T2 { } +class B2 { } + +class Program { + static void Main() { } + async T1 f1() => await Task.Delay(1); + async T2 f2() => await Task.Delay(1); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t, int i) { } } } +"; + var compilation = CreateCompilationWithMscorlib45(source); + compilation.VerifyEmitDiagnostics( + // (8,2): error CS7036: There is no argument given that corresponds to the required formal parameter 'i' of 'AsyncBuilderAttribute.AsyncBuilderAttribute(Type, int)' + // [AsyncBuilder(typeof(B2))] class T2 { } + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "AsyncBuilder(typeof(B2))").WithArguments("i", "System.Runtime.CompilerServices.AsyncBuilderAttribute.AsyncBuilderAttribute(System.Type, int)").WithLocation(8, 2), + // (13,14): error CS1983: The return type of an async method must be void, Task or Task + // async T1 f1() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "f1").WithLocation(13, 14), + // (14,14): error CS1983: The return type of an async method must be void, Task or Task + // async T2 f2() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "f2").WithLocation(14, 14) + ); } + + + [Fact] + static void AsyncBuilderAttributeSingleParameterWrong() + { + var source = @" +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +[AsyncBuilder(1)] class T { } + +class Program { + static void Main() { } + async T f() => await Task.Delay(1); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(int i) { } } } +"; + var compilation = CreateCompilationWithMscorlib45(source); + compilation.VerifyEmitDiagnostics( + // (9,13): error CS1983: The return type of an async method must be void, Task or Task + // async T f() => await Task.Delay(1); + Diagnostic(ErrorCode.ERR_BadAsyncReturn, "f").WithLocation(9, 13) + ); + } + } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeTests.cs index 6d113440120a0..ed04be501d39b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeTests.cs @@ -13,12 +13,17 @@ public void AsyncTasklikeFromBuilderMethod() { var source = @" using System.Threading.Tasks; +using System.Runtime.CompilerServices; class C { async ValueTask f() { await (Task)null; } async ValueTask g() { await (Task)null; return 1; } } -struct ValueTask { public static string CreateAsyncMethodBuilder() => null; } -struct ValueTask { public static Task CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(string))] +struct ValueTask { } +[AsyncBuilder(typeof(Task<>))] +struct ValueTask { } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var compilation = CreateCompilationWithMscorlib45(source).VerifyDiagnostics(); @@ -52,11 +57,6 @@ static async Tasklike g() { await (Task)null; } - - static async UnTasklike h() - { - await (Task)null; - } } class Awaitable @@ -69,17 +69,12 @@ class Unawaitable public Func GetAwaiter = () => (Task.FromResult(1) as Task).GetAwaiter(); } -public class Tasklike { - public static TasklikeMethodBuilder CreateAsyncMethodBuilder() => null; -} - -public class UnTasklike -{ - public static Func CreateAsyncMethodBuilder = () => null; -} +[AsyncBuilder(typeof(TasklikeMethodBuilder))] +public class Tasklike { } public class TasklikeMethodBuilder { + public static TasklikeMethodBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult() { } @@ -90,28 +85,12 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } -public class UnTasklikeMethodBuilder -{ - public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } - public void SetStateMachine(IAsyncStateMachine stateMachine) { } - public void SetResult() { } - public void SetException(Exception exception) { } - private void EnsureTaskBuilder() { } - public UnTasklike Task => null; - public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } - public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } -} +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CreateCompilationWithMscorlib45(source).VerifyDiagnostics( // (15,9): error CS0118: 'GetAwaiter' is a field but is used like a method // await new Unawaitable(); // error: GetAwaiter must be a field not a delegate - Diagnostic(ErrorCode.ERR_BadSKknown, "await new Unawaitable()").WithArguments("GetAwaiter", "field", "method").WithLocation(15, 9), - // (23,29): error CS1983: The return type of an async method must be void, Task, Task or other tasklike - // static async UnTasklike h() - Diagnostic(ErrorCode.ERR_BadAsyncReturn, "h").WithLocation(23, 29), - // (23,29): error CS0161: 'Program.h()': not all code paths return a value - // static async UnTasklike h() - Diagnostic(ErrorCode.ERR_ReturnExpected, "h").WithArguments("Program.h()").WithLocation(23, 29) + Diagnostic(ErrorCode.ERR_BadSKknown, "await new Unawaitable()").WithArguments("GetAwaiter", "field", "method").WithLocation(15, 9) ); } @@ -132,9 +111,9 @@ static void Main() <> <> } +[AsyncBuilder(typeof(ValueTaskMethodBuilder))] struct ValueTask { - public static ValueTaskMethodBuilder CreateAsyncMethodBuilder() => new ValueTaskMethodBuilder(); <> internal Awaiter GetAwaiter() => new Awaiter(); internal class Awaiter : INotifyCompletion @@ -144,10 +123,10 @@ public void OnCompleted(Action a) { } internal void GetResult() { } } } +[AsyncBuilder(typeof(ValueTaskMethodBuilder<>))] struct ValueTask { internal T _result; - public static ValueTaskMethodBuilder CreateAsyncMethodBuilder() => new ValueTaskMethodBuilder(); <> public T Result => _result; internal Awaiter GetAwaiter() => new Awaiter(this); @@ -163,6 +142,7 @@ public void OnCompleted(Action a) { } sealed class ValueTaskMethodBuilder { private ValueTask _task = new ValueTask(); + public static ValueTaskMethodBuilder Create() => new ValueTaskMethodBuilder(); public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { @@ -177,6 +157,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter sealed class ValueTaskMethodBuilder { private ValueTask _task = new ValueTask(); + public static ValueTaskMethodBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { @@ -187,7 +168,10 @@ public void SetException(Exception e) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } public ValueTask Task => _task; -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; source = source.Replace("<>", arg); source = source.Replace("<>", (betterOverload != null) ? "static string " + betterOverload + " => \"better\";" : ""); source = source.Replace("<>", (worseOverload != null) ? "static string " + worseOverload + " => \"worse\";" : ""); @@ -303,14 +287,19 @@ public void AsyncTasklikeMethod() { var source = @" using System.Threading.Tasks; +using System.Runtime.CompilerServices; class C { async ValueTask f() { await Task.Delay(0); } async ValueTask g() { await Task.Delay(0); return 1; } } -struct ValueTask { public static ValueTaskMethodBuilder CreateAsyncMethodBuilder() => null; } -struct ValueTask { public static ValueTaskMethodBuilder CreateAsyncMethodBuilder() => null;} +[AsyncBuilder(typeof(ValueTaskMethodBuilder))] +struct ValueTask { } +[AsyncBuilder(typeof(ValueTaskMethodBuilder<>))] +struct ValueTask { } class ValueTaskMethodBuilder {} class ValueTaskMethodBuilder {} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var compilation = CreateCompilationWithMscorlib45(source).VerifyDiagnostics(); var methodf = compilation.GetMember("C.f"); @@ -360,13 +349,20 @@ public class MyTask { } var source3 = @" using System.Threading.Tasks; +using System.Runtime.CompilerServices; class C { static void Main() { } async MyTask f() { await (Task)null; } } -public class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } -public class MyTaskBuilder { } +[AsyncBuilder(typeof(MyTaskBuilder))] +public class MyTask { } +public class MyTaskBuilder +{ + public static MyTaskBuilder Create() => null; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CreateCompilationWithMscorlib45(source3).VerifyDiagnostics(); } @@ -391,8 +387,10 @@ static void h(Func lambda) { } static void h(Func lambda) { } } -public class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder<>))] +public class MyTask { } public class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult(T result) { } @@ -402,9 +400,11 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } -public class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder))] +public class MyTask { } public class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult() { } @@ -413,6 +413,8 @@ public void SetException(Exception exception) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CreateCompilationWithMscorlib45(source).VerifyDiagnostics( // (8,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.h(Func)' and 'C.h(Func)' @@ -430,8 +432,11 @@ public void AsyncTasklikeInadmissibleArity() class C { async Mismatch2 g() { await Task.Delay(0); return 1; } } -struct Mismatch2 { public static Mismatch2MethodBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(Mismatch2MethodBuilder<>))] +struct Mismatch2 { } class Mismatch2MethodBuilder {} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; var comp = CreateCompilationWithMscorlib45(source); comp.VerifyEmitDiagnostics( @@ -464,21 +469,22 @@ static void Main() } } +[AsyncBuilder(typeof(ValueTaskBuilder<>))] class ValueTask { - public static ValueTaskBuilder CreateAsyncMethodBuilder() => null; public static implicit operator ValueTask(Task task) => null; } +[AsyncBuilder(typeof(MyTaskBuilder<>))] class MyTask { - public static MyTaskBuilder CreateAsyncMethodBuilder() => null; public static implicit operator MyTask(Task task) => null; public static implicit operator Task(MyTask mytask) => null; } class ValueTaskBuilder { + public static ValueTaskBuilder Create() => null; public void Start(ref TSM sm) where TSM : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine sm) { } public void SetResult(T r) { } @@ -490,6 +496,7 @@ public void AwaitUnsafeOnCompleted(ref TA a, ref TSM sm) where TA : ICr class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void Start(ref TSM sm) where TSM : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine sm) { } public void SetResult(T r) { } @@ -498,6 +505,8 @@ public void SetException(Exception ex) { } public void AwaitOnCompleted(ref TA a, ref TSM sm) where TA : INotifyCompletion where TSM : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TA a, ref TSM sm) where TA : ICriticalNotifyCompletion where TSM : IAsyncStateMachine { } } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CompileAndVerify(source, additionalRefs: new[] { MscorlibRef_v4_0_30316_17626 }, expectedOutput: "1"); } @@ -533,13 +542,12 @@ static void Main() } } -public class ValueTask -{ - public static ValueTaskBuilder CreateAsyncMethodBuilder() => null; -} +[AsyncBuilder(typeof(ValueTaskBuilder<>))] +public class ValueTask { } public class ValueTaskBuilder { + public static ValueTaskBuilder Create() => null; public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void Start(ref TSM stateMachine) where TSM : IAsyncStateMachine { } public void AwaitOnCompleted(ref TA awaiter, ref TSM stateMachine) where TA : INotifyCompletion where TSM : IAsyncStateMachine { } @@ -548,6 +556,8 @@ public void SetResult(T result) { } public void SetException(Exception ex) { } public ValueTask Task => null; } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CompileAndVerify(source, additionalRefs: new[] { MscorlibRef_v4_0_30316_17626 }, expectedOutput: "bbbb"); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs index d0b7eef02ac4d..14e4fd82f0105 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionTests.cs @@ -487,9 +487,11 @@ static void Main() static void h(Func> lambda) { } static void h(Func> lambda) { } } -public class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder<>))] +public class MyTask { } public class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult(T result) { } @@ -498,6 +500,8 @@ public void SetException(Exception exception) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CreateCompilationWithMscorlib45(source1).VerifyDiagnostics( // (9,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.h(Func>)' and 'C.h(Func>)' @@ -518,9 +522,11 @@ static void Main() static void k(Func> lambda) { } static void k(Func> lambda) { } } -public class MyTask { public static MyTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskBuilder<>))] +public class MyTask { } public class MyTaskBuilder { + public static MyTaskBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult(T result) { } @@ -530,9 +536,11 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } -public class YourTask { public static YourTaskBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(YourTask<>))] +public class YourTask { } public class YourTaskBuilder { + public static YourTaskBuilder Create() => null; public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { } public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetResult(T result) { } @@ -541,6 +549,8 @@ public void SetException(Exception exception) { } public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { } public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { } } + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } "; CreateCompilationWithMscorlib45(source2).VerifyDiagnostics( // (9,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.k(Func>)' and 'C.k(Func>)' @@ -553,7 +563,9 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter public void NormalizeTaskTypes() { string source = -@"class A +@" +using System.Runtime.CompilerServices; +class A { internal struct B { } } @@ -567,20 +579,21 @@ unsafe class C static int* F4; #pragma warning restore CS0169 } -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} +[AsyncBuilder(typeof(MyTaskMethodBuilder))] +struct MyTask { } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] +struct MyTask { } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); } struct MyTaskMethodBuilder { -}"; + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeDebugDll); compilation.VerifyDiagnostics(); @@ -615,6 +628,7 @@ public void NormalizeTaskTypes_Tuples() { string source = @"using System; +using System.Runtime.CompilerServices; using System.Threading.Tasks; class C { @@ -625,19 +639,17 @@ class C static (MyTask, char, byte, short, ushort, int, uint, long, ulong, char, byte, short, ushort, int, uint, long, MyTask) F3; #pragma warning restore CS0169 } -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} +[AsyncBuilder(typeof(MyTaskMethodBuilder))] +struct MyTask { } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] +struct MyTask { } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); } namespace System { @@ -657,7 +669,11 @@ class TupleElementNamesAttribute : Attribute { public TupleElementNamesAttribute(string[] names) { } } -}"; + +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyDiagnostics(); @@ -715,12 +731,12 @@ .method public hidebysig specialname rtspecialname instance void .ctor() cil man } .class public MyTask { - .method public hidebysig static class MyTaskMethodBuilder CreateAsyncMethodBuilder() cil managed { ldnull ret } + .custom instance void System.Runtime.CompilerServices.AsyncBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder) } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .class public MyTask`1 { - .method public hidebysig static class MyTaskMethodBuilder`1 CreateAsyncMethodBuilder() cil managed { ldnull ret } + .custom instance void System.Runtime.CompilerServices.AsyncBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder`1) } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .class public MyTaskMethodBuilder @@ -731,6 +747,13 @@ .class public MyTaskMethodBuilder`1 { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } +.namespace System.Runtime.CompilerServices +{ + .class public AsyncBuilderAttribute extends [mscorlib]System.Attribute + { + .method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Type t) cil managed { ret } + } +} "; var source = @""; @@ -748,24 +771,28 @@ .method public hidebysig specialname rtspecialname instance void .ctor() cil man public void NormalizeTaskTypes_Pointers() { string source = -@"unsafe class C +@" +using System.Runtime.CompilerServices; +unsafe class C { #pragma warning disable CS0169 static C>* F0; #pragma warning restore CS0169 } -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] +struct MyTask { } struct MyTaskMethodBuilder { -}"; + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeDebugDll); compilation.VerifyDiagnostics( // (4,12): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C>') // static C>* F0; - Diagnostic(ErrorCode.ERR_ManagedAddr, "C>*").WithArguments("C>").WithLocation(4, 12)); + Diagnostic(ErrorCode.ERR_ManagedAddr, "C>*").WithArguments("C>").WithLocation(6, 12)); var type = compilation.GetMember("C.F0").Type; var normalized = type.NormalizeTaskTypes(compilation); @@ -784,13 +811,20 @@ .method public hidebysig specialname rtspecialname instance void .ctor() cil man } .class public MyTask { - .method public hidebysig static class MyTaskMethodBuilder CreateAsyncMethodBuilder() cil managed { ldnull ret } + .custom instance void System.Runtime.CompilerServices.AsyncBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder) } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } .class public MyTaskMethodBuilder { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } } +.namespace System.Runtime.CompilerServices +{ + .class public AsyncBuilderAttribute extends [mscorlib]System.Attribute + { + .method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Type t) cil managed { ret } + } +} "; var source = @""; @@ -808,35 +842,38 @@ .method public hidebysig specialname rtspecialname instance void .ctor() cil man public void NormalizeTaskTypes_Errors() { string source = -@"class C +@" +using System.Runtime.CompilerServices; +class C { #pragma warning disable CS0169 static A F0; static MyTask F1; #pragma warning restore CS0169 } -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} +[AsyncBuilder(typeof(MyTaskMethodBuilder))] +struct MyTask { } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] +struct MyTask { } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); } struct MyTaskMethodBuilder { -}"; + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyDiagnostics( // (5,19): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?) // static MyTask F1; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(5, 19), + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(7, 19), // (4,12): error CS0246: The type or namespace name 'A<,>' could not be found (are you missing a using directive or an assembly reference?) // static A F0; - Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "A").WithArguments("A<,>").WithLocation(4, 12)); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "A").WithArguments("A<,>").WithLocation(6, 12)); var type = compilation.GetMember("C.F0").Type; Assert.Equal(TypeKind.Error, type.TypeKind); @@ -855,7 +892,9 @@ struct MyTaskMethodBuilder public void NormalizeTaskTypes_Inner() { string source = -@"class C +@" +using System.Runtime.CompilerServices; +class C { #pragma warning disable CS0169 static MyTask F0; @@ -865,21 +904,22 @@ public void NormalizeTaskTypes_Inner() class Inner { } - class MyTask - { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; - } - class MyTask - { - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; - } + [AsyncBuilder(typeof(C<,>.MyTaskMethodBuilder))] + class MyTask { } + [AsyncBuilder(typeof(C<,>.MyTaskMethodBuilder<>))] + class MyTask { } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; } -}"; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyDiagnostics(); @@ -903,29 +943,36 @@ class MyTaskMethodBuilder public void NormalizeTaskTypes_Outer() { string source = -@"class C +@" +using System.Runtime.CompilerServices; +class C { #pragma warning disable CS0169 static MyTask F0; static MyTask>.B F1; #pragma warning restore CS0169 } +[AsyncBuilder(typeof(MyTaskMethodBuilder))] class MyTask { internal class A { } - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] class MyTask { internal class B { } - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => null; } class MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => null; } class MyTaskMethodBuilder { -}"; + public static MyTaskMethodBuilder Create() => null; +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilationWithMscorlib45(source); compilation.VerifyDiagnostics(); @@ -948,26 +995,29 @@ class MyTaskMethodBuilder public void NormalizeTaskTypes_MissingWellKnownTypes() { string source = -@"class C +@" +using System.Runtime.CompilerServices; +class C { #pragma warning disable CS0169 static MyTask F; #pragma warning restore CS0169 } -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} -struct MyTask -{ - public static MyTaskMethodBuilder CreateAsyncMethodBuilder() => new MyTaskMethodBuilder(); -} +[AsyncBuilder(typeof(MyTaskMethodBuilder))] +struct MyTask { } +[AsyncBuilder(typeof(MyTaskMethodBuilder<>))] +struct MyTask { } struct MyTaskMethodBuilder { + public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); } struct MyTaskMethodBuilder { -}"; + public MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(); +} + +namespace System.Runtime.CompilerServices { class AsyncBuilderAttribute : System.Attribute { public AsyncBuilderAttribute(System.Type t) { } } } +"; var compilation = CreateCompilation(source, references: new[] { MscorlibRef_v20 }); compilation.VerifyDiagnostics(); var type = compilation.GetMember("C.F").Type; diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 62ddc2ba18e51..ebf224aa86baa 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -703,7 +703,6 @@ Microsoft.CodeAnalysis.Text.SourceText.GetChecksum() -> System.Collections.Immut abstract Microsoft.CodeAnalysis.Diagnostics.OperationBlockStartAnalysisContext.RegisterOperationAction(System.Action action, System.Collections.Immutable.ImmutableArray operationKinds) -> void abstract Microsoft.CodeAnalysis.Diagnostics.OperationBlockStartAnalysisContext.RegisterOperationBlockEndAction(System.Action action) -> void abstract Microsoft.CodeAnalysis.SemanticModel.GetOperationCore(Microsoft.CodeAnalysis.SyntaxNode node, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.IOperation -const Microsoft.CodeAnalysis.WellKnownMemberNames.CreateAsyncMethodBuilder = "CreateAsyncMethodBuilder" -> string override Microsoft.CodeAnalysis.Semantics.OperationWalker.Visit(Microsoft.CodeAnalysis.IOperation operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitAddressOfExpression(Microsoft.CodeAnalysis.Semantics.IAddressOfExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitArgument(Microsoft.CodeAnalysis.Semantics.IArgument operation) -> void diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index 05d7f98207b9d..353034c83a3a9 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -344,6 +344,7 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfWindowsRuntimeImportAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfDynamicSecurityMethodAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfRequiredAttributeAttribute = { s_signature_HasThis_Void_Type }; + private static readonly byte[][] s_signaturesOfAsyncBuilderAttribute = { s_signature_HasThis_Void_Type }; private static readonly byte[][] s_signaturesOfAsyncStateMachineAttribute = { s_signature_HasThis_Void_Type }; private static readonly byte[][] s_signaturesOfIteratorStateMachineAttribute = { s_signature_HasThis_Void_Type }; private static readonly byte[][] s_signaturesOfRuntimeCompatibilityAttribute = { s_signature_HasThis_Void }; @@ -467,6 +468,7 @@ static AttributeDescription() internal static readonly AttributeDescription WindowsRuntimeImportAttribute = new AttributeDescription("System.Runtime.InteropServices.WindowsRuntime", "WindowsRuntimeImportAttribute", s_signaturesOfWindowsRuntimeImportAttribute); internal static readonly AttributeDescription DynamicSecurityMethodAttribute = new AttributeDescription("System.Security", "DynamicSecurityMethodAttribute", s_signaturesOfDynamicSecurityMethodAttribute); internal static readonly AttributeDescription RequiredAttributeAttribute = new AttributeDescription("System.Runtime.CompilerServices", "RequiredAttributeAttribute", s_signaturesOfRequiredAttributeAttribute); + internal static readonly AttributeDescription AsyncBuilderAttribute = new AttributeDescription("System.Runtime.CompilerServices", "AsyncBuilderAttribute", s_signaturesOfAsyncBuilderAttribute); internal static readonly AttributeDescription AsyncStateMachineAttribute = new AttributeDescription("System.Runtime.CompilerServices", "AsyncStateMachineAttribute", s_signaturesOfAsyncStateMachineAttribute); internal static readonly AttributeDescription IteratorStateMachineAttribute = new AttributeDescription("System.Runtime.CompilerServices", "IteratorStateMachineAttribute", s_signaturesOfIteratorStateMachineAttribute); internal static readonly AttributeDescription CompilationRelaxationsAttribute = new AttributeDescription("System.Runtime.CompilerServices", "CompilationRelaxationsAttribute", s_signaturesOfCompilationRelaxationsAttribute); diff --git a/src/Compilers/Core/Portable/Symbols/WellKnownMemberNames.cs b/src/Compilers/Core/Portable/Symbols/WellKnownMemberNames.cs index d8411efe8acca..3345a2f2d1591 100644 --- a/src/Compilers/Core/Portable/Symbols/WellKnownMemberNames.cs +++ b/src/Compilers/Core/Portable/Symbols/WellKnownMemberNames.cs @@ -298,11 +298,5 @@ public static class WellKnownMemberNames /// (see C# Specification, ยง7.7.7.1 Awaitable expressions). /// public const string OnCompleted = nameof(OnCompleted); - - /// - /// The required name for the CreateAsyncMethodBuilder method used to - /// build a tasklike instance. - /// - public const string CreateAsyncMethodBuilder = "CreateAsyncMethodBuilder"; } }