Skip to content

Analyze flow in receiver of extension method group in delegate creation #60093

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

Merged
merged 4 commits into from
Mar 16, 2022

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Mar 10, 2022

Fixes #59738 again

This is PR #59874, but with an extra commit to ignore the implicit this receiver on a static method.
Adjusting the initial binding to remove that receiver seems desirable but riskier, so I'm sticking with a local fix. See #56395 for a similar situation.

@jcouv jcouv force-pushed the definite-assignment branch from eca246b to c159d78 Compare March 10, 2022 22:14
@jcouv jcouv marked this pull request as ready for review March 11, 2022 08:35
@jcouv jcouv requested a review from a team as a code owner March 11, 2022 08:35
@RikkiGibson RikkiGibson self-assigned this Mar 11, 2022
{
VisitLocalFunctionUse(localFunc, node.Syntax, isCall: false);
}
else if (node.MethodOpt is { } method && methodGroup.ReceiverOpt is { } receiver && !ignoreReceiver(receiver, method))
{
EnterRegionIfNeeded(methodGroup);
VisitRvalue(methodGroup.ReceiverOpt);
Copy link
Contributor

@bernd5 bernd5 Mar 12, 2022

Choose a reason for hiding this comment

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

I would use the local receiver here #Closed

static bool ignoreReceiver(BoundExpression receiver, MethodSymbol method)
{
// ignore the implicit `this` receiver on a static method
return method.IsStatic && receiver is { Kind: BoundKind.ThisReference, WasCompilerGenerated: true };
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we should add a comment here:
we may need to visit the receiver / can't ignore static methods at all because of extension methods.

static bool ignoreReceiver(BoundExpression receiver, MethodSymbol method)
{
// ignore the implicit `this` receiver on a static method
return method.IsStatic && receiver is { Kind: BoundKind.ThisReference, WasCompilerGenerated: true };
Copy link
Contributor

@AlekseyTs AlekseyTs Mar 14, 2022

Choose a reason for hiding this comment

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

Kind: BoundKind.ThisReference, WasCompilerGenerated: true }

I think we can have this as a receiver for a legitimate extension method reference. We have a special property IsExtensionMethod clearly identifying extension methods. Consider using it instead and, if it is not set, ignoring receivers for a static method. #Closed

Copy link
Member Author

Choose a reason for hiding this comment

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

The reason I used this logic was to align with a previous PR that skips such implicit this receivers on static methods: #56395

Just to clarify, I think you're proposing return method.IsStatic && !method.IsExtensionMethod;.
I'd be fine with that. @333fred, any concern?

Copy link
Member

Choose a reason for hiding this comment

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

That might be too broad. AnalyzeDataFlow should still see the invalid receiver as being read for extract method to work as intended.

Copy link
Contributor

Choose a reason for hiding this comment

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

AnalyzeDataFlow should still see the invalid receiver as being read for extract method to work as intended.

I am not sure if I agree with that. Clearly, the receiver for static methods (excluding extension scenario) is not going to be evaluated, so I think we have a flexibility in terms of how flow analysis should work in the error scenario.
The current implementation is incorrect in my opinion. Primarily because the PR description provides no clarity about what is our philosophy around visiting and not visiting receivers. Also, it is not clear to me why do we want to handle receivers differently by comparison to BoundCall. Perhaps the behavior is the same, but it is not obvious from the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

In general, I do not see us actually making sure that region analysis will work for any misplaced expression. For example, there are BoundLocalDeclaration.ArgumentsOpt and it looks like flow analysis never visits them. Therefore, it is not clear to me why we should visit erroneous (misplaced) receiver. BTW, the issue that we are trying to fix is about failure for a valid scenario.

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 3)

@jcouv jcouv requested a review from AlekseyTs March 16, 2022 01:23
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 4)

@jcouv
Copy link
Member Author

jcouv commented Mar 16, 2022

@dotnet/roslyn-compiler for second review. Thanks

@jcouv jcouv enabled auto-merge (squash) March 16, 2022 18:19
@jcouv jcouv merged commit 4ca0b15 into dotnet:main Mar 16, 2022
@ghost ghost added this to the Next milestone Mar 16, 2022
@@ -1533,8 +1533,8 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE

static bool ignoreReceiver(BoundExpression receiver, MethodSymbol method)
{
// ignore the implicit `this` receiver on a static method
return method.IsStatic && receiver is { Kind: BoundKind.ThisReference, WasCompilerGenerated: true };
// static methods that aren't extensions get an implicit `this` receiver that should be ignored
Copy link
Member

Choose a reason for hiding this comment

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

Do we have a test for an extension method called in non-reduced form? It may not be very meaningful since I think this would either have no receiver or have a type expression as a receiver, but thought I would check anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

the static method itself doesn't get an implicit receiver - but the methodgroup...

@allisonchou allisonchou modified the milestones: Next, 17.2.P3 Mar 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AnalyzeDataFlow fails
6 participants