diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 2d882b4c97d..100e78d2f45 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -368,11 +368,10 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat { fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir::MatchSource) { match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) { UsefulWithWitness(pats) => { - let witnesses = match &pats[..] { - [] => vec![DUMMY_WILD_PAT], - [p..] => { - p.iter().map(|w| &**w ).collect() - } + let witnesses = if pats.is_empty() { + vec![DUMMY_WILD_PAT] + } else { + pats.iter().map(|w| &**w ).collect() }; match source { hir::MatchSource::ForLoopDesugar => { @@ -392,10 +391,21 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir: _ => { let pattern_strings: Vec<_> = witnesses.iter().map(|w| { pat_to_string(w) - }).take(10).collect(); + }).collect(); + let (tail, head) = pattern_strings.split_last().unwrap(); + const HEAD_LIMIT: usize = 9; + let joined_patterns = match head.len() { + 0 => tail.clone(), + 1...HEAD_LIMIT => head.join("`, `") + "` and `" + tail, + _ => { + let head_iter = head.to_owned().into_iter(); + let truncated_head: Vec<_> = head_iter.take(HEAD_LIMIT).collect(); + truncated_head.join("`, `") + "`, … and `" + tail + } + }; span_err!(cx.tcx.sess, sp, E0004, "non-exhaustive patterns: `{}` not covered", - pattern_strings.join("`, `") + joined_patterns ); }, } diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs index 62e61e8bf59..a84d42f1a70 100644 --- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs +++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs @@ -16,12 +16,6 @@ struct Foo { second: Option<[usize; 4]> } -enum Color { - Red, - Green, - CustomRGBA { a: bool, r: u8, g: u8, b: u8 } -} - fn struct_with_a_nested_enum_and_vector() { match (Foo { first: true, second: None }) { //~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered @@ -32,13 +26,42 @@ fn struct_with_a_nested_enum_and_vector() { } } -fn enum_with_multiple_missing_variants() { +enum Color { + Red, + Green, + CustomRGBA { a: bool, r: u8, g: u8, b: u8 } +} + +fn enum_with_two_missing_variants() { match Color::Red { - //~^ ERROR non-exhaustive patterns: `Red`, `Green` not covered + //~^ ERROR non-exhaustive patterns: `Red` and `Green` not covered Color::CustomRGBA { .. } => () } } +enum Direction { + North, East, South, West +} + +fn enum_with_three_or_more_missing_variants() { + match Direction::North { + //~^ ERROR non-exhaustive patterns: `East`, `South` and `West` not covered + Direction::North => () + } +} + +enum ExcessiveEnum { + First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth +} + +fn enum_with_excessive_missing_variants() { + match ExcessiveEnum::First { + //~^ ERROR `Sixth`, `Seventh`, `Eighth`, `Ninth`, `Tenth`, … and `Twelfth` not covered + + ExcessiveEnum::First => () + } +} + fn enum_struct_variant() { match Color::Red { //~^ ERROR non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered