mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 16:51:53 +03:00
fix ordering bug in pattern exhaustiveness
This commit is contained in:
parent
f8b540b6f4
commit
dc320e9fd9
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user