Skip to content

Commit

Permalink
Fix compiling unreachable integer patterns
Browse files Browse the repository at this point in the history
This ensures that when encountering cases that use binding patterns
followed by cases that use integer patterns, those integer patterns are
compiled such that they can be detected by a compiler as being
unreachable (= since their original target bodies are not present in the
decision tree).

This is adopted from the Gleam merge request
gleam-lang/gleam#3046 that made the same fix,
minus a redundant clone() when pushing into the fallback rows.

For more information refer to the following issues:

- inko-lang/inko#707
- gleam-lang/gleam#2651
  • Loading branch information
yorickpeterse committed Oct 30, 2024
1 parent ce8cbe2 commit e2d23d0
Showing 1 changed file with 38 additions and 5 deletions.
43 changes: 38 additions & 5 deletions jacobs2021/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,16 +550,20 @@ impl Compiler {
}

tested.insert(key, raw_cases.len());
raw_cases.push((cons, Vec::new(), vec![row]));

let mut rows = fallback_rows.clone();

rows.push(row);
raw_cases.push((cons, Vec::new(), rows));
} else {
for (_, _, rows) in &mut raw_cases {
rows.push(row.clone());
}

fallback_rows.push(row);
}
}

for (_, _, rows) in &mut raw_cases {
rows.append(&mut fallback_rows.clone());
}

let cases = raw_cases
.into_iter()
.map(|(cons, vars, rows)| {
Expand Down Expand Up @@ -1041,6 +1045,35 @@ mod tests {
);
}

#[test]
fn test_compile_unreachable_int_pattern() {
let mut compiler = Compiler::new();
let int_type = new_type(&mut compiler, Type::Int);
let input = compiler.new_variable(int_type);
let result = compile(
compiler,
input,
vec![(int(4), rhs(1)), (bind("a"), rhs(3)), (int(5), rhs(2))],
);

assert_eq!(
result.tree,
Decision::Switch(
input,
vec![
Case::new(Constructor::Int(4), Vec::new(), success(1)),
Case::new(
Constructor::Int(5),
Vec::new(),
success_with_bindings(vec![("a", input)], 3)
),
],
Some(Box::new(success_with_bindings(vec![("a", input)], 3)))
)
);
assert_eq!(result.diagnostics.reachable, vec![1, 3, 3]);
}

#[test]
fn test_compile_nonexhaustive_nested_int_pattern() {
let mut compiler = Compiler::new();
Expand Down

0 comments on commit e2d23d0

Please sign in to comment.