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

Perform type inference in range pattern #88090

Merged
merged 3 commits into from
Oct 5, 2021
Merged

Conversation

nbdd0121
Copy link
Contributor

Fix #88074

@rust-highfive
Copy link
Collaborator

r? @jackh726

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 16, 2021
@jackh726
Copy link
Member

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)

Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

When associated consts are involved in this error, we should likely point at them.

Comment on lines 7 to 8
| | this is of type `_` but it should be `char` or numeric
| this is of type `_` but it should be `char` or numeric
Copy link
Contributor

Choose a reason for hiding this comment

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

Somewhere we are not actually using resolve_ty_if_possible. We should be mentioning that these are of type String.

if let Some((ref mut fail, _, _)) = rhs {
*fail = true;
}
self.emit_err_pat_range(span, lhs, rhs);
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 this is why. We pass in lhs and rhs. Inside of emit_err_pat_range we don't resolve_vars_if_possible on lhs.1 or rhs.1. I think that doing that should make the labels talk about String instead of _.

@inquisitivecrystal inquisitivecrystal added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 24, 2021
@jackh726
Copy link
Member

jackh726 commented Sep 7, 2021

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.

@jackh726 jackh726 added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 7, 2021
@nikomatsakis
Copy link
Contributor

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?

@jackh726
Copy link
Member

jackh726 commented Sep 9, 2021

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.

@nbdd0121
Copy link
Contributor Author

nbdd0121 commented Sep 9, 2021

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

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.

@nbdd0121
Copy link
Contributor Author

nbdd0121 commented Sep 9, 2021

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?

@jackh726
Copy link
Member

jackh726 commented Sep 9, 2021

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.

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?

@nbdd0121
Copy link
Contributor Author

nbdd0121 commented Sep 9, 2021

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.

@jackh726
Copy link
Member

jackh726 commented Sep 9, 2021

I would say if the change to emit "type annotations needed" is small, that's preferable, so behavior lines up. If not, then I think it can be left as a followup FIXME

@nbdd0121
Copy link
Contributor Author

v1 -> v2:

  • add extra explanatory comments
  • add resolve_vars_if_possible to emit_err_pat_range
  • emit E0282 type annotations needed if type is _

@nikomatsakis
Copy link
Contributor

@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).

@rfcbot
Copy link

rfcbot commented Sep 21, 2021

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 rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Sep 21, 2021
@nikomatsakis nikomatsakis removed the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Sep 21, 2021
@nikomatsakis
Copy link
Contributor

@rfcbot fcp cancel

@nikomatsakis
Copy link
Contributor

@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).

@rfcbot
Copy link

rfcbot commented Sep 21, 2021

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 rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Sep 21, 2021
@rfcbot
Copy link

rfcbot commented Sep 21, 2021

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Sep 21, 2021
@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Oct 3, 2021
@rfcbot
Copy link

rfcbot commented Oct 3, 2021

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.

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Oct 4, 2021

📌 Commit 52a0403 has been approved by nikomatsakis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). labels Oct 4, 2021
Manishearth added a commit to Manishearth/rust that referenced this pull request Oct 5, 2021
Manishearth added a commit to Manishearth/rust that referenced this pull request Oct 5, 2021
Manishearth added a commit to Manishearth/rust that referenced this pull request Oct 5, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 5, 2021
…ingjubilee

Rollup of 15 pull requests

Successful merges:

 - rust-lang#87993 (Stabilize try_reserve)
 - rust-lang#88090 (Perform type inference in range pattern)
 - rust-lang#88780 (Added abs_diff for integer types.)
 - rust-lang#89270 (path.push() should work as expected on windows verbatim paths)
 - rust-lang#89413 (Correctly handle supertraits for min_specialization)
 - rust-lang#89456 (Update to the final LLVM 13.0.0 release)
 - rust-lang#89466 (Fix bug with query modifier parsing)
 - rust-lang#89473 (Fix extra `non_snake_case` warning for shorthand field bindings)
 - rust-lang#89474 (rustdoc: Improve doctest pass's name and module's name)
 - rust-lang#89478 (Fixed numerus of error message)
 - rust-lang#89480 (Add test for issue 89118.)
 - rust-lang#89487 (Try to recover from a `=>` -> `=` or `->` typo in a match arm)
 - rust-lang#89494 (Deny `where` clauses on `auto` traits)
 - rust-lang#89511 (:arrow_up: rust-analyzer)
 - rust-lang#89536 (update Miri)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 4f6afee into rust-lang:master Oct 5, 2021
@rustbot rustbot added this to the 1.57.0 milestone Oct 5, 2021
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Oct 7, 2021
@nbdd0121 nbdd0121 deleted the inference branch October 7, 2021 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Range pattern does not perform type inference
10 participants