Skip to content

Commit 04d6d7b

Browse files
davidtwcopietroalbini
authored andcommitted
Lower constant patterns with ascribed types.
This commit fixes a bug introduced by rust-lang#55937 which started checking user type annotations for associated type patterns. Where lowering a associated constant expression would previously return a `PatternKind::Constant`, it now returns a `PatternKind::AscribeUserType` with a `PatternKind::Constant` inside, this commit unwraps that to access the constant pattern inside and behaves as before.
1 parent 94ca417 commit 04d6d7b

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

src/librustc_mir/hair/pattern/mod.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ pub enum PatternKind<'tcx> {
164164
},
165165
}
166166

167+
impl<'tcx> PatternKind<'tcx> {
168+
/// If this is a `PatternKind::AscribeUserType` then return the subpattern kind, otherwise
169+
/// return this pattern kind.
170+
fn with_user_type_ascription_subpattern(self) -> Self {
171+
match self {
172+
PatternKind::AscribeUserType { subpattern: Pattern { box kind, .. }, .. } => kind,
173+
kind => kind,
174+
}
175+
}
176+
}
177+
167178
#[derive(Clone, Copy, Debug, PartialEq)]
168179
pub struct PatternRange<'tcx> {
169180
pub lo: ty::Const<'tcx>,
@@ -400,9 +411,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
400411
PatKind::Lit(ref value) => self.lower_lit(value),
401412

402413
PatKind::Range(ref lo_expr, ref hi_expr, end) => {
403-
match (self.lower_lit(lo_expr), self.lower_lit(hi_expr)) {
404-
(PatternKind::Constant { value: lo },
405-
PatternKind::Constant { value: hi }) => {
414+
match (
415+
// Look for `PatternKind::Constant` patterns inside of any
416+
// `PatternKind::AscribeUserType` patterns. Type ascriptions can be safely
417+
// ignored for the purposes of lowering a range correctly - these are checked
418+
// elsewhere for well-formedness.
419+
self.lower_lit(lo_expr).with_user_type_ascription_subpattern(),
420+
self.lower_lit(hi_expr).with_user_type_ascription_subpattern(),
421+
) {
422+
(PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
406423
use std::cmp::Ordering;
407424
let cmp = compare_const_vals(
408425
self.tcx,
@@ -451,7 +468,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
451468
}
452469
}
453470
}
454-
_ => PatternKind::Wild
471+
ref pats => {
472+
self.tcx.sess.delay_span_bug(
473+
pat.span,
474+
&format!("found bad range pattern `{:?}` outside of error recovery",
475+
pats),
476+
);
477+
478+
PatternKind::Wild
479+
}
455480
}
456481
}
457482

src/test/ui/nll/issue-57960.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// run-pass
2+
3+
#![allow(dead_code)]
4+
5+
trait Range {
6+
const FIRST: u8;
7+
const LAST: u8;
8+
}
9+
10+
struct OneDigit;
11+
impl Range for OneDigit {
12+
const FIRST: u8 = 0;
13+
const LAST: u8 = 9;
14+
}
15+
16+
struct TwoDigits;
17+
impl Range for TwoDigits {
18+
const FIRST: u8 = 10;
19+
const LAST: u8 = 99;
20+
}
21+
22+
struct ThreeDigits;
23+
impl Range for ThreeDigits {
24+
const FIRST: u8 = 100;
25+
const LAST: u8 = 255;
26+
}
27+
28+
fn digits(x: u8) -> u32 {
29+
match x {
30+
OneDigit::FIRST...OneDigit::LAST => 1,
31+
TwoDigits::FIRST...TwoDigits::LAST => 2,
32+
ThreeDigits::FIRST...ThreeDigits::LAST => 3,
33+
_ => unreachable!(),
34+
}
35+
}
36+
37+
fn main() {
38+
assert_eq!(digits(100), 3);
39+
}

0 commit comments

Comments
 (0)