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

Handle deconstruct pattern in ref safety analysis #75511

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

jjonescz
Copy link
Member

Fixes #75484.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Oct 15, 2024
@jjonescz jjonescz marked this pull request as ready for review October 17, 2024 14:09
@jjonescz jjonescz requested a review from a team as a code owner October 17, 2024 14:09
@jjonescz
Copy link
Member Author

@dotnet/roslyn-compiler for reviews, thanks

@jaredpar
Copy link
Member

@jcouv, @cston PTAL

// (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));
}
Copy link
Member

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

jcouv
jcouv previously approved these changes Nov 1, 2024
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 1)

@jcouv
Copy link
Member

jcouv commented Nov 1, 2024

@cston for second review. Thanks

var placeholder = new BoundDeconstructValuePlaceholder(
x.Syntax,
variableSymbol: null,
isDiscardExpression: true,
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Member Author

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 vars to have val escape scope of _localScopeDepth. Per ref safety rules of Deconstruct(out var ...) like calls, ref-struct out vars should have that scope only if the receiver is unscoped. So I added a condition to that effect.

@jjonescz jjonescz marked this pull request as draft November 4, 2024 11:44
@jjonescz jjonescz dismissed jcouv’s stale review November 4, 2024 14:57

Reworked the implementation

@jjonescz jjonescz marked this pull request as ready for review November 4, 2024 16:42
@jjonescz
Copy link
Member Author

jjonescz commented Nov 8, 2024

@jcouv @RikkiGibson for another look, thanks

{
R M()
{
(var x, _) = new S();
Copy link
Contributor

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.

Copy link
Member Author

@jjonescz jjonescz Nov 11, 2024

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.

@jjonescz
Copy link
Member Author

@dotnet/roslyn-compiler for reviews, thanks

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
5 participants