Skip to content

Commit bc14bb2

Browse files
lukesandbergclaude
andcommitted
Drop output_dependent on immutable task completion
Immutable tasks never change their output, so their output_dependent set is dead weight after completion — no new readers are added (guarded by !task.immutable()) and no invalidation will ever traverse it. Extend the macro's cleanup_after_execution to support drop_on_completion_if_immutable on inline collection fields and apply it to output_dependent. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent db0fdc3 commit bc14bb2

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

turbopack/crates/turbo-tasks-backend/src/backend/storage_schema.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ struct TaskStorageSchema {
7474

7575
/// Tasks that depend on this task's output.
7676
77-
#[field(storage = "auto_set", category = "data", inline, filter_transient)]
77+
#[field(
78+
storage = "auto_set",
79+
category = "data",
80+
inline,
81+
filter_transient,
82+
drop_on_completion_if_immutable
83+
)]
7884
output_dependent: AutoSet<TaskId>,
7985

8086
/// The task's output value.

turbopack/crates/turbo-tasks-macros/src/derive/task_storage_macro.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,25 +2442,38 @@ fn generate_automap_ops(field: &FieldInfo) -> TokenStream {
24422442
/// 4. For fields with `shrink_on_completion`: shrink or remove if empty
24432443
/// 5. For fields with `drop_on_completion_if_immutable` when task is immutable: remove
24442444
fn generate_cleanup_after_execution(grouped_fields: &GroupedFields) -> TokenStream {
2445-
// Generate shrink calls for inline collection fields with shrink_on_completion
2446-
let mut inline_shrinks = Vec::new();
2445+
// Generate cleanup calls for inline collection fields
2446+
let mut inline_cleanups = Vec::new();
24472447
for field in grouped_fields.all_inline() {
24482448
if field.is_flag() {
24492449
continue;
24502450
}
2451-
if !field.shrink_on_completion {
2451+
let shrink = field.shrink_on_completion;
2452+
let drop_if_immutable = field.drop_on_completion_if_immutable;
2453+
if !shrink && !drop_if_immutable {
24522454
continue;
24532455
}
2454-
// Only collection types can be shrunk
2456+
// Only collection types can be shrunk/dropped
24552457
let is_collection = matches!(
24562458
field.storage_type,
24572459
StorageType::AutoSet | StorageType::AutoMap | StorageType::CounterMap
24582460
);
24592461
if is_collection {
24602462
let field_name = &field.field_name;
2461-
inline_shrinks.push(quote! {
2462-
typed.#field_name.shrink_to_fit();
2463-
});
2463+
let cleanup = match (shrink, drop_if_immutable) {
2464+
(_, true) => quote! {
2465+
if is_immutable {
2466+
typed.#field_name = Default::default();
2467+
} else {
2468+
typed.#field_name.shrink_to_fit();
2469+
}
2470+
},
2471+
(true, false) => quote! {
2472+
typed.#field_name.shrink_to_fit();
2473+
},
2474+
(false, false) => unreachable!(),
2475+
};
2476+
inline_cleanups.push(cleanup);
24642477
}
24652478
}
24662479

@@ -2551,8 +2564,8 @@ fn generate_cleanup_after_execution(grouped_fields: &GroupedFields) -> TokenStre
25512564
let typed = self.typed_mut();
25522565
let is_immutable = typed.flags.immutable();
25532566

2554-
// Shrink inline collection fields (always present, not in lazy vec)
2555-
#(#inline_shrinks)*
2567+
// Clean up inline collection fields (always present, not in lazy vec)
2568+
#(#inline_cleanups)*
25562569

25572570
// swap_retain pattern: iterate with manual index, swap_remove to delete
25582571
let mut i = 0;

0 commit comments

Comments
 (0)