-
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
Share pattern-matching temps when they are the same type. #19378
Conversation
LocalSymbol temp; | ||
if (!localByType.TryGetValue(type, out temp)) | ||
{ | ||
temp = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatching, Syntax); |
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.
_enclosingSymbol as MethodSymbol [](start = 44, length = 32)
Can this be null? If not use explicit cast.
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 parameter is "optional" in the constructor.
While it would be possible to change this to a cast now, that would be an error when we introduce a match expression, because in that case the enclosing symbol could be a field (for a field initializer). I'd rather leave this as is so it is future-proof.
@@ -101,6 +101,7 @@ internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabel | |||
/// the decision tree. | |||
/// </summary> | |||
private ImmutableArray<BoundPatternSwitchSection> BindPatternSwitchSections( | |||
SyntaxNode syntax, |
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.
SyntaxNode syntax [](start = 12, length = 17)
It looks like there is only one call-site. Consider making this a SwitchStatementSyntax and removing the two next parameters (boundSwitchExpression is coming from a property, sections are available from SwitchStatementSyntax). #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.
Yes; even this syntax
parameter is unneeded (it is available in the property SwitchSyntax
).
@@ -26,17 +26,63 @@ internal abstract class DecisionTreeBuilder | |||
protected readonly Symbol _enclosingSymbol; | |||
protected readonly Conversions _conversions; | |||
protected HashSet<DiagnosticInfo> _useSiteDiagnostics = new HashSet<DiagnosticInfo>(); | |||
private Dictionary<TypeSymbol, LocalSymbol> localByType = new Dictionary<TypeSymbol, LocalSymbol>(); |
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.
new Dictionary<TypeSymbol, LocalSymbol>(); [](start = 66, length = 42)
Should this dictionary be sensitive to dynamic/object, tuple names and custom modifier differences?
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.
No, it definitely should 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.
No, it definitely should not.
Please add a test targeting this scenario.
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.
Added TestIgnoreDynamicVsObjectAndTupleElementNames_03
.
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.
My "No" above should be "Yes".
@@ -59,15 +59,9 @@ private BoundStatement MakeLoweredForm(BoundPatternSwitchStatement node) | |||
var expression = _localRewriter.VisitExpression(node.Expression); | |||
var result = ArrayBuilder<BoundStatement>.GetInstance(); | |||
|
|||
// if the expression is "too complex", we copy it to a temp. |
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 the expression is "too complex", we copy it to a temp. [](start = 16, length = 60)
Could you please explain why this is no longer needed?
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.
Lowering starts by lowering to a decision tree, which starts by calling CreateEmptyDecisionTree
, which contains code equivalent to this deleted code. The existing generated code always contained two temps instead of one.
/// <summary>
/// Create a fresh decision tree for the given input expression of the given type.
/// </summary>
protected DecisionTree CreateEmptyDecisionTree(BoundExpression expression)
{
var type = expression.Type;
LocalSymbol temp = null;
if (expression.ConstantValue == null)
{
// Unless it is a constant, the decision tree acts on a copy of the input expression.
// We create a temp to represent that copy. Lowering will assign into this temp.
temp = PatternMatchingTemp(type);
expression = new BoundLocal(expression.Syntax, temp, null, type);
}
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 for the explanation.
Done with review pass. |
Fix some additional affected tests.
…ic are not merged.
@AlekseyTs The PR has been modified to respond to your comments. |
@@ -115,11 +113,11 @@ internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabel | |||
|
|||
// Bind match sections | |||
var boundPatternSwitchSectionsBuilder = ArrayBuilder<BoundPatternSwitchSection>.GetInstance(); | |||
SubsumptionDiagnosticBuilder subsumption = new SubsumptionDiagnosticBuilder(ContainingMemberOrLambda, this.Conversions, boundSwitchExpression); | |||
foreach (var sectionSyntax in sections) | |||
SubsumptionDiagnosticBuilder subsumption = new SubsumptionDiagnosticBuilder(base.ContainingMemberOrLambda, SwitchSyntax, this.Conversions, SwitchGoverningExpression); |
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.
base. [](start = 88, length = 5)
Does the base.
make a difference?
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.
No.
} | ||
|
||
[Fact, WorkItem(19280, "https://github.com/dotnet/roslyn/issues/19280")] | ||
public void TestIgnoreDynamicVsObjectAndTupleElementNames_03() |
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.
TestIgnoreDynamicVsObjectAndTupleElementNames_03 [](start = 20, length = 48)
I am confused, the name of the test says "Ignore", but it looks like the differences aren't ignored.
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'll rename it TestSignificanceOfDynamicVersusObjectAndTupleNamesInUniquenessOfPatternMatchingTemps
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 May I please have a second review from the compiler team? |
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
/CC @MeiChin-Tsai for ask mode approval, please |
Approved. thx. |
Customer scenario
Use edit-and-continue in a method that contains a pattern-switch statement. It doesn't work today, but we'd like to enable it. This work is a first step in making that happen.
Bugs this fixes:
Fixes #19280
Workarounds, if any
None.
Risk
Quite low. We simply reuse temporary variables when they are used in non-overlapping ranges.
Performance impact
No compiler perf change expected. Slight improvement to code quality.
Is this a regression from a previous update?
N/A
Root cause analysis:
N/A
How was the bug found?
N/A
@dotnet/roslyn-compiler @tmat Please review this compiler fix. It is a prerequisite to E&C work we hope to get into 15.3.