-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow overriding the AsyncMethodBuilder on methods #54033
Changes from all commits
78a89b7
f084cb2
e1f1d41
a39ee15
e4ab3c3
72cbc01
3e9518b
2a3fdf1
869671b
22b5373
8ac378a
2e7ad79
4375aea
43416a2
d5c0a27
f7900d8
e7ed4e3
af160e2
4218507
ee207cb
ec32fb2
9637282
7da7da7
457aac7
3268386
9440d0f
a576b8c
36b5a5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,7 +159,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
out createBuilderMethod); | ||
if ((object)createBuilderMethod == null) | ||
{ | ||
collection = default(AsyncMethodBuilderMemberCollection); | ||
collection = default; | ||
return false; | ||
} | ||
return TryCreate( | ||
|
@@ -178,18 +178,30 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
collection: out collection); | ||
} | ||
|
||
if (method.IsAsyncReturningTask(F.Compilation)) | ||
object methodLevelBuilder = null; | ||
if (method.IsAsyncEffectivelyReturningTask(F.Compilation)) | ||
{ | ||
var returnType = (NamedTypeSymbol)method.ReturnType; | ||
NamedTypeSymbol builderType; | ||
MethodSymbol createBuilderMethod = null; | ||
PropertySymbol taskProperty = null; | ||
|
||
bool useMethodLevelBuilder = method.HasAsyncMethodBuilderAttribute(out methodLevelBuilder); | ||
bool customBuilder; | ||
object builderArgument; | ||
bool customBuilder = returnType.IsCustomTaskType(out builderArgument); | ||
|
||
if (useMethodLevelBuilder) | ||
{ | ||
customBuilder = true; | ||
builderArgument = methodLevelBuilder; | ||
} | ||
else | ||
{ | ||
customBuilder = returnType.IsCustomTaskType(out builderArgument); | ||
} | ||
|
||
if (customBuilder) | ||
{ | ||
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false); | ||
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false, useMethodLevelBuilder); | ||
if ((object)builderType != null) | ||
{ | ||
taskProperty = GetCustomTaskProperty(F, builderType, returnType); | ||
|
@@ -213,13 +225,15 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
customBuilder, | ||
out taskProperty); | ||
} | ||
|
||
if ((object)builderType == null || | ||
(object)createBuilderMethod == null || | ||
(object)taskProperty == null) | ||
{ | ||
collection = default(AsyncMethodBuilderMemberCollection); | ||
collection = default; | ||
return false; | ||
} | ||
|
||
return TryCreate( | ||
F, | ||
customBuilder: customBuilder, | ||
|
@@ -236,7 +250,7 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
collection: out collection); | ||
} | ||
|
||
if (method.IsAsyncReturningGenericTask(F.Compilation)) | ||
if (method.IsAsyncEffectivelyReturningGenericTask(F.Compilation)) | ||
{ | ||
var returnType = (NamedTypeSymbol)method.ReturnType; | ||
var resultType = returnType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Single().Type; | ||
|
@@ -252,12 +266,23 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
NamedTypeSymbol builderType; | ||
MethodSymbol createBuilderMethod = null; | ||
PropertySymbol taskProperty = null; | ||
|
||
bool useMethodLevelBuilder = method.HasAsyncMethodBuilderAttribute(out methodLevelBuilder); | ||
bool customBuilder; | ||
object builderArgument; | ||
bool customBuilder = returnType.IsCustomTaskType(out builderArgument); | ||
|
||
if (useMethodLevelBuilder) | ||
{ | ||
customBuilder = true; | ||
builderArgument = methodLevelBuilder; | ||
} | ||
else | ||
{ | ||
customBuilder = returnType.IsCustomTaskType(out builderArgument); | ||
} | ||
|
||
if (customBuilder) | ||
{ | ||
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true); | ||
builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true, useMethodLevelBuilder); | ||
if ((object)builderType != null) | ||
{ | ||
builderType = builderType.ConstructedFrom.Construct(resultType); | ||
|
@@ -283,13 +308,15 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
customBuilder, | ||
out taskProperty); | ||
} | ||
|
||
if ((object)builderType == null || | ||
(object)taskProperty == null || | ||
(object)createBuilderMethod == null) | ||
{ | ||
collection = default(AsyncMethodBuilderMemberCollection); | ||
collection = default; | ||
return false; | ||
} | ||
|
||
return TryCreate( | ||
F, | ||
customBuilder: customBuilder, | ||
|
@@ -309,14 +336,14 @@ internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, | |
throw ExceptionUtilities.UnexpectedValue(method); | ||
} | ||
|
||
private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F, object builderAttributeArgument, Accessibility desiredAccessibility, bool isGeneric) | ||
private static NamedTypeSymbol ValidateBuilderType(SyntheticBoundNodeFactory F, object builderAttributeArgument, Accessibility desiredAccessibility, bool isGeneric, bool forMethodLevelBuilder = false) | ||
{ | ||
var builderType = builderAttributeArgument as NamedTypeSymbol; | ||
|
||
if ((object)builderType != null && | ||
!builderType.IsErrorType() && | ||
!builderType.IsVoidType() && | ||
builderType.DeclaredAccessibility == desiredAccessibility) | ||
(forMethodLevelBuilder || builderType.DeclaredAccessibility == desiredAccessibility)) | ||
{ | ||
bool isArityOk = isGeneric | ||
? builderType.IsUnboundGenericType && builderType.ContainingType?.IsGenericType != true && builderType.Arity == 1 | ||
|
@@ -376,7 +403,7 @@ private static bool TryCreate( | |
return true; | ||
} | ||
|
||
collection = default(AsyncMethodBuilderMemberCollection); | ||
collection = default; | ||
return false; | ||
} | ||
|
||
|
@@ -448,6 +475,7 @@ private static MethodSymbol GetCustomCreateMethod( | |
method.IsStatic && | ||
method.ParameterCount == 0 && | ||
!method.IsGenericMethod && | ||
method.RefKind == RefKind.None && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this actually just a bug fix? #Resolved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need this change for proper behavior of method-level builders (see test |
||
method.ReturnType.Equals(builderType, TypeCompareKind.AllIgnoreOptions)) | ||
{ | ||
return method; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Changes to this method are covered by
BuilderFactoryOnMethod_OnLambda_NotTaskLikeTypes
. With this change the test doesn't reportERR_AnonymousReturnExpected
norERR_CantConvAsyncAnonFuncReturns
below. #Resolved