Skip to content

fix: implement deallocation for fixed-length lists with heap elements#1538

Open
sumleo wants to merge 1 commit intobytecodealliance:mainfrom
sumleo:fix/fixed-length-list-dealloc
Open

fix: implement deallocation for fixed-length lists with heap elements#1538
sumleo wants to merge 1 commit intobytecodealliance:mainfrom
sumleo:fix/fixed-length-list-dealloc

Conversation

@sumleo
Copy link
Contributor

@sumleo sumleo commented Feb 12, 2026

Summary

  • The deallocate function in core ABI had a todo!() for FixedLengthList, panicking when flat deallocation was needed (e.g., list<own<resource>, 3>)
  • The deallocate_indirect function was a silent no-op (=> {}), leaking memory for fixed-length lists containing heap-allocated elements like strings or nested lists
  • For flat deallocation, reused flat_for_each_record_type with repeated element types to iterate and deallocate each element
  • For indirect deallocation, reused deallocate_indirect_fields with a vec of repeated element types to correctly compute memory offsets

Test plan

  • Added codegen test verifying cabi_post_ deallocation functions are generated for list<string, 3> exports
  • needs_deallocate already correctly returns true for fixed-length lists with complex elements — the fix ensures the deallocation instructions are actually emitted
  • All existing workspace tests pass

@sumleo sumleo force-pushed the fix/fixed-length-list-dealloc branch 2 times, most recently from 6f79a2d to f7b5b06 Compare February 12, 2026 13:44
Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! For testing this, could this be added to a tests/runtime/* test?

@sumleo sumleo force-pushed the fix/fixed-length-list-dealloc branch from f7b5b06 to 17933c5 Compare February 12, 2026 23:58
@sumleo
Copy link
Contributor Author

sumleo commented Feb 12, 2026

Done. Extended the existing tests/runtime/fixed-length-lists/ test with:

  • string-list-param, string-list-result, and string-list-roundtrip functions using list<string, N> in the WIT interface
  • Custom allocator (alloc.rs) in both test and runner components
  • allocated-bytes function to track heap allocation
  • Guard pattern in the runner to verify no memory leaks after each call

This exercises both the deallocate (flat) and deallocate_indirect (pointer-based) code paths for fixed-length lists with heap-allocated elements.

@sumleo sumleo force-pushed the fix/fixed-length-list-dealloc branch from 17933c5 to 9b20147 Compare February 13, 2026 14:38
"expected cabi_post_ deallocation function for fixed-length list \
with string elements, but none was generated"
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind dropping this test as well? This should be exercised by tests/runtime/fixed-length-lists and avoids trying to peek into the generated code like this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Removed the codegen test — the runtime tests now cover this with actual allocation tracking.

@cpetig
Copy link
Collaborator

cpetig commented Feb 13, 2026

I think this (at least partially as it doesn't fix c++ code) fixes #1501 .

Update: While the test for the new functionality is (incorrectly) tied to Rust, this could also fix the C++ code because of the change in abi.rs. I am positive but I wouldn't promise a full fix before I tested more.

assert_eq!(result, ([2.0, -42.0], [0.25, -0.125]));
}
{
let _guard = Guard::new();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these allocation guards test for a no-op (as there must be no allocations for any of the tested types), but they don't hurt either.

The list<string,3> test would become interesting with a guard though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Added list<string, 3> test functions (string-list-param, string-list-result, string-list-roundtrip) with Guards that actually exercise deallocation of heap-allocated elements.

@sumleo sumleo force-pushed the fix/fixed-length-list-dealloc branch 2 times, most recently from a14be8c to 922c9a7 Compare February 15, 2026 14:52
Fixed three bugs in the handling of FixedLengthList types:

1. `deallocate` in abi.rs was `todo!()`, causing a panic when flat
   deallocation was needed (e.g. `list<own<resource>, 3>`). Now uses
   `flat_for_each_record_type` to iterate element types.

2. `deallocate_indirect` in abi.rs was a silent no-op `=> {}`, leaking
   heap-allocated elements (e.g. strings in `list<string, 3>`). Now
   iterates each element's memory offset and deallocates using
   `deallocate_indirect_fields`.

3. `FixedLengthListLower` in the Rust code generator used array
   indexing (`a[0]`, `a[1]`, ...) to extract elements, which fails for
   non-Copy types like String. Changed to use array destructuring
   (`let [e0, e1, ...] = a;`) to properly move elements out.

Added runtime tests with `list<string, 3>` functions (param, result,
roundtrip) and allocation tracking via Guard pattern to verify no
memory leaks when passing/returning fixed-length lists of strings.
@sumleo sumleo force-pushed the fix/fixed-length-list-dealloc branch from 922c9a7 to d9baa75 Compare February 15, 2026 15:18
@alexcrichton alexcrichton added this pull request to the merge queue Feb 15, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants