-
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
[semi-auto-props]: Add more tests (GetMembers, speculative semantic model) #59270
[semi-auto-props]: Add more tests (GetMembers, speculative semantic model) #59270
Conversation
Assert.Empty(comp.GetTypeByMetadataName("C").GetFieldsToEmit()); | ||
|
||
var fieldKeywordTypeInfo = speculativeModel.GetTypeInfo(identifier); | ||
Assert.Equal(SpecialType.System_Int32, fieldKeywordTypeInfo.Type.SpecialType); |
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 you please verify if this is expected to work? Currently it doesn't work because (as far as I understand), before speculation, we already marked the backing field as computed.
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 you please verify if this is expected to work?
Define "to work".
We are in the investigation territory here. Reviewers should be able to see the current behavior. Meaning, the tests should pass, they should reflect the current behavior. Then we can examine if the behavior matches our expectations.
model.TryGetSpeculativeSemanticModel(token.SpanStart, identifier, out var speculativeModel); | ||
var fieldKeywordTypeInfo = speculativeModel.GetTypeInfo(identifier); | ||
|
||
Assert.Empty(comp.GetTypeByMetadataName("C").GetFieldsToEmit()); |
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.
This assertion fails. What I was trying to do in this test is to not cause binding to the original compilation so that the sentinel value remains, then I only bind the speculated node. This caused the property to have a backing field, which GetFieldsToEmit
will return. @AlekseyTs Any pointers as to what I need to do, for both this test and the previous one?
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.
Any pointers as to what I need to do, for both this test and the previous one?
I agree that the behavior doesn't feel right. But before doing anything to fix it, let's add more tests to better understand the set of scenarios we should handle.
Note, the tests should pass, asserts should reflect the current behavior. Otherwise, reviewers cannot "see" the current behavior. If some behavior feels unexpected to you, add a comment.
Here are additional tests that I suggest:
- Speculate with a field identifier within a an accessor that uses the field keyword.
- Speculate with a field identifier within a an accessor that doesn't use the field keyword, but there is another accessor that uses the keyword.
- Speculate in a duplicate accessor (in the second getter, for example). Both when the first accessor uses and doesn't use the field keyword.
Once we have these tests, I might suggest more scenarios to try.
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.
@AlekseyTs For each of those scenarios, do you want two tests?
- Bind original tree first
- Bind speculated tree first
as I demonstrated in #59270 (comment)
If not, which scenario of the two is the interesting one?
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.
For each of those scenarios, do you want two tests?
Yes, let's have two a pair of tests per scenario.
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
Done with review pass (commit 3) |
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
Done with review pass (commit 4) |
@AlekseyTs I added more tests. This is ready for another look. |
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
I didn't have a chance to complete review of changes made post commit 5. We might want to add tests for more scenarios. Once we'll have the tests in place, we will have to decide what exact behavior do we want and adjust implementation accordingly. In reply to: 1039641573 |
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Outdated
Show resolved
Hide resolved
src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs
Show resolved
Hide resolved
src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CompilationContext.cs
Outdated
Show resolved
Hide resolved
src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs
Show resolved
Hide resolved
src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CompilationContext.cs
Outdated
Show resolved
Hide resolved
Done with review pass (commit 10) |
Done with review pass (commit 11). I didn't see any response to #59270 (comment). |
Sorry for missing this comment. It's partially addressed with a question regarding expression evaluator tests. |
// public int P { get { int field = field; return field; } } | ||
Diagnostic(ErrorCode.ERR_UseDefViolation, "field").WithArguments("field").WithLocation(4, 38) | ||
); | ||
Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); |
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.
{ | ||
Assert.Equal("System.Int32 field", fieldKeywordSymbolInfo.Symbol.GetSymbol().ToTestDisplayString()); | ||
Assert.Equal(SymbolKind.Local, fieldKeywordSymbolInfo.Symbol.Kind); | ||
Assert.Equal(2, accessorBindingData.NumberOfPerformedAccessorBinding); |
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.
[InlineData("get { return field; } get => 0;")] | ||
[InlineData("get { return 0; } get { return field; }")] | ||
[InlineData("get { return field; } get { return 0; }")] | ||
[InlineData("get { return field; } get { int field = 0; return field; }")] |
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.
[InlineData("get { return 0; } get { return 1; }", 27, 0, false)] | ||
[InlineData("get { return 0; } get { return 1; }", 27, 1, false)] | ||
[InlineData("get { double field = 0; return field; } get { return 1; }", 49, 0, true)] | ||
[InlineData("get { double field = 0; return field; } get { return 1; }", 49, 1, false)] |
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 had an internal discussion about expected behavior for speculative binding. We settled on: "field
in the speculative model does not bind to a backing field if the original location was not a semi-auto property." This is captured as a check box in #57012. It might be worth adding a PROTOTYPE comment here because the behavior doesn't match the expectation. #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.
"
field
in the speculative model does not bind to a backing field if the original location was not a semi-auto property."
@AlekseyTs In case the speculated tree was bound first, we don't yet know if the original is semi-auto property or not. What should we do in that case?
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 might be worth adding a PROTOTYPE comment here because the behavior doesn't match the expectation.
@AlekseyTs Taking a look at this specific test again, it seems that we already don't bind to a backing field (Assert.Null(fieldKeywordSymbolInfo.Symbol);
). Was your comment intended for another test? Am I missing something?
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.
Taking a look at this specific test again, it seems that we already don't bind to a backing field (
Assert.Null(fieldKeywordSymbolInfo.Symbol);
). Was your comment intended for another test? Am I missing something?
I probably misinterpreted the meaning of the speculatingProducesLocal
parameter. Assumed that false
means field rather than "not found".
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.
In case the speculated tree was bound first, we don't yet know if the original is semi-auto property or not. What should we do in that case?
One way or the other we probably need to figure out if the original property is a semi-auto property. Just need to find a "right" way to do that. Always force binding the accessors in the process of speculation obviously is going to work, but we should consider if there are "better" alternatives.
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs
Show resolved
Hide resolved
Done with review pass (commit 13) |
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 14)
@Youssef1313 Thanks for the contribution. |
Thanks for reviewing @AlekseyTs! What do you think the next step should be? A new scenario? Fixing speculative semantic model tests? something else? |
@Youssef1313 I'll take look over the next day or so and let you know. |
Test plan: #57012