diff options
| author | bors <bors@rust-lang.org> | 2019-02-08 17:13:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-02-08 17:13:56 +0000 |
| commit | a2ec156a5b5d58f2a73bf21b1fe037b6ac1cf5cc (patch) | |
| tree | 29a60d54848218c387047656d2529aee28f97ca3 | |
| parent | 0710c2026f257b9560f7f84539bc57183c3a02d3 (diff) | |
| parent | 6717727fcbc8e07f471b4a6d8fecd600230a5616 (diff) | |
| download | rust-a2ec156a5b5d58f2a73bf21b1fe037b6ac1cf5cc.tar.gz rust-a2ec156a5b5d58f2a73bf21b1fe037b6ac1cf5cc.zip | |
Auto merge of #58161 - davidtwco:issue-57960, r=arielb1
Lower constant patterns with ascribed types. Fixes #57960. This PR fixes a bug introduced by #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 PR unwraps that to access the constant pattern inside and behaves as before. r? @pnkfelix
| -rw-r--r-- | src/librustc_mir/hair/pattern/mod.rs | 33 | ||||
| -rw-r--r-- | src/test/ui/nll/issue-57960.rs | 39 |
2 files changed, 68 insertions, 4 deletions
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 6b7e1416118..eacb11fc1ac 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -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>, @@ -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, @@ -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 + } } } diff --git a/src/test/ui/nll/issue-57960.rs b/src/test/ui/nll/issue-57960.rs new file mode 100644 index 00000000000..0b52e46c459 --- /dev/null +++ b/src/test/ui/nll/issue-57960.rs @@ -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); +} |
