feat(exhaustiveness): show both clauses in redundant error

This commit is contained in:
rvcas 2023-07-31 13:21:01 -04:00 committed by Lucas
parent ef2fc57ca9
commit b6ac39f322
3 changed files with 22 additions and 9 deletions

View File

@ -1434,8 +1434,8 @@ impl<'a> Environment<'a> {
} }
/// Checks that the given patterns are exhaustive for given type. /// Checks that the given patterns are exhaustive for given type.
/// Currently only performs exhaustiveness checking for custom types, /// https://github.com/elm/compiler/blob/047d5026fe6547c842db65f7196fed3f0b4743ee/compiler/src/Nitpick/PatternMatches.hs#L397-L475
/// only at the top level (without recursing into constructor arguments). /// http://moscova.inria.fr/~maranget/papers/warn/index.html
pub fn check_exhaustiveness( pub fn check_exhaustiveness(
&mut self, &mut self,
unchecked_patterns: &[&TypedPattern], unchecked_patterns: &[&TypedPattern],
@ -1451,8 +1451,19 @@ impl<'a> Environment<'a> {
if matrix.is_useful(&pattern_stack) { if matrix.is_useful(&pattern_stack) {
matrix.push(pattern_stack); matrix.push(pattern_stack);
} else { } else {
let index = matrix
.flatten()
.into_iter()
.enumerate()
.find(|(_, p)| p == pattern_stack.head())
.map(|(i, _)| i)
.expect("should find index");
let typed_pattern = unchecked_patterns[index];
return Err(Error::RedundantMatchClause { return Err(Error::RedundantMatchClause {
location: unchecked_pattern.location(), original: typed_pattern.location(),
redundant: unchecked_pattern.location(),
}); });
} }
} }

View File

@ -543,17 +543,19 @@ Maybe you meant to turn it public using the '{keyword_pub}' keyword?"#
#[error( #[error(
"{}\n", "{}\n",
format!( format!(
"I discovered a '{keyword_when}/{keyword_is}' expression with a redundant clause.", "I discovered a '{keyword_when}/{keyword_is}' expression with a redundant pattern.",
keyword_is = "is".if_supports_color(Stdout, |s| s.purple()), keyword_is = "is".if_supports_color(Stdout, |s| s.purple()),
keyword_when = "when".if_supports_color(Stdout, |s| s.purple()) keyword_when = "when".if_supports_color(Stdout, |s| s.purple())
) )
)] )]
#[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#matching"))] #[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#matching"))]
#[diagnostic(code("redundant_pattern_match"))] #[diagnostic(code("redundant_pattern_match"))]
#[diagnostic(help("You can safely remove this clause."))] #[diagnostic(help("Double check these patterns and then remove one of the clauses."))]
RedundantMatchClause { RedundantMatchClause {
#[label] #[label("first found here")]
location: Span, original: Span,
#[label("redundant")]
redundant: Span,
}, },
#[error("I couldn't figure out the type of a record you're trying to access.\n")] #[error("I couldn't figure out the type of a record you're trying to access.\n")]

View File

@ -41,7 +41,7 @@ impl PatternStack {
self.0.insert(index, element); self.0.insert(index, element);
} }
fn head(&self) -> &Pattern { pub(super) fn head(&self) -> &Pattern {
&self.0[0] &self.0[0]
} }
@ -385,7 +385,7 @@ pub(crate) enum Complete {
No, No,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
pub(crate) enum Pattern { pub(crate) enum Pattern {
Wildcard, Wildcard,
Literal(Literal), Literal(Literal),