mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-02 19:32:17 +00:00
fix index bug in recursive decrements
This commit is contained in:
parent
e0b5a76a04
commit
c848a85eb4
3 changed files with 54 additions and 6 deletions
|
@ -1,6 +1,7 @@
|
||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
use bumpalo::collections::vec::Vec;
|
use bumpalo::collections::vec::Vec;
|
||||||
|
use bumpalo::collections::CollectIn;
|
||||||
use roc_module::low_level::{LowLevel, LowLevel::*};
|
use roc_module::low_level::{LowLevel, LowLevel::*};
|
||||||
use roc_module::symbol::{IdentIds, Symbol};
|
use roc_module::symbol::{IdentIds, Symbol};
|
||||||
use roc_target::PtrWidth;
|
use roc_target::PtrWidth;
|
||||||
|
@ -1279,6 +1280,13 @@ fn refcount_union_contents<'a>(
|
||||||
// (Order is important, to avoid use-after-free for Dec)
|
// (Order is important, to avoid use-after-free for Dec)
|
||||||
let following = Stmt::Jump(jp_contents_modified, &[]);
|
let following = Stmt::Jump(jp_contents_modified, &[]);
|
||||||
|
|
||||||
|
let field_layouts = field_layouts
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.enumerate()
|
||||||
|
.collect_in::<Vec<_>>(root.arena)
|
||||||
|
.into_bump_slice();
|
||||||
|
|
||||||
let fields_stmt = refcount_tag_fields(
|
let fields_stmt = refcount_tag_fields(
|
||||||
root,
|
root,
|
||||||
ident_ids,
|
ident_ids,
|
||||||
|
@ -1503,7 +1511,7 @@ fn refcount_union_tailrec<'a>(
|
||||||
let mut tail_stmt = None;
|
let mut tail_stmt = None;
|
||||||
for (i, field) in field_layouts.iter().enumerate() {
|
for (i, field) in field_layouts.iter().enumerate() {
|
||||||
if i != tailrec_index {
|
if i != tailrec_index {
|
||||||
filtered.push(*field);
|
filtered.push((i, *field));
|
||||||
} else {
|
} else {
|
||||||
let field_val =
|
let field_val =
|
||||||
root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
|
root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
|
||||||
|
@ -1537,7 +1545,14 @@ fn refcount_union_tailrec<'a>(
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
|
|
||||||
(*field_layouts, tail_stmt)
|
let field_layouts = field_layouts
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.enumerate()
|
||||||
|
.collect_in::<Vec<_>>(root.arena)
|
||||||
|
.into_bump_slice();
|
||||||
|
|
||||||
|
(field_layouts, tail_stmt)
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields_stmt = refcount_tag_fields(
|
let fields_stmt = refcount_tag_fields(
|
||||||
|
@ -1608,20 +1623,20 @@ fn refcount_tag_fields<'a>(
|
||||||
ctx: &mut Context<'a>,
|
ctx: &mut Context<'a>,
|
||||||
layout_interner: &mut STLayoutInterner<'a>,
|
layout_interner: &mut STLayoutInterner<'a>,
|
||||||
union_layout: UnionLayout<'a>,
|
union_layout: UnionLayout<'a>,
|
||||||
field_layouts: &'a [InLayout<'a>],
|
field_layouts: &'a [(usize, InLayout<'a>)],
|
||||||
structure: Symbol,
|
structure: Symbol,
|
||||||
tag_id: TagIdIntType,
|
tag_id: TagIdIntType,
|
||||||
following: Stmt<'a>,
|
following: Stmt<'a>,
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
let mut stmt = following;
|
let mut stmt = following;
|
||||||
|
|
||||||
for (i, field_layout) in field_layouts.iter().enumerate().rev() {
|
for (i, field_layout) in field_layouts.iter().rev() {
|
||||||
if layout_interner.contains_refcounted(*field_layout) {
|
if layout_interner.contains_refcounted(*field_layout) {
|
||||||
let field_val = root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
|
let field_val = root.create_symbol(ident_ids, &format!("field_{}_{}", tag_id, i));
|
||||||
let field_val_expr = Expr::UnionAtIndex {
|
let field_val_expr = Expr::UnionAtIndex {
|
||||||
union_layout,
|
union_layout,
|
||||||
tag_id,
|
tag_id,
|
||||||
index: i as u64,
|
index: *i as u64,
|
||||||
structure,
|
structure,
|
||||||
};
|
};
|
||||||
let field_val_stmt = |next| Stmt::Let(field_val, field_val_expr, *field_layout, next);
|
let field_val_stmt = |next| Stmt::Let(field_val, field_val_expr, *field_layout, next);
|
||||||
|
|
|
@ -2661,7 +2661,10 @@ impl<'a> Layout<'a> {
|
||||||
Layout::RecursivePointer(_) => {
|
Layout::RecursivePointer(_) => {
|
||||||
unreachable!("should be looked up to get an actual layout")
|
unreachable!("should be looked up to get an actual layout")
|
||||||
}
|
}
|
||||||
Layout::Boxed(inner) => Ord::max(ptr_width, interner.get(*inner).alignment_bytes(interner, target_info)),
|
Layout::Boxed(inner) => Ord::max(
|
||||||
|
ptr_width,
|
||||||
|
interner.get(*inner).alignment_bytes(interner, target_info),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,3 +496,33 @@ fn boxed_str_dec() {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-wasm"))]
|
||||||
|
fn non_nullable_unwrapped_alignment_8() {
|
||||||
|
assert_refcounts!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Expr : [ZAdd Expr Expr, Val I64, Var I64]
|
||||||
|
|
||||||
|
eval : Expr -> I64
|
||||||
|
eval = \e ->
|
||||||
|
when e is
|
||||||
|
Var _ -> 0
|
||||||
|
Val v -> v
|
||||||
|
ZAdd l r -> eval l + eval r
|
||||||
|
|
||||||
|
expr : Expr
|
||||||
|
expr = (ZAdd (Val 4) (Val 5))
|
||||||
|
|
||||||
|
eval expr
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
i64,
|
||||||
|
&[
|
||||||
|
Deallocated, // Val 4
|
||||||
|
Deallocated, // Val 5
|
||||||
|
Deallocated, // ZAdd _ _
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue