mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
fix ordering bug in pattern exhaustiveness
This commit is contained in:
parent
f8b540b6f4
commit
dc320e9fd9
3 changed files with 109 additions and 6 deletions
|
@ -935,7 +935,7 @@ fn path_to_expr_help<'a>(
|
||||||
) -> (Expr<'a>, Layout<'a>) {
|
) -> (Expr<'a>, Layout<'a>) {
|
||||||
match path {
|
match path {
|
||||||
Path::Unbox(ref unboxed) => match **unboxed {
|
Path::Unbox(ref unboxed) => match **unboxed {
|
||||||
_ => todo!(),
|
_ => (Expr::Load(symbol), layout),
|
||||||
},
|
},
|
||||||
|
|
||||||
Path::Empty => (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!
|
// rows that match the same things. This is not a useful vector!
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
// NOTE: if there are bugs in this code, look at the ordering of the row/matrix
|
||||||
let mut vector = vector.clone();
|
let mut vector = vector.clone();
|
||||||
let first_pattern = vector.remove(0);
|
let first_pattern = vector.remove(0);
|
||||||
let patterns = vector;
|
let patterns = vector;
|
||||||
|
@ -359,8 +360,8 @@ fn is_useful(matrix: &PatternMatrix, vector: &Row) -> bool {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut new_row = Vec::new();
|
let mut new_row = Vec::new();
|
||||||
new_row.extend(args);
|
|
||||||
new_row.extend(patterns);
|
new_row.extend(patterns);
|
||||||
|
new_row.extend(args);
|
||||||
|
|
||||||
is_useful(&new_matrix, &new_row)
|
is_useful(&new_matrix, &new_row)
|
||||||
}
|
}
|
||||||
|
@ -450,13 +451,21 @@ fn specialize_row_by_literal(literal: &Literal, row: &Row) -> Option<Row> {
|
||||||
let patterns = row;
|
let patterns = row;
|
||||||
|
|
||||||
match head {
|
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(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)
|
/// 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]
|
#[test]
|
||||||
fn patterns_int_redundant() {
|
fn patterns_int_redundant() {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue