Skip to content
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

Extensions: account for new extensions in function type scenarios #77755

Merged
merged 2 commits into from
Mar 24, 2025

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Mar 22, 2025

Relates to test plan #76130

@jcouv jcouv added Area-Compilers Feature - Extension Everything The extension everything feature labels Mar 22, 2025
@jcouv jcouv self-assigned this Mar 22, 2025
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Mar 22, 2025
// For lookup APIs in the semantic model, we can return symbols that aren't fully inferred.
// But for function type inference, if the symbol isn't fully inferred with the information we have (the receiver and any explicit type arguments)
// then we won't return it.
internal static Symbol? GetReducedAndFilteredSymbol(this Symbol member, ImmutableArray<TypeWithAnnotations> typeArguments, TypeSymbol receiverType, CSharpCompilation compilation, bool checkFullyInferred)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 This logic is extracted from AddReducedAndFilteredSymbol, but the check for "fully inferred" was added.

if (node.ResultKind == LookupResultKind.Viable)
{
var methods = ArrayBuilder<MethodSymbol>.GetInstance(capacity: node.Methods.Length);
foreach (var memberMethod in node.Methods)
{
switch (node.ReceiverOpt)
{
case BoundTypeOrValueExpression:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Fixed a bug here. The relevant test is FunctionType_ColorColorReceiver_04.

@jcouv jcouv marked this pull request as ready for review March 22, 2025 04:30
@jcouv jcouv requested a review from a team as a code owner March 22, 2025 04:30
@jcouv
Copy link
Member Author

jcouv commented Mar 22, 2025

@AlekseyTs @jjonescz for review. Thanks

}

[Fact]
public void Params_ExtensionScopes_01()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Params_ExtensionScopes_01

Could you remind what is special about params?

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 1)

@jcouv jcouv requested a review from jjonescz March 24, 2025 17:34
}
}

if ((object)constructed == null)
Copy link
Member

@jjonescz jjonescz Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks unnecessary since we return constructed below anyway. #Resolved

Debug.Assert(property.GetIsNewExtensionMember());
var constructedProperty = (PropertySymbol)SourceNamedTypeSymbol.GetCompatibleSubstitutedMember(compilation, property, receiverType)!;

if (constructedProperty is null)
Copy link
Member

@jjonescz jjonescz Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment. #Resolved

if (member is MethodSymbol method)
{
// 1. construct with explicit type arguments if provided
MethodSymbol constructed;
Copy link
Member

@jjonescz jjonescz Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be nullable? We seem to be comparing constructed to null in several places below.

Suggested change
MethodSymbol constructed;
MethodSymbol? constructed;
``` #Resolved

// infer type arguments based off the receiver type if needed, check applicability
Debug.Assert(receiverType is not null);
Debug.Assert(property.GetIsNewExtensionMember());
var constructedProperty = (PropertySymbol)SourceNamedTypeSymbol.GetCompatibleSubstitutedMember(compilation, property, receiverType)!;
Copy link
Member

@jjonescz jjonescz Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we suppress nullability here but compare with null below? #Resolved

else
{
Debug.Assert(method.GetIsNewExtensionMember());
constructed = (MethodSymbol)SourceNamedTypeSymbol.GetCompatibleSubstitutedMember(compilation, constructed, receiverType)!;
Copy link
Member

@jjonescz jjonescz Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be also checking this result for null instead of suppressing nullability? Since we do that below for properties. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Thanks. Added a test that hits that

@jcouv jcouv requested a review from AlekseyTs March 24, 2025 21:11
Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 2)

@jcouv jcouv enabled auto-merge (squash) March 24, 2025 21:19
@jcouv jcouv merged commit 39479f2 into dotnet:features/extensions Mar 24, 2025
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Feature - Extension Everything The extension everything feature untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants