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

Adjust semantic model for method group conversion #75719

Merged
merged 4 commits into from
Nov 11, 2024

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Nov 4, 2024

Fixes #36377

In the scenario, we have a user-defined conversion for cast, stacked with a method group conversion.

@jcouv jcouv self-assigned this Nov 4, 2024
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Nov 4, 2024
@jcouv jcouv force-pushed the method-conversion branch 4 times, most recently from 146f4ac to 4edb67b Compare November 6, 2024 20:45
@jcouv jcouv marked this pull request as ready for review November 7, 2024 19:49
@jcouv jcouv requested a review from a team as a code owner November 7, 2024 19:49
@@ -4294,6 +4294,12 @@ private OneOrMany<Symbol> GetMethodGroupSemanticSymbols(
// we want to get the symbol that overload resolution chose for M, not the whole method group M.
var conversion = (BoundConversion)boundNodeForSyntacticParent;

if (conversion.ConversionKind is not ConversionKind.MethodGroup && conversion.Operand is BoundConversion nestedConversion)
Copy link
Member

@333fred 333fred Nov 7, 2024

Choose a reason for hiding this comment

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

Nit:

Suggested change
if (conversion.ConversionKind is not ConversionKind.MethodGroup && conversion.Operand is BoundConversion nestedConversion)
if (conversion is { ConversionKind: not ConversionKind.MethodGroup, Operand: BoundConversion nestedConversion })
``` #Resolved

@AlekseyTs
Copy link
Contributor

@jcouv Was this a regression?

@@ -425,6 +426,112 @@ static void Main()
Assert.True(conversion.IsNumeric);
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36377")]
public void GetSymbolInfo_ExplicitCastOnMethodGroup()
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

Consider adding a similar test for VB #Closed


public static int Test() => 1;

public static explicit operator C(System.Func<int> intDelegate)
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

explicit

Consider testing with implicit operator, including a scenario when the cast operator, (C), is not present in code. #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.

Done. There are some existing unexpected behaviors there. Filing issues for those

@@ -4294,6 +4294,12 @@ private OneOrMany<Symbol> GetMethodGroupSemanticSymbols(
// we want to get the symbol that overload resolution chose for M, not the whole method group M.
var conversion = (BoundConversion)boundNodeForSyntacticParent;

if (conversion.ConversionKind is not ConversionKind.MethodGroup && conversion.Operand is BoundConversion nestedConversion)
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

nestedConversion

It feels like we should also check how this node related to the conversion syntactically #Closed

@@ -4294,6 +4294,12 @@ private OneOrMany<Symbol> GetMethodGroupSemanticSymbols(
// we want to get the symbol that overload resolution chose for M, not the whole method group M.
var conversion = (BoundConversion)boundNodeForSyntacticParent;

if (conversion.ConversionKind is not ConversionKind.MethodGroup && conversion.Operand is BoundConversion nestedConversion)
{
Debug.Assert(conversion.ConversionKind is ConversionKind.NoConversion || conversion.ExplicitCastInCode);
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

Debug.Assert(conversion.ConversionKind is ConversionKind.NoConversion || conversion.ExplicitCastInCode);

It is not obvious why is it reasonable to make this assumption. And more importantly why do we need to make it. If we are going after a specific bound tree shape, I think we should be checking for that instead. For example, we might want to confirm that the nested conversion is the immediate conversion for the BoundMethodGroup boundNode. If that is not the case, switching the conversion node doesn't feel appropriate. #Closed

if (conversion.ConversionKind is not ConversionKind.MethodGroup && conversion.Operand is BoundConversion nestedConversion)
{
Debug.Assert(conversion.ConversionKind is ConversionKind.NoConversion || conversion.ExplicitCastInCode);
conversion = nestedConversion;
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

conversion = nestedConversion;

Consider adding a comment about why/when we need to do this transformation. #Closed

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 1)

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Nov 8, 2024

                        Debug.Assert(conversion.ConversionKind == ConversionKind.MethodGroup);

Perhaps this should be converted into a real check? Basically, we are interested in a method group conversion and we should check for that rather than assume that this is what we have. #Closed


Refers to: src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs:4306 in 03f70f7. [](commit_id = 03f70f7, deletion_comment = False)

@jcouv
Copy link
Member Author

jcouv commented Nov 8, 2024

@jcouv Was this a regression?

Nothing indicates that in the linked issue (filed in 2019).

var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var memberAccess = GetSyntax<MemberAccessExpressionSyntax>(tree, "C.Test");
Assert.Equal("C C.op_Implicit(System.Func<System.Int32> intDelegate)", model.GetSymbolInfo(memberAccess).Symbol.ToTestDisplayString()); // Unexpected: Should be "void C.Test()"
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

// Unexpected: Should be "void C.Test()"

Are we planning to address this? #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.

Opened #75833

Dim x As C = DirectCast(AddressOf C.Test, C)
~~~~~~~~~~~~~~~~
</expected>)
End Sub
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 8, 2024

Choose a reason for hiding this comment

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

End Sub

It doesn't look like we are testing SemanticModel behavior #Closed

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 2)

@jcouv jcouv requested a review from 333fred November 8, 2024 20:18
@jaredpar jaredpar removed the untriaged Issues and PRs which have not yet been triaged by a lead label Nov 11, 2024
@jcouv jcouv requested a review from AlekseyTs November 11, 2024 17:01
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 jcouv merged commit 32f7283 into dotnet:main Nov 11, 2024
24 checks passed
@jcouv jcouv deleted the method-conversion branch November 11, 2024 22:30
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Nov 11, 2024
@jjonescz jjonescz modified the milestones: Next, 17.13 P2 Nov 25, 2024
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.

Go To Definition does not work correctly with delegate and operator
5 participants