Skip to content

Commit 6717727

Browse files
committed
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 8ae730a commit 6717727

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
@@ -167,6 +167,17 @@ pub enum PatternKind<'tcx> {
167167
},
168168
}
169169

170+
impl<'tcx> PatternKind<'tcx> {
171+
/// If this is a `PatternKind::AscribeUserType` then return the subpattern kind, otherwise
172+
/// return this pattern kind.
173+
fn with_user_type_ascription_subpattern(self) -> Self {
174+
match self {
175+
PatternKind::AscribeUserType { subpattern: Pattern { box kind, .. }, .. } => kind,
176+
kind => kind,
177+
}
178+
}
179+
}
180+
170181
#[derive(Clone, Copy, Debug, PartialEq)]
171182
pub struct PatternRange<'tcx> {
172183
pub lo: ty::Const<'tcx>,
@@ -403,9 +414,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
403414
PatKind::Lit(ref value) => self.lower_lit(value),
404415

405416
PatKind::Range(ref lo_expr, ref hi_expr, end) => {
406-
match (self.lower_lit(lo_expr), self.lower_lit(hi_expr)) {
407-
(PatternKind::Constant { value: lo },
408-
PatternKind::Constant { value: hi }) => {
417+
match (
418+
// Look for `PatternKind::Constant` patterns inside of any
419+
// `PatternKind::AscribeUserType` patterns. Type ascriptions can be safely
420+
// ignored for the purposes of lowering a range correctly - these are checked
421+
// elsewhere for well-formedness.
422+
self.lower_lit(lo_expr).with_user_type_ascription_subpattern(),
423+
self.lower_lit(hi_expr).with_user_type_ascription_subpattern(),
424+
) {
425+
(PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
409426
use std::cmp::Ordering;
410427
let cmp = compare_const_vals(
411428
self.tcx,
@@ -454,7 +471,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
454471
}
455472
}
456473
}
457-
_ => PatternKind::Wild
474+
ref pats => {
475+
self.tcx.sess.delay_span_bug(
476+
pat.span,
477+
&format!("found bad range pattern `{:?}` outside of error recovery",
478+
pats),
479+
);
480+
481+
PatternKind::Wild
482+
}
458483
}
459484
}
460485

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)