mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Handle case where only other tag of nullable unwrapped needs no refcount
It's possible to have a nullable unwrapped code where the only material payload does not need refcounting operations. In this case the refcounting function is the trivial one.
This commit is contained in:
parent
b5fe932c22
commit
94c2c47da4
2 changed files with 49 additions and 4 deletions
|
@ -1345,11 +1345,16 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
union_layout,
|
||||
UnionLayout::NullableUnwrapped { .. } | UnionLayout::NonNullableUnwrapped { .. }
|
||||
) {
|
||||
debug_assert_eq!(cases.len(), 1);
|
||||
debug_assert!(cases.len() <= 1, "{cases:?}");
|
||||
|
||||
// in this case, don't switch, because the `else` branch below would try to read the (nonexistent) tag id
|
||||
let (_, only_branch) = cases.pop().unwrap();
|
||||
env.builder.build_unconditional_branch(only_branch);
|
||||
if cases.is_empty() {
|
||||
// The only other layout doesn't need refcounting. Pass through.
|
||||
builder.build_return(None);
|
||||
} else {
|
||||
// in this case, don't switch, because the `else` branch below would try to read the (nonexistent) tag id
|
||||
let (_, only_branch) = cases.pop().unwrap();
|
||||
env.builder.build_unconditional_branch(only_branch);
|
||||
}
|
||||
} else {
|
||||
let default_block = env.context.append_basic_block(parent, "switch_default");
|
||||
|
||||
|
@ -1372,6 +1377,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct UnionLayoutTags<'a> {
|
||||
nullable_id: Option<u16>,
|
||||
tags: &'a [&'a [InLayout<'a>]],
|
||||
|
|
|
@ -2196,3 +2196,42 @@ fn nullable_wrapped_with_nullable_not_last_index() {
|
|||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn refcount_nullable_unwrapped_needing_no_refcount_issue_5027() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
Effect : {} -> Str
|
||||
|
||||
after = \effect, buildNext ->
|
||||
\{} ->
|
||||
when buildNext (effect {}) is
|
||||
thunk -> thunk {}
|
||||
|
||||
line : Effect
|
||||
line = \{} -> "done"
|
||||
|
||||
await : Effect, (Str -> Effect) -> Effect
|
||||
await = \fx, cont ->
|
||||
after
|
||||
fx
|
||||
cont
|
||||
|
||||
succeed : {} -> Effect
|
||||
succeed = \{} -> (\{} -> "success")
|
||||
|
||||
test =
|
||||
await line \s ->
|
||||
if s == "done" then succeed {} else test
|
||||
|
||||
main = test {}
|
||||
"#
|
||||
),
|
||||
RocStr::from("success"),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue