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

List patterns: add more tests and fix nullability analysis #53822

Merged
merged 10 commits into from
Oct 11, 2021

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Jun 1, 2021

Test plan: #51289

Note: the nullability analysis in this PR does not handle exhaustiveness analysis with aliasing of start/end or nested indexes

@jcouv jcouv added Area-Compilers PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. New Feature - List Patterns labels Jun 1, 2021
@jcouv jcouv added this to the C# 10 milestone Jun 1, 2021
@jcouv jcouv self-assigned this Jun 1, 2021
@jcouv jcouv changed the base branch from features/extended-property-patterns to features/list-patterns June 3, 2021 15:14
@jcouv jcouv force-pushed the list-tests branch 2 times, most recently from 0e1f442 to 232d033 Compare June 5, 2021 02:57
@jcouv jcouv marked this pull request as ready for review June 5, 2021 03:00
@jcouv jcouv requested a review from a team as a code owner June 5, 2021 03:00
@jcouv jcouv requested a review from alrz June 5, 2021 03:00
@jcouv jcouv removed the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Jun 5, 2021
@@ -1867,5 +1868,1811 @@ void verify(PropertyPatternClauseSyntax clause, string syntax, string type)
Assert.Equal(type, typeInfo.ConvertedType.ToDisplayString());
}
}

[Fact]
public void SlicePattern_Exhaustiveness()
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

This is not testing slice. Did you mean LengthPattern_Exhaustiveness #Resolved

Diagnostic(ErrorCode.ERR_NoTypeDef, "c[1..^1]").WithArguments("Missing", "missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(9, 21)
);


Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

new line #Resolved

public int this[int i] => throw null;
public int Property => throw null;
}";
// PROTOTYPE bad explanation
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

📝 I'll have a PR out for this next (I'd probably hold that off until after LDM) #Resolved

}

[Fact]
public void LengthPattern_GenericLength()
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

Maybe also test for new C<Index>() is { 0 } with class C<T> { this[T] } (should work) #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.

Good idea. It looks like there may be a bug with Index/Range, and the same one for list patterns. See ListPattern_GenericIndexingParameter below.

{
if (new C() is [var length])
length.ToString();
_ = new C<int>()[^1];
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

I don't think this is intended to be here. #Resolved

public int Count => throw null;
public int this[int i] => throw null;
}";
// PROTOTYPE should not warn, because we've covered all possibilities for first position in single item list and we don't care about lists of other lengths.
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

Slice could return an arbitrary type - as far as the analysis goes, the input type of the subpattern is "unrelated" to the list. #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.

Right. I think there's still a question of whether we have some reasonable expectations when a slice returns an indexable/rangeable type. Do we just give up on analysis or do we have some notion of what is "well-behaved"?

Copy link
Contributor

Choose a reason for hiding this comment

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

We only do this for tests when the input is exactly the same. In #53891 I had to explicitly add a special case when there's two different but "matching" indexers as the input which is a little unorthodox.

As for slice subpatterns, it wouldn't be that simple. We should match nested subpattern with the outer list. I didn't go through it but I'd expect it's going to be a lot of work which is arguably unlikely to be useful in real code.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd expect it's going to be a lot of work which is arguably unlikely to be useful in real code.

I agree. I'd be comfortable dropping the slice analysis. Just need to confirm with LDM.


class C
{
public nint Count => throw null!;
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

📝 We possibly can support this if we relax range indexers too. #Resolved

public string? Property => throw null!;
}";
// PROTOTYPE bad explanations on 1 and 2
// Note: it's a bit annoying that we don't assume a positive Count here, or allow a `uint` Count
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

Assuming positive count in the codegen or for subsumption? e.g. Is the match e is [-1] impossible? of course we don't need to worry about this if we drop length patterns.. #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.

LDM agreed to make such assumptions for the length/list pattern. But not generally for property patterns such as Count: <= 0 above.
Not having a good syntax for empty list means causing more pain if I fall back to Count property pattern.

public int Count => throw null;
public int this[int i] => throw null;
}";
// PROTOTYPE should not warn, because we've covered all possibilities for first position in single item list and we don't care about lists of other lengths.
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

📝 Will be addressed by #53891 #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.

Very cool. Thanks!
Ping when you want some eyes on that PR.

public class C
{
public int Length => 2;
public string this[in System.Index i] => ""item value"";
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

I think we should also test for [ImplicitlyConvertibleFromIndex i] (should work) #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.

Good idea. Added ListPattern_ImplicitlyConvertibleFromIndexAndRange which hit an assertion.

@jcouv jcouv requested a review from alrz June 5, 2021 16:23
}
}
";
// PROTOTYPE errors 1 and 2 are unexpected
Copy link
Contributor

@alrz alrz Jun 5, 2021

Choose a reason for hiding this comment

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

This is expected. we require exactly this[int] as the member for implicit support (vs. only a viable lookup for Index). #Resolved

@jcouv jcouv marked this pull request as draft June 24, 2021 00:55
@jcouv jcouv added the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Jun 24, 2021
@jaredpar jaredpar modified the milestones: C# 10, 17.0 Jul 13, 2021
@jcouv jcouv removed the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Jul 13, 2021
@jcouv jcouv marked this pull request as ready for review July 13, 2021 19:25
@jcouv
Copy link
Member Author

jcouv commented Jul 13, 2021

Rebased the change on top of syntax change PR which is now merged.

@jcouv jcouv marked this pull request as draft July 13, 2021 20:11
@jcouv jcouv marked this pull request as ready for review July 14, 2021 15:53
@jcouv jcouv requested a review from 333fred September 17, 2021 06:31
@jcouv jcouv modified the milestones: 17.0, 17.1 Sep 17, 2021
@jcouv jcouv mentioned this pull request Sep 18, 2021
91 tasks
@jcouv
Copy link
Member Author

jcouv commented Oct 4, 2021

@333fred @dotnet/roslyn-compiler for review. Thanks

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

Done review pass (commit 8)

@jcouv jcouv requested a review from 333fred October 6, 2021 06:08
Copy link
Member

@333fred 333fred 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 9)

@jcouv
Copy link
Member Author

jcouv commented Oct 6, 2021

@dotnet/roslyn-compiler for second review. Thanks

tests.Add(new Tests.One(indexEvaluation));
var indexTemp = new BoundDagTemp(syntax, subpattern.InputType, indexEvaluation);
var indexTemp = new BoundDagTemp(subpattern.Syntax, subpattern.InputType, indexEvaluation);
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we should open a tracking issue to make an analogous change for the scenarios @alrz is referring to.

verify(declarations[0], "item", "System.Int32");
verify(declarations[1], "item2", "System.Int32?");
verify(declarations[2], "item3", "System.String?");
verify(declarations[3], "item4", "System.String?");
Copy link
Contributor

@RikkiGibson RikkiGibson Oct 9, 2021

Choose a reason for hiding this comment

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

nit: assert on declarations.Length? (same comment in the other similar new tests) #Resolved

}
}
";
// PROTOTYPE: incorrect exhaustiveness examples from explainer
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: prefer PROTOTYPE(list-patterns) (also for other prototype comments in the file.)

FWIW, I don't see shortcomings in the pattern explainer as blocking.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since we disallow the "PROTOTYPE" keyword in main branch, I figured the longer format doesn't help much (and it's more trouble to type). I'll stick with that if that's okay.

@jcouv jcouv enabled auto-merge (squash) October 11, 2021 05:39
@jcouv jcouv merged commit d7c97c6 into dotnet:features/list-patterns Oct 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants