Skip to content

Commit e1f1d41

Browse files
author
Julien Couvreur
committed
Relax accessibility requirements for overrides
1 parent f084cb2 commit e1f1d41

File tree

2 files changed

+51
-21
lines changed

2 files changed

+51
-21
lines changed

src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncMethodBuilderMemberCollection.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
189189

190190
if ((object)methodLevelBuilder != null)
191191
{
192-
var initialBuilderType = ValidateBuilderType(F, methodLevelBuilder, returnType.DeclaredAccessibility, isGeneric: false);
192+
var initialBuilderType = ValidateBuilderType(F, methodLevelBuilder, returnType.DeclaredAccessibility, isGeneric: false, forOverride: true);
193193
customBuilder = true;
194194
if ((object)initialBuilderType != null)
195195
{
@@ -282,7 +282,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
282282

283283
if ((object)methodLevelBuilder != null)
284284
{
285-
var initialBuilderType = ValidateBuilderType(F, methodLevelBuilder, returnType.DeclaredAccessibility, isGeneric: true);
285+
var initialBuilderType = ValidateBuilderType(F, methodLevelBuilder, returnType.DeclaredAccessibility, isGeneric: true, forOverride: true);
286286
customBuilder = true;
287287
if ((object)initialBuilderType != null)
288288
{
@@ -361,14 +361,14 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method,
361361
throw ExceptionUtilities.UnexpectedValue(method);
362362
}
363363

364-
private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F, object builderAttributeArgument, Accessibility desiredAccessibility, bool isGeneric)
364+
private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F, object builderAttributeArgument, Accessibility desiredAccessibility, bool isGeneric, bool forOverride = false)
365365
{
366366
var builderType = builderAttributeArgument as NamedTypeSymbol;
367367

368368
if ((object)builderType != null &&
369369
!builderType.IsErrorType() &&
370370
!builderType.IsVoidType() &&
371-
builderType.DeclaredAccessibility == desiredAccessibility)
371+
(forOverride || builderType.DeclaredAccessibility == desiredAccessibility))
372372
{
373373
bool isArityOk = isGeneric
374374
? builderType.IsUnboundGenericType && builderType.ContainingType?.IsGenericType != true && builderType.Arity == 1

src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMethodBuilderOverrideTests.cs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,9 @@ public void BuilderFactoryOnMethod_BuilderFactoryIsInternal()
11331133
using System;
11341134
using System.Runtime.CompilerServices;
11351135
using System.Threading.Tasks;
1136+
1137+
Console.WriteLine(await C.M());
1138+
11361139
class C
11371140
{{
11381141
[AsyncMethodBuilder(typeof(MyTaskMethodBuilderFactory))]
@@ -1142,7 +1145,7 @@ class C
11421145
static async MyTask<T> G<T>(T t) {{ System.Console.Write(""G ""); await Task.Delay(0); return t; }}
11431146
11441147
[AsyncMethodBuilder(typeof(MyTaskMethodBuilderFactory<>))]
1145-
static async MyTask<int> M() {{ System.Console.Write(""M ""); await F(); return await G(3); }}
1148+
public static async MyTask<int> M() {{ System.Console.Write(""M ""); await F(); return await G(3); }}
11461149
}}
11471150
11481151
[AsyncMethodBuilder(null)]
@@ -1156,17 +1159,44 @@ class C
11561159
{AsyncMethodBuilderAttribute}
11571160
";
11581161
var compilation = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.RegularPreview);
1159-
compilation.VerifyEmitDiagnostics(
1160-
// (8,29): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>
1161-
// static async MyTask F() { System.Console.Write("F "); await Task.Delay(0); }
1162-
Diagnostic(ErrorCode.ERR_BadAsyncReturn, @"{ System.Console.Write(""F ""); await Task.Delay(0); }").WithLocation(8, 29),
1163-
// (11,38): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>
1164-
// static async MyTask<T> G<T>(T t) { System.Console.Write("G "); await Task.Delay(0); return t; }
1165-
Diagnostic(ErrorCode.ERR_BadAsyncReturn, @"{ System.Console.Write(""G ""); await Task.Delay(0); return t; }").WithLocation(11, 38),
1166-
// (14,34): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>
1167-
// static async MyTask<int> M() { System.Console.Write("M "); await F(); return await G(3); }
1168-
Diagnostic(ErrorCode.ERR_BadAsyncReturn, @"{ System.Console.Write(""M ""); await F(); return await G(3); }").WithLocation(14, 34)
1169-
);
1162+
CompileAndVerify(compilation, expectedOutput: "M F G 3");
1163+
}
1164+
1165+
[Fact]
1166+
public void BuilderFactoryOnMethod_BuilderFactoryIsPrivate()
1167+
{
1168+
var source = $@"
1169+
using System;
1170+
using System.Runtime.CompilerServices;
1171+
using System.Threading.Tasks;
1172+
1173+
Console.WriteLine(await C.M());
1174+
1175+
class C
1176+
{{
1177+
[AsyncMethodBuilder(typeof(MyTaskMethodBuilderFactory))]
1178+
static async MyTask F() {{ System.Console.Write(""F ""); await Task.Delay(0); }}
1179+
1180+
[AsyncMethodBuilder(typeof(MyTaskMethodBuilderFactory<>))]
1181+
static async MyTask<T> G<T>(T t) {{ System.Console.Write(""G ""); await Task.Delay(0); return t; }}
1182+
1183+
[AsyncMethodBuilder(typeof(MyTaskMethodBuilderFactory<>))]
1184+
public static async MyTask<int> M() {{ System.Console.Write(""M ""); await F(); return await G(3); }}
1185+
1186+
{AsyncBuilderFactoryCode("MyTaskMethodBuilder", "MyTask").Replace("public class MyTaskMethodBuilderFactory", "private class MyTaskMethodBuilderFactory")}
1187+
{AsyncBuilderFactoryCode("MyTaskMethodBuilder", "MyTask", "T").Replace("public class MyTaskMethodBuilderFactory<T>", "private class MyTaskMethodBuilderFactory<T>")}
1188+
}}
1189+
1190+
[AsyncMethodBuilder(null)]
1191+
{AwaitableTypeCode("MyTask")}
1192+
1193+
[AsyncMethodBuilder(null)]
1194+
{AwaitableTypeCode("MyTask", "T")}
1195+
1196+
{AsyncMethodBuilderAttribute}
1197+
";
1198+
var compilation = CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.RegularPreview);
1199+
CompileAndVerify(compilation, expectedOutput: "M F G 3");
11701200
}
11711201

11721202
[Fact]
@@ -2063,7 +2093,7 @@ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter
20632093
}
20642094

20652095
[Fact]
2066-
public void BuilderFactoryOnMethod_WrongAccessibilityForFinalBuilder()
2096+
public void BuilderFactoryOnMethod_WrongAccessibilityForFinalBuilderMembers()
20672097
{
20682098
var source = $@"
20692099
using System;
@@ -2112,12 +2142,12 @@ class Program
21122142
// (97,19): error CS0656: Missing compiler required member 'B2Factory.Create'
21132143
// async T2 f2() => await Task.Delay(2);
21142144
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(2)").WithArguments("B2Factory", "Create").WithLocation(97, 19),
2115-
// (100,19): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>
2145+
// (100,19): error CS0656: Missing compiler required member 'B3.Task'
21162146
// async T3 f3() => await Task.Delay(3);
2117-
Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(3)").WithLocation(100, 19),
2118-
// (103,19): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>
2147+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(3)").WithArguments("B3", "Task").WithLocation(100, 19),
2148+
// (103,19): error CS0656: Missing compiler required member 'B4Factory.Create'
21192149
// async T4 f4() => await Task.Delay(4);
2120-
Diagnostic(ErrorCode.ERR_BadAsyncReturn, "=> await Task.Delay(4)").WithLocation(103, 19)
2150+
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=> await Task.Delay(4)").WithArguments("B4Factory", "Create").WithLocation(103, 19)
21212151
);
21222152
}
21232153

0 commit comments

Comments
 (0)