-
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
List patterns: add more tests and fix nullability analysis #53822
Conversation
0e1f442
to
232d033
Compare
@@ -1867,5 +1868,1811 @@ void verify(PropertyPatternClauseSyntax clause, string syntax, string type) | |||
Assert.Equal(type, typeInfo.ConvertedType.ToDisplayString()); | |||
} | |||
} | |||
|
|||
[Fact] | |||
public void SlicePattern_Exhaustiveness() |
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 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) | ||
); | ||
|
||
|
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 line #Resolved
public int this[int i] => throw null; | ||
public int Property => throw null; | ||
}"; | ||
// PROTOTYPE bad explanation |
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 have a PR out for this next (I'd probably hold that off until after LDM) #Resolved
} | ||
|
||
[Fact] | ||
public void LengthPattern_GenericLength() |
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.
Maybe also test for new C<Index>() is { 0 }
with class C<T> { this[T] }
(should work) #Resolved
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.
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]; |
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 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. |
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.
Slice
could return an arbitrary type - as far as the analysis goes, the input type of the subpattern is "unrelated" to the list. #Resolved
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.
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"?
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 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.
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'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!; |
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 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 |
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.
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
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.
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. |
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.
📝 Will be addressed by #53891 #Resolved
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.
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""; |
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 think we should also test for [ImplicitlyConvertibleFromIndex i]
(should work) #Resolved
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.
Good idea. Added ListPattern_ImplicitlyConvertibleFromIndexAndRange
which hit an assertion.
} | ||
} | ||
"; | ||
// PROTOTYPE errors 1 and 2 are unexpected |
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 is expected. we require exactly this[int]
as the member for implicit support (vs. only a viable lookup for Index). #Resolved
Rebased the change on top of syntax change PR which is now merged. |
@333fred @dotnet/roslyn-compiler for review. Thanks |
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.
Done review pass (commit 8)
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs
Outdated
Show resolved
Hide resolved
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 9)
@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); |
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.
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?"); |
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.
nit: assert on declarations.Length? (same comment in the other similar new tests) #Resolved
} | ||
} | ||
"; | ||
// PROTOTYPE: incorrect exhaustiveness examples from explainer |
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.
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.
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.
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.
Test plan: #51289
Note: the nullability analysis in this PR does not handle exhaustiveness analysis with aliasing of start/end or nested indexes