-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
LambdaRewriter should only assign proxies from locals in original frame in EE #19349
Conversation
@dotnet/roslyn-compiler, @tmat, @jinujoseph, @ivanbasov please review. |
variableSlotAllocatorOpt, | ||
diagnosticsThisMethod, | ||
_debugDocumentProvider, | ||
method.GenerateDebugInfo ? importChain : null, |
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.
[](start = 32, length = 4)
nit: Extra indent
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.
Fixed.
// confuse the method body generator by making a fresh bag and then loading | ||
// any diagnostics emitted into it back into the main diagnostic bag. | ||
var diagnosticsThisMethod = DiagnosticBag.GetInstance(); | ||
// We make sure that an asynchronous mutation to the diagnostic bag does not |
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.
// We mak [](start = 20, length = 9)
Is this block just indented?
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.
Yes, the only change is to indenting.
@@ -101,7 +101,7 @@ public MappedLocalFunction(SynthesizedLambdaMethod symbol, ClosureKind closureKi | |||
// True if the rewritten tree should include assignments of the |
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.
True [](start = 11, length = 4)
The comment needs update.
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.
Updated comments.
Update comment Refers to: src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs:210 in 7497a20. [](commit_id = 7497a20ac2756ea95b89cb506e7d60af9cd688fd, deletion_comment = False) |
@@ -101,7 +101,7 @@ public MappedLocalFunction(SynthesizedLambdaMethod symbol, ClosureKind closureKi | |||
// True if the rewritten tree should include assignments of the | |||
// original locals to the lifted proxies. This is only useful for the | |||
// expression evaluator where the original locals are left as is. | |||
private readonly bool _assignLocals; | |||
private readonly HashSet<LocalSymbol> _assignLocals; |
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.
_assignLocals [](start = 46, length = 13)
If this is null then all locals are assigned, otherwise only those that are in this set?
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.
If null
, no locals are assigned. The use was incorrect. Fixed.
{ | ||
localsBuilder.Add(local); | ||
localsSet.Add(local); | ||
} |
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.
Can be simplified:
if (localsSet.Add(local))
{
localsBuilder.Add(local)
}
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.
@dotnet/roslyn-compiler, @tmat, please review. |
@@ -830,6 +830,50 @@ End Class | |||
End Sub | |||
|
|||
<Fact> | |||
Public Sub CapturedLocalInNestedLocalFunction() |
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.
LocalFunction [](start = 40, length = 13)
Lambda? VB doesn't support local functions.
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.
Fixed.
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
@dotnet/roslyn-compiler for a second review, thanks. |
@dotnet/roslyn-compiler for a second review for a small change to the compiler. @MattGertz for approval since this is an EE fix. |
@dotnet-bot retest this please |
@dotnet/roslyn-compiler please provide a second review for 15.3. Thanks. |
@dotnet-bot test windows_release_vs-integration_prtest please |
📝 Notes from discussion with Chuck: But in the case of nested lambdas, it is possible to introduce a closure with a field which should not be initialized this way, because it does not exist in the original method. The EE already keeps track of all the variables in scope (including locals from source that were compiled/lifted into a closure and don't exist as locals in the IL), so we can use this information to decide which variables need this initialization and which do not. That's the fix in this PR :-) |
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 for the background explanation.
Customer scenario
Evaluate expression containing nested lambdas where the inner lambda closes over a local in outer lambda.
Bugs this fixes:
#18273
Workarounds, if any
Avoid evaluating such expressions
Risk
Low
Performance impact
Low
Is this a regression from a previous update?
Probably not a regression. Unit test included.