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

[semi-auto-props]: Add more tests (GetMembers, speculative semantic model) #59270

Merged
merged 14 commits into from
Feb 24, 2022

Conversation

Youssef1313
Copy link
Member

Test plan: #57012

@Youssef1313 Youssef1313 requested a review from a team as a code owner February 4, 2022 11:09
@ghost ghost added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Feb 4, 2022
Assert.Empty(comp.GetTypeByMetadataName("C").GetFieldsToEmit());

var fieldKeywordTypeInfo = speculativeModel.GetTypeInfo(identifier);
Assert.Equal(SpecialType.System_Int32, fieldKeywordTypeInfo.Type.SpecialType);
Copy link
Member Author

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.

Copy link
Contributor

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

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?

Copy link
Contributor

@AlekseyTs AlekseyTs Feb 4, 2022

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.

Copy link
Member Author

@Youssef1313 Youssef1313 Feb 5, 2022

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?

  1. Bind original tree first
  2. Bind speculated tree first

as I demonstrated in #59270 (comment)

If not, which scenario of the two is the interesting one?

Copy link
Contributor

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.

@Youssef1313 Youssef1313 changed the title [semi-auto-props]: Add more tests [semi-auto-props]: Add more tests (GetMembers, speculative semantic model) Feb 4, 2022
@AlekseyTs
Copy link
Contributor

Done with review pass (commit 3)

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 4)

@Youssef1313
Copy link
Member Author

@AlekseyTs I added more tests. This is ready for another look.

@AlekseyTs
Copy link
Contributor

Is the next step to address the cases where we don't like the behavior of speculative semantic model? Are all of them covered by PROTOTYPE comments or do you see cases that're not (or vice versa)?

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

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 10)

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 11). I didn't see any response to #59270 (comment).

@Youssef1313
Copy link
Member Author

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);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding);

Consider also checking GetFieldsToEmit before this assert. #Closed

{
Assert.Equal("System.Int32 field", fieldKeywordSymbolInfo.Symbol.GetSymbol().ToTestDisplayString());
Assert.Equal(SymbolKind.Local, fieldKeywordSymbolInfo.Symbol.Kind);
Assert.Equal(2, accessorBindingData.NumberOfPerformedAccessorBinding);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert.Equal(2, accessorBindingData.NumberOfPerformedAccessorBinding);

I think it would be good to determine what triggers the binding (by asserting NumberOfPerformedAccessorBinding in right places), the GetFieldsToEmit above or speculative binding. #Closed

[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; }")]
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 23, 2022

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 { int field = 0; return field; }")]

Is testing different order not interesting? #Closed

[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)]
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false

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

Copy link
Member Author

@Youssef1313 Youssef1313 Feb 25, 2022

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?

Copy link
Member Author

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?

Copy link
Contributor

@AlekseyTs AlekseyTs Feb 25, 2022

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".

Copy link
Contributor

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.

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 13)

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 14)

@AlekseyTs AlekseyTs merged commit 73d45d9 into dotnet:features/semi-auto-props Feb 24, 2022
@AlekseyTs
Copy link
Contributor

@Youssef1313 Thanks for the contribution.

@Youssef1313 Youssef1313 deleted the semi-tests branch February 24, 2022 19:21
@Youssef1313
Copy link
Member Author

Youssef1313 commented Feb 24, 2022

Thanks for reviewing @AlekseyTs! What do you think the next step should be? A new scenario? Fixing speculative semantic model tests? something else?

@333fred
Copy link
Member

333fred commented Feb 24, 2022

@Youssef1313 I'll take look over the next day or so and let you know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants