-
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 deconstruct pattern in ref safety analysis #75511
base: main
Are you sure you want to change the base?
Conversation
cd7baee
to
769f731
Compare
@dotnet/roslyn-compiler for reviews, thanks |
// (13,20): error CS8352: Cannot use variable 'x2' in this context because it may expose referenced variables outside of their declaration scope | ||
// return x2; | ||
Diagnostic(ErrorCode.ERR_EscapeVariable, "x2").WithArguments("x2").WithLocation(13, 20)); | ||
} |
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.
nit: Consider also testing a nested deconstruction scenario: ((var x, var y), var z)
. I expect it should just fall out by composition
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 Thanks (iteration 1)
@cston for second review. Thanks |
var placeholder = new BoundDeconstructValuePlaceholder( | ||
x.Syntax, | ||
variableSymbol: null, | ||
isDiscardExpression: true, |
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.
I didn't understand why we should pass 'isDiscardExpression: true' here.
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.
Originally this code path was written to handle discards in the pattern which correspond to out _
discard arguments of the equivalent Deconstruct
call.
But now I realize there can be also nested subpatterns and we need to be smarter about extracting all variable accesses from that.
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.
I think MAMM should not have an effect on the underlying Deconstruct calls of patterns. So I have removed the code which was trying to check invocation ref safety of an equivalent Deconstruct
call (it wouldn't be so easy to do because one argument to the call could correspond to multiple variables in case of binary patterns).
I also added more tests where the Deconstruct
method used by the pattern has the receiver scoped. Turned out that didn't work - the using (new PatternInput(this, _localScopeDepth))
caused all the pattern ref-struct var
s to have val escape scope of _localScopeDepth
. Per ref safety rules of Deconstruct(out var ...)
like calls, ref-struct out var
s should have that scope only if the receiver is unscoped. So I added a condition to that effect.
@jcouv @RikkiGibson for another look, thanks |
{ | ||
R M() | ||
{ | ||
(var x, _) = new S(); |
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.
It feels like we should also have tests where the Deconstruct receiver is something we can return a reference to. For example, if it is a by-ref parameter.
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.
Thanks, that actually doesn't work as expected for normal deconstruction (as opposed to a pattern matching one) which seems like an orthogonal issue (this PR fixes deconstruction in pattern matching). Filed #75850.
@dotnet/roslyn-compiler for reviews, thanks |
Fixes #75484.