Perform type inference in range pattern by nbdd0121 · Pull Request #88090 · rust...
source link: https://github.com/rust-lang/rust/pull/88090
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
r? @jackh726
(rust-highfive has picked a reviewer for you, use r? to override)
This is technically a behavior change (even though I agree it's more of a bug fix), so I'm just going to cc @rust-lang/compiler
(If anyone else knows this code better and wants to take the review, feel free)
The changes look reasonable after a cursory review. @rust-lang/lang should chime in and approve the behavioral change (unless this was intentional). With that I can take a closer look at the code to approve or as for more changes.
}
impl Zero for String {
const ZERO: Self = String::new();
| | this is of type `_` but it should be `char` or numeric
| this is of type `_` but it should be `char` or numeric
if let Some((ref mut fail, _, _)) = rhs {
*fail = true;
}
self.emit_err_pat_range(span, lhs, rhs);
I'm going to go ahead and nominate this for the lang team:
Do we want to allow inference in range patterns (as in https://github.com/rust-lang/rust/blob/353c03955dfe0831e4b58f9e05e99447c06adff2/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs)? The Self
type here could be inferred to be i32
, as would be in a non-range pattern.
To summarize the effects of this PR, I believe it implements the following logic:
- When type checking a range pattern...
- In a range pattern, the LHS and RHS must be of equal type
- Further, those types must be known to be char or integral
whereas before the logic was
- When type checking a range pattern...
- In a range pattern, the LHS and RHS must be known to be char or integral
- And they must be the same type
This change in ordering makes all the difference for the inferencer, of course, since it is able to propagate types from one side to the other. Does this sound correct?
To summarize the effects of this PR, I believe it implements the following logic:
When type checking a range pattern...
- In a range pattern, the LHS and RHS must be of equal type
- Further, those types must be known to be char or integral
whereas before the logic was
When type checking a range pattern...
- In a range pattern, the LHS and RHS must be known to be char or integral
- And they must be the same type
This change in ordering makes all the difference for the inferencer, of course, since it is able to propagate types from one side to the other. Does this sound correct?
That looks correct to me.
@nbdd0121 could you actually add that explanation as a comment? That makes it abundantly clear what's going on.
A more accurate description:
- When type checking a range pattern...
- In a range pattern, if types of LHS and RHS are known, they must be char or integral
- This is just for better diagnostics (see note 1 below).
- LHS, RHS and the expected type must all be the same type
- Further, those types must be known to be char or integral
- In a range pattern, if types of LHS and RHS are known, they must be char or integral
whereas before the logic was
- When type checking a range pattern...
- In a range pattern, the LHS and RHS must be known to be char or integral
- And LHS, RHS and the expected type must all be the same type
Note 1: the early check if LHS or RHS types are known is needed because range pattern will strip away references. So if the early check is omitted and we just start unifying types, then
match "A" { "A".."B" => (), _ => (), }
will have LHS and RHS be &str
while expected type is str
, and the unification will fail and produce very terrible diagnostics. So in this case I just keep the current early check and let rustc complain that &str
isn't char or integral rather than &str
and str
mismatches.
BTW one more thing: with this PR,
match Zero::ZERO { Zero::ZERO ..= Zero::ZERO => {}, _ => {}, }
will still complain that _
is not char or integral like it does now. I wonder if I should change it to complain that "type must be known at this point" instead?
Note 1: the early check if LHS or RHS types are known is needed because range pattern will strip away references. So if the early check is omitted and we just start unifying types, then
match "A" { "A".."B" => (), _ => (), }will have LHS and RHS be
&str
while expected type isstr
, and the unification will fail and produce very terrible diagnostics. So in this case I just keep the current early check and let rustc complain that&str
isn't char or integral rather than&str
andstr
mismatches.
Interesting...can you make sure there is a test that covers this case?
BTW one more thing: with this PR,
match Zero::ZERO { Zero::ZERO ..= Zero::ZERO => {}, _ => {}, }will still complain that
_
is not char or integral like it does now. I wonder if I should change it to complain that "type must be known at this point" instead?
What happens with non-range patterns?
Interesting...can you make sure there is a test that covers this case?
This is from a existing test case ^^
What happens with non-range patterns?
Non-range patterns do not need to inspect the type, so
match Zero::ZERO { Zero::ZERO => {}, _ => {}, }
will just behave like
let _ = Zero::ZERO;
and gives a "type annotations needed" error.
@rfcbot fcp merge
We discussed this in the @rust-lang/lang meeting today. General consensus was that this change was quite reasonable; in order to change the assumption that L/R hand sides of ..
are the same type, we'd have to alter the Range
type to have multiple type parameters, which would be a very large change (and of course the assumption is already baked in, just enforced later).
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
@rfcbot fcp cancel
@rfcbot fcp merge
We discussed this in the @rust-lang/lang meeting today. General consensus was that this change was quite reasonable; in order to change the assumption that L/R hand sides of ..
are the same type, we'd have to alter the Range
type to have multiple type parameters, which would be a very large change (and of course the assumption is already baked in, just enforced later).
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
Copy link
rfcbot commented 19 days ago
This is now entering its final comment period, as per the review above.
Copy link
rfcbot commented 7 days ago
The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
This will be merged soon.
@bors r+
Commit 52a0403 has been approved by nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK