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

Lower constant patterns with ascribed types. #58161

Merged
merged 1 commit into from
Feb 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions src/librustc_mir/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ pub enum PatternKind<'tcx> {
},
}

impl<'tcx> PatternKind<'tcx> {
/// If this is a `PatternKind::AscribeUserType` then return the subpattern kind, otherwise
/// return this pattern kind.
fn with_user_type_ascription_subpattern(self) -> Self {
match self {
PatternKind::AscribeUserType { subpattern: Pattern { box kind, .. }, .. } => kind,
kind => kind,
}
}
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct PatternRange<'tcx> {
pub lo: ty::Const<'tcx>,
Expand Down Expand Up @@ -403,9 +414,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
PatKind::Lit(ref value) => self.lower_lit(value),

PatKind::Range(ref lo_expr, ref hi_expr, end) => {
match (self.lower_lit(lo_expr), self.lower_lit(hi_expr)) {
(PatternKind::Constant { value: lo },
PatternKind::Constant { value: hi }) => {
match (
// Look for `PatternKind::Constant` patterns inside of any
// `PatternKind::AscribeUserType` patterns. Type ascriptions can be safely
// ignored for the purposes of lowering a range correctly - these are checked
// elsewhere for well-formedness.
self.lower_lit(lo_expr).with_user_type_ascription_subpattern(),
self.lower_lit(hi_expr).with_user_type_ascription_subpattern(),
) {
(PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
use std::cmp::Ordering;
let cmp = compare_const_vals(
self.tcx,
Expand Down Expand Up @@ -454,7 +471,15 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
}
}
}
_ => PatternKind::Wild
ref pats => {
self.tcx.sess.delay_span_bug(
pat.span,
&format!("found bad range pattern `{:?}` outside of error recovery",
pats),
);

PatternKind::Wild
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/test/ui/nll/issue-57960.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// run-pass

#![allow(dead_code)]

trait Range {
const FIRST: u8;
const LAST: u8;
}

struct OneDigit;
impl Range for OneDigit {
const FIRST: u8 = 0;
const LAST: u8 = 9;
}

struct TwoDigits;
impl Range for TwoDigits {
const FIRST: u8 = 10;
const LAST: u8 = 99;
}

struct ThreeDigits;
impl Range for ThreeDigits {
const FIRST: u8 = 100;
const LAST: u8 = 255;
}

fn digits(x: u8) -> u32 {
match x {
OneDigit::FIRST...OneDigit::LAST => 1,
TwoDigits::FIRST...TwoDigits::LAST => 2,
ThreeDigits::FIRST...ThreeDigits::LAST => 3,
_ => unreachable!(),
}
}

fn main() {
assert_eq!(digits(100), 3);
}