fix ordering bug in pattern exhaustiveness

This commit is contained in:
Folkert 2020-04-23 20:12:40 +02:00 committed by Richard Feldman
parent f8b540b6f4
commit dc320e9fd9
3 changed files with 109 additions and 6 deletions

View File

@ -935,7 +935,7 @@ fn path_to_expr_help<'a>(
) -> (Expr<'a>, Layout<'a>) {
match path {
Path::Unbox(ref unboxed) => match **unboxed {
_ => todo!(),
_ => (Expr::Load(symbol), layout),
},
Path::Empty => (Expr::Load(symbol), layout),

View File

@ -346,6 +346,7 @@ fn is_useful(matrix: &PatternMatrix, vector: &Row) -> bool {
// rows that match the same things. This is not a useful vector!
false
} else {
// NOTE: if there are bugs in this code, look at the ordering of the row/matrix
let mut vector = vector.clone();
let first_pattern = vector.remove(0);
let patterns = vector;
@ -359,8 +360,8 @@ fn is_useful(matrix: &PatternMatrix, vector: &Row) -> bool {
.collect();
let mut new_row = Vec::new();
new_row.extend(args);
new_row.extend(patterns);
new_row.extend(args);
is_useful(&new_matrix, &new_row)
}
@ -450,13 +451,21 @@ fn specialize_row_by_literal(literal: &Literal, row: &Row) -> Option<Row> {
let patterns = row;
match head {
Some(Literal(lit)) => if &lit == literal { Some(patterns) } else{ None } ,
Some(Literal(lit)) => {
if &lit == literal {
Some(patterns)
} else {
None
}
}
Some(Anything) => Some(patterns),
Some(Ctor(_,_,_)) => panic!( "Compiler bug! After type checking, constructors and literals should never align in pattern match exhaustiveness checks."),
Some(Ctor(_, _, _)) => panic!(
r#"Compiler bug! After type checking, constructors and literals should never align in pattern match exhaustiveness checks."#
),
None => panic!("Compiler error! Empty matrices should not get specialized."),
}
None => panic!("Compiler error! Empty matrices should not get specialized."),
}
}
/// INVARIANT: (length row == N) ==> (length result == N-1)

View File

@ -2243,6 +2243,100 @@ mod test_reporting {
)
}
#[test]
fn patterns_record_not_exhaustive() {
report_problem_as(
indoc!(
r#"
x = { a: 3 }
when x is
{ a: 4 } -> 4
"#
),
indoc!(
r#"
-- UNSAFE PATTERN --------------------------------------------------------------
This `when` does not cover all the possibilities:
3 > when x is
4 > { a: 4 } -> 4
Other possibilities include:
#Record _
I would have to crash if I saw one of those! Add branches for them!
"#
),
)
}
#[test]
fn patterns_record_guard_not_exhaustive() {
report_problem_as(
indoc!(
r#"
y : [ Nothing, Just Int ]
y = Just 4
x = { a: y, b: 42}
when x is
{ a: Nothing } -> 4
{ a: Just 3 } -> 4
"#
),
indoc!(
r#"
-- UNSAFE PATTERN --------------------------------------------------------------
This `when` does not cover all the possibilities:
5 > when x is
6 > { a: Nothing } -> 4
7 > { a: Just 3 } -> 4
Other possibilities include:
#Record Just _ _
I would have to crash if I saw one of those! Add branches for them!
"#
),
)
}
#[test]
fn patterns_nested_tag_not_exhaustive() {
report_problem_as(
indoc!(
r#"
when Record Nothing 1 is
Record (Nothing) b -> b
Record (Just 3) b -> b
"#
),
indoc!(
r#"
-- UNSAFE PATTERN --------------------------------------------------------------
This `when` does not cover all the possibilities:
1 > when Record Nothing 1 is
2 > Record (Nothing) b -> b
3 > Record (Just 3) b -> b
Other possibilities include:
Record Just _ _
I would have to crash if I saw one of those! Add branches for them!
"#
),
)
}
#[test]
fn patterns_int_redundant() {
report_problem_as(