Skip to content

Commit

Permalink
Fix missing drops when ignoring match values
Browse files Browse the repository at this point in the history
When the first case in a match expression returns a `Nil`, the values
returned by other cases (regardless of their type) are to be ignored,
and dropped at the end of the case body. This wasn't implemented
correctly, resulting in either drop errors (in case a reference was
returned), or a leak (when returning an owned value).

Changelog: fixed
  • Loading branch information
yorickpeterse committed Aug 11, 2023
1 parent ad26748 commit 37bc3f1
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
12 changes: 10 additions & 2 deletions compiler/src/type_check/expressions.rs
Expand Up @@ -3063,8 +3063,16 @@ impl<'a> CheckMethodBody<'a> {
let typ =
self.last_expression_type(&mut case.body, &mut new_scope);

// If an arm returns a Never type we'll ignore it. This way e.g.
// the first arm can return `Never` and the other arms can
// If the first case returns `Nil`, the value returned by other
// cases is to be ignored. In this case we also want to discard
// the case body's return values, so we have to overwrite the
// `write_result` field.
if typ.is_nil(self.db()) {
node.write_result = false;
}

// If a case returns a Never type we'll ignore it. This way e.g.
// the first case can return `Never` and the other cases can
// return other types, as long as those types are compatible
// with the first non-Never type.
if !typ.is_never(self.db()) {
Expand Down
11 changes: 11 additions & 0 deletions std/test/compiler/test_pattern_matching.inko
Expand Up @@ -66,4 +66,15 @@ fn pub tests(t: mut Tests) {
case _ -> {}
}
}

# This test checks if the `mut a` reference is dropped at the end of the match
# arm, because the first match case returns `Nil`.
t.no_panic('match drops case return values when they are to be ignored') fn {
let a = [10]

match 10 {
case 5 -> nil
case _ -> mut a
}
}
}

0 comments on commit 37bc3f1

Please sign in to comment.