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

Collection expressions: analyze nullability of element assignments #70192

Merged
merged 14 commits into from
Oct 5, 2023

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Sep 29, 2023

Addresses parts of #68786

The parts that are not addressed in this PR:

  • method type re-inference with nullability (added some scenarios to illustrate)
  • spreads

Relates to test plan #66418

@jcouv jcouv self-assigned this Sep 29, 2023
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Sep 29, 2023
@jcouv jcouv added this to the 17.8 milestone Sep 29, 2023
@jcouv jcouv force-pushed the coll-nullability branch 2 times, most recently from db7004f to 3c6919c Compare September 29, 2023 18:09
@jcouv jcouv force-pushed the coll-nullability branch 3 times, most recently from b8d0c85 to 121cade Compare September 29, 2023 20:11
@jcouv jcouv marked this pull request as ready for review September 29, 2023 20:41
@jcouv jcouv requested a review from a team as a code owner September 29, 2023 20:41
break;
case BoundCollectionExpressionSpreadElement spread:
// https://github.com/dotnet/roslyn/issues/68786: We should check the spread
Visit(spread);
Copy link
Contributor

@RikkiGibson RikkiGibson Oct 4, 2023

Choose a reason for hiding this comment

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

Is there anything to do besides visit the spread, and warn if the result may be null? (since we want to enumerate the operand value, it should be non-null.) #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we may want VisitRvalue here because if a spread puts us into a split state after visiting (like in an error scenario) that could mess things up later on.

Copy link
Member

@cston cston Oct 4, 2023

Choose a reason for hiding this comment

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

FWIW, with #70197, NullableWalker.VisitCollectionExpressionSpreadElement() relies on base.VisitCollectionExpressionSpreadElement(node) which simply calls VisitRvalue(node.Expression).

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd be comfortable with this assuming we have a test demonstrating that things don't fall over when an expression inside a spread splits the state. e.g. [..(x is not null)]

Copy link
Member Author

Choose a reason for hiding this comment

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

Spreads are not in scope for this PR, so I don't want to go too far. I'd be okay with removing this entirely if you prefer.

As things stand, ..(x is null) hits an assertion: System.InvalidOperationException : Analyzed 11 nodes in NullableWalker, but DebugVerifier expects 10. Example of unverified node: BoundCollectionExpressionSpreadElement ..(x is null)

In release mode, the test produces the expected diagnsotic (binding error). Added a test

Copy link
Member Author

@jcouv jcouv Oct 4, 2023

Choose a reason for hiding this comment

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

Note: a similar assertion is hit if I remove this case, even on simple cases. I still think it's beneficial to keep it in the interim (before we have fully coverage on spreads)

System.InvalidOperationException : Analyzed 33 nodes in NullableWalker, but DebugVerifier expects 27. Example of unverified node: BoundCollectionExpressionSpreadElement ..a

Copy link
Contributor

@RikkiGibson RikkiGibson Oct 4, 2023

Choose a reason for hiding this comment

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

As long as the compiler doesn't blow up in the retail build in these cases, I'm happy. Since it looks like we are actually visiting the spread operand, I think we are just missing the top-level nullable warning for when the operand may be null. That's OK to address later. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

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

Chuck pointed out the assertion problem can be solved by undoing the s_skippedExpressions change. Done

RikkiGibson
RikkiGibson previously approved these changes Oct 4, 2023
@RikkiGibson RikkiGibson dismissed their stale review October 4, 2023 17:28

Want to wait until the suggested Visit->VisitRValue change is investigated

@RikkiGibson
Copy link
Contributor

Analyzers leg failed

src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs(18732,1): error IDE0055: (NETCORE_ENGINEERING_TELEMETRY=Build) Fix formatting (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055)

// https://github.com/dotnet/roslyn/issues/68786: We should check the spreads without asserting in DebugVerifier
#if RELEASE
string src = """
#nullable enable
Copy link
Contributor

@RikkiGibson RikkiGibson Oct 4, 2023

Choose a reason for hiding this comment

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

Formatting warning is being reported here. I honestly don't know what's wrong. Maybe a bug due to presence of the if-directive above? Might want to use compilation options to enable nullability for this test, or use attributes to only run the test in release mode.

I think @Youssef1313 may have reported something like this recently. #Resolved

Copy link
Member

Choose a reason for hiding this comment

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

@RikkiGibson Yup, that's the same root cause as dotnet/csharplang#7520.

For "Debug" where the #if RELEASE is false, the compiler will parse everything in the #if RELEASE block as disabled trivia, and it will parse #nullable enable as NullableDirectiveTrivia even if the human thinking is that it's part of a string literal and not a nullable directive trivia.

public void SpreadNullability_SplitExpression()
{
// https://github.com/dotnet/roslyn/issues/68786: We should check the spreads without asserting in DebugVerifier
#if RELEASE
Copy link
Member

@jjonescz jjonescz Oct 5, 2023

Choose a reason for hiding this comment

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

Consider using [ConditionalFact(typeof(IsRelease))] instead. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup. Done. Thanks

@jcouv jcouv changed the base branch from release/dev17.8 to features/CollectionLiterals October 5, 2023 16:38
@jcouv jcouv enabled auto-merge (squash) October 5, 2023 22:44
@jcouv jcouv merged commit 89a699d into dotnet:features/CollectionLiterals Oct 5, 2023
25 checks passed
@jcouv jcouv deleted the coll-nullability branch October 6, 2023 00:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers New Feature - Collection Expressions untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants