-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Handle ref returning receivers in dynamic calls #70676
Conversation
@@ -549,6 +549,9 @@ internal static RefKind GetReceiverRefKind(BoundExpression loweredReceiver) | |||
|
|||
switch (loweredReceiver.Kind) | |||
{ | |||
case BoundKind.Call: |
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.
Are we missing handling for other interesting scenarios? For example, I do not see explicit case for fields. We probably could run into a sequence (for example if we need to reorder arguments for a call), etc.
It looks like the purpose of this method is to determine whether we can take a reference to the receiver without storing the value in a temp. It feels fragile to have a helper that is used only for the purpose of dynamic rewrite, especially taking future language changes into account. Scenarios involving dynamic rewrite are easy to miss during testing. Therefore, I think we should either switch to a different existing helper, which is used more often (Binder.HasHome
?), or we could try always pass value type receiver by reference and let emit layer to figure out if it needs a temp for that (it looks like that shouldn't change semantics of the operation). #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.
Are we missing handling for other interesting scenarios?
Good catch, thanks.
we could try always pass value type receiver by reference and let emit layer to figure out if it needs a temp for that
That seems like it would work except it's hitting the following assert which I'm not sure how to easily change (apart from removing it).
Debug.Assert(argument.Type.IsDynamic(), "passing args byref should not clone them into temps"); |
It would also change IL (introducing temp for rvalue struct receivers), so I'm exploring the first option instead (using Binder.HasHome
).
Done with review pass (commit 1) |
var hasHome = Binder.HasHome(loweredReceiver, | ||
Binder.AddressKind.Writeable, | ||
_factory.CurrentFunction, | ||
_factory.Compilation.IsPeVerifyCompatEnabled, |
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.
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.
Or, at least, with intent.
{ | ||
dynamic d = 1; | ||
GetS().M(d); | ||
System.Console.Write(GetS().X); |
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 (commit 4) |
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 (commit 5)
Fixes #68063.