Skip to content

Optimize encoding and decoding of Vec<T> when T is trivial#7582

Draft
ironcev wants to merge 2 commits intomasterfrom
ironcev/optimize-vec-encoding-decoding
Draft

Optimize encoding and decoding of Vec<T> when T is trivial#7582
ironcev wants to merge 2 commits intomasterfrom
ironcev/optimize-vec-encoding-decoding

Conversation

@ironcev
Copy link
Member

@ironcev ironcev commented Mar 26, 2026

Description

This PR optimizes the encoding and decoding of std::vec::Vec::<T> when T is a trivially encodable and decodable type. In that case, we don't have encode each element individually, but just encode the vector's length and mem-copy its content to the Buffer.

Checklist

  • I have linked to any relevant issues.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation where relevant (API docs, the reference, and the Sway book).
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added (or requested a maintainer to add) the necessary Breaking* or New Feature labels where relevant.
  • I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
  • I have requested a review from the relevant team or maintainers.

@ironcev ironcev self-assigned this Mar 26, 2026
@cursor
Copy link

cursor bot commented Mar 26, 2026

PR Summary

High Risk
Changes Vec<T> ABI encoding/decoding behavior for trivially (de)codable element types, which can affect wire format compatibility and contract/script return data expectations. Updates and replaces e2e tests accordingly, so regressions would surface as ABI mismatches rather than compile-time errors.

Overview
Optimizes Vec<T> ABI (de)serialization by branching on element triviality. Vec<T>::abi_encode / abi_decode now detect when T is trivially encodable/decodable and take a different path, falling back to the previous per-element length+loop encoding for non-trivial T.

Adjusts coverage and fixtures for the new behavior. Removes the older raw_ptr/vec_ret run test and adds a new stdlib/vec_encoding_decoding test program (with updated Forc metadata and run/unit test configs) that exercises trivial vs non-trivial vectors and nested vectors under the new encoding expectations.

Written by Cursor Bugbot for commit eb09491. This will update automatically on new commits. Configure here.

@ironcev ironcev added lib: std Standard library performance Everything related to performance, speed wise or memory wise. labels Mar 26, 2026
@ironcev
Copy link
Member Author

ironcev commented Mar 26, 2026

👍

@ironcev ironcev deployed to fuel-sway-bot March 26, 2026 07:20 — with GitHub Actions Active
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

let encoded_decoded: Vec<u64> = abi_decode(encoded_as_alias);
assert_eq(encoded_decoded, vec);

log(encoded_decoded);
Copy link

Choose a reason for hiding this comment

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

Test vec_non_trivial incorrectly tests trivial path instead

Medium Severity

The vec_non_trivial test calls create_vec_trivial(10) and uses Vec<u64>, making it an exact duplicate of vec_trivial. It was clearly intended to call create_vec_non_trivial(10) and use Vec<u32> (the non-trivial type, since u32 has is_encode_trivial() -> false). This means the non-trivial encoding/decoding path for flat Vec<u32> has no unit test coverage. Compare with nested_vec_non_trivial which correctly uses create_nested_vec_non_trivial and Vec<Vec<u32>>.

Fix in Cursor Fix in Web

category = "run"

script_data_new_encoding = "0000000000000003000000000000007c000000000000007c000000000000007c 00000000000000030000007c0000007c0000007c"
expected_result_new_encoding = { action = "return_data", value = "0000000000000006000000000000007c000000000000007c000000000000007c000000000000007c000000000000007c000000000000007c 00000000000000060000007c0000007c0000007c0000007c0000007c0000007c" }
Copy link

Choose a reason for hiding this comment

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

Script test data incompatible with new trivial encoding format

High Severity

The script_data_new_encoding encodes Vec<u64> with an element-count length prefix (0000000000000003 = 3), but the new trivial decode path uses raw_slice::abi_decode which interprets the prefix as a byte count. For 3 u64 elements the byte count needs to be 24 (0x18). Reading only 3 bytes produces a Vec with len = 3/8 = 0, causing the assert_eq(trivial.len(), 3) in main to fail. The expected_result_new_encoding has the same mismatch (uses 6 instead of 48).

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib: std Standard library performance Everything related to performance, speed wise or memory wise.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants