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

VB: Do not use overload resolution for expression tree conversion #75490

Merged
merged 3 commits into from
Oct 18, 2024

Conversation

AlekseyTs
Copy link
Contributor

Related to #74275.

@AlekseyTs AlekseyTs requested a review from a team as a code owner October 11, 2024 21:50
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Oct 11, 2024
@@ -32,7 +22,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
BinaryOperatorKind.Divide,
BinaryOperatorKind.Modulo,
BinaryOperatorKind.IntegerDivide,
BinaryOperatorKind.Concatenate,
Copy link
Member

@jcouv jcouv Oct 14, 2024

Choose a reason for hiding this comment

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

nit: If it's the same situation as the Like, consider moving this case below and adding to the comment (line 44) #Resolved

@AlekseyTs
Copy link
Contributor Author

@dotnet/roslyn-compiler Please review.

End Function

' Emit a Default node for a specific type
Private Function [Default](type As TypeSymbol) As BoundExpression
Return ConvertRuntimeHelperToExpressionTree("Default", _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))
Return _factory.Convert(
Copy link
Member

@jcouv jcouv Oct 14, 2024

Choose a reason for hiding this comment

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

Could you provide some context on why some calls to ConvertRuntimeHelperToExpressionTree are now wrapped in a Convert but not all? #Closed

Copy link
Contributor Author

@AlekseyTs AlekseyTs Oct 14, 2024

Choose a reason for hiding this comment

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

Could you provide some context on why some calls to ConvertRuntimeHelperToExpressionTree are now wrapped in a Convert but not all?

Normally, Visit does this conversion. However, we are not getting here due to a Visit invocation and this conversion was applied during overload resolution, which we no longer perform. Therefore, the conversion is applied explicitly because types should match exactly.

Copy link
Member

Choose a reason for hiding this comment

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

From offline discussion, ConvertRuntimeHelperToExpressionTree that are returned from a Visit... method are already converted, we only need to apply the conversion explicitly for helper/factory methods.
FWIW, I didn't observe any break in CodeGenExprLambda.vb (on either net472 or net9.0) or in Build.cmd -testCompilerOnly -test when removing Convert in Default or New.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed this conversion, apparently changes elsewhere made it unnecessary

Return ConvertRuntimeHelperToExpressionTree("Call", factoryArgs)
Return _factory.Convert(
_expressionType,
ConvertRuntimeHelperToExpressionTree(
Copy link
Member

@jcouv jcouv Oct 14, 2024

Choose a reason for hiding this comment

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

nit: The indentation is off (two arguments should be on same level like below) #Resolved

End Function

Private Function InitWithParameterlessValueTypeConstructor(type As TypeSymbol) As BoundExpression
' The "New" overload without a methodInfo automatically generates the parameterless constructor for us.
Debug.Assert(type.IsValueType)
Return ConvertRuntimeHelperToExpressionTree("New", _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))
Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_Type, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))
Copy link
Member

@jcouv jcouv Oct 14, 2024

Choose a reason for hiding this comment

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

It is surprising that we don't need Convert here since InitWithParameterlessValueTypeConstructor and [Default] are used in the same place in the same way. #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is surprising that we don't need Convert here since InitWithParameterlessValueTypeConstructor and [Default] are used in the same place in the same way.

I was adding conversions on as needed basis, when tests were failing. I also wasn't changing all ConvertRuntimeHelperToExpressionTree calls at the same time, so the conversions were necessary to pass tests at some point. It looks like the need to add conversions for some call sites got eliminated when all call sites were adjusted. I removed those. Thanks.

Copy link
Member

@jcouv jcouv left a 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 1)

@jcouv jcouv self-assigned this Oct 14, 2024
@AlekseyTs
Copy link
Contributor Author

@dotnet/roslyn-compiler For the second review

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM Thanks (iteration 3)

@AlekseyTs
Copy link
Contributor Author

@dotnet/roslyn-compiler For the second review

2 similar comments
@AlekseyTs
Copy link
Contributor Author

@dotnet/roslyn-compiler For the second review

@AlekseyTs
Copy link
Contributor Author

@dotnet/roslyn-compiler For the second review

ElseIf opKind = BinaryOperatorKind.Concatenate Then
helper = DirectCast(_factory.SpecialMember(SpecialMember.System_String__ConcatStringString), MethodSymbol)

If helper Is Nothing Then ' Don't know how to do 'BinaryOperatorKind.Power' without the method
Copy link
Member

@jjonescz jjonescz Oct 18, 2024

Choose a reason for hiding this comment

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

' Don't know how to do 'BinaryOperatorKind.Power' without the method

This comment and the one above look inaccurate. We might not be doing 'Power' operation. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This comment and the one above look inaccurate. We might not be doing 'Power' operation.

I think the comment accurately reflects the motivation for adding the check. It is an error to fail to find the helper for any operator. The question is what the rewriter should do to recover. The error has been reported, but the rewriter needs to produce a bound node to return. It used to be that the rewriter would continue as though the helper is not needed and would produce a node of that shape, there are expression tree factories to do that (despite the fact that that wouldn't accurately reflect semantics of the operator). In order to maintain that recovery strategy, we would have to make use of a "Power" factory method that is never used in a success scenario, which, in my opinion, would lead to a confusion of anyone who would want to figure out what is a minimal set of factories required by VB. The new error recovery approach is going to work well for all operators, but the primary motivation is to exclude usage of a "Power" factory method that would never be needed in a success scenario.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers 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.

4 participants