-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Emit extension implementation methods #77197
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
Emit extension implementation methods #77197
Conversation
| { | ||
| if (method is { IsStatic: false, ContainingType: SourceNamedTypeSymbol { IsExtension: true, ExtensionParameter: { } parameter } }) | ||
| { | ||
| return new WithParametersBinder([parameter], resultBinder); |
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.
Should the doc comment of WithParametersBinder be updated to mention this scenario?
/// <summary>
/// Binder used to place the parameters of a method, property, indexer, or delegate
/// in scope when binding <param> tags inside of XML documentation comments
/// and `nameof` in certain attribute positions.
/// </summary>
``` #ResolvedThere 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.
Should the doc comment of
WithParametersBinderbe updated to mention this scenario?
Mentioned this in a PROTOTYPE comment
| method = method ?? GetMethodSymbol(methodDecl, resultBinder); | ||
| isIteratorBody = method.IsIterator; | ||
| resultBinder = WithExtensionReceiverParameterBinderIfNecessary(resultBinder, method); | ||
| resultBinder = new InMethodBinder(method, resultBinder); |
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.
Wouldn't it be better to update InMethodBinder to handle extension receiver? #Resolved
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.
Wouldn't it be better to update InMethodBinder to handle extension receiver?
It depends. For example, whether we consider method parameters and receiver parameters in the same scope and what are the shadowing rules might affect the decision. My goal in this PR is to quickly enable test scenarios for implementation methods. I'll add a prototype comment.
|
|
||
| bool haveExtraParameter = sourceMethod.ParameterCount != implementationMethod.ParameterCount; | ||
| if (haveExtraParameter) | ||
| { |
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.
Consider asserting that implementationMethod.ParameterCount - 1 == sourceMethod.ParameterCount #Resolved
|
This PR modifies public API files. Please follow the instructions at https://github.com/dotnet/roslyn/blob/main/docs/contributing/API%20Review%20Process.md for ensuring all public APIs are reviewed before merging. |
26ae105 to
d358e8f
Compare
|
I had to rebase because, for some reason, GitHub was including all commits from #77216 into this PR as well (despite the fact that that PR was already merged). Sorry for any inconvenience that that might cause. #Closed |
| AddSynthesizedTypeMembersIfNecessary(builder, declaredMembersAndInitializers, diagnostics); | ||
| AddSynthesizedConstructorsIfNecessary(builder, declaredMembersAndInitializers, diagnostics); | ||
|
|
||
| if (TypeKind == TypeKind.Class) |
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.
nit: consider tightening this check to only top-level non-generic static classes #Closed
| public override MethodKind MethodKind => MethodKind.Ordinary; | ||
| public override bool IsImplicitlyDeclared => true; | ||
|
|
||
| internal override bool HasSpecialName => true; |
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.
Did we have a motivating scenario for this? I thought we wanted to hold off on marking as special name until a scenario was identified #Closed
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.
We are generating a special name for this method, that is enough motivation in my mind (like we do for property accessors an the like). The flag doesn't cause any harm to anyone, but it can be used to quickly filter methods in metadata.
| get | ||
| { | ||
| return _originalMethod.ParameterCount + | ||
| (_originalMethod.IsStatic || _originalMethod.ContainingType is not SourceNamedTypeSymbol { ExtensionParameter: { } } ? 0 : 1); |
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.
Would it be better to not create an implementation method in the first place when the ExtensionParameter is faulty? #Closed
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.
I do not know. So far that didn't cause an problems.
| return localFunctions.SelectAsArray(static (l, map) => (MethodSymbol)map[l], _symbolMap); | ||
| } | ||
|
|
||
| [return: NotNullIfNotNull("symbol")] |
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.
I don't mind this approach, but consider moving this to Refers to: src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs:2989 in d358e8f. [](commit_id = d358e8f, deletion_comment = False) |
I do not want to be required to provide a base line with specific references. For example, I might use base line from core CLR run, then the helper wouldn't work In reply to: 2660273404 Refers to: src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs:2989 in d358e8f. [](commit_id = d358e8f, deletion_comment = False) |
| { | ||
| ILBuilder builder = new ILBuilder(_moduleBeingBuiltOpt, new LocalSlotManager(slotAllocator: null), OptimizationLevel.Release, areLocalsZeroed: false); | ||
|
|
||
| // throw null; |
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.
nit: consider expanding the comment to provide more context "// Emit methods in extensions as skeletons:" #Closed
|
|
||
| internal sealed override bool HasAsyncMethodBuilderAttribute(out TypeSymbol? builderArgument) | ||
| { | ||
| // PROTOTYPE(roles): Test this code path |
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.
jcouv
left a comment
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.
Done with review pass (iteration 3)
It is my intent to use a name in these tests. In reply to: 2660289257 Refers to: src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs:4547 in d358e8f. [](commit_id = d358e8f, deletion_comment = False) |
We don't have to and I intend to port end-to-end tests from roles branch. I think they will cover execution of interesting scenarios In reply to: 2660301916 Refers to: src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs:4735 in d358e8f. [](commit_id = d358e8f, deletion_comment = False) |
jcouv
left a comment
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.
LGTM Thanks (iteration 4)
Relates to test plan #76130