Repository: vercel/next.js
Pull request: Turbopack: use unsigned values for follower and upper edges

<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the PR.
- Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to understand the PR)
- When linking to a Slack thread, you might want to share details of the conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->


Closes PACK-4683

Changed files:
filename: turbopack/crates/turbo-tasks-backend/src/backend/operation/aggregation_update.rs
patch: @@ -1304,10 +1304,6 @@ impl AggregationUpdateQueue {
                         follower_in_upper = true;
                         return None;
                     };
-                    if old < 0 {
-                        follower_in_upper = true;
-                        return Some(old);
-                    }
                     if old == 1 {
                         keep_upper = true;
                         removed_uppers.push(upper_id);
@@ -1382,10 +1378,6 @@ impl AggregationUpdateQueue {
                             inner_in_upper = true;
                             return None;
                         };
-                        if old < 0 {
-                            inner_in_upper = true;
-                            return Some(old);
-                        }
                         if old == 1 {
                             removed_follower = true;
                             return None;
@@ -1409,7 +1401,7 @@ impl AggregationUpdateQueue {
                             task: lost_follower_id,
                         });
                     }
-                    // notify uppers about new follower
+                    // notify uppers about lost follower
                     if !upper_ids.is_empty() {
                         self.push(AggregationUpdateJob::InnerOfUppersLostFollower {
                             upper_ids,
@@ -1471,10 +1463,6 @@ impl AggregationUpdateQueue {
                         follower_in_upper = true;
                         return None;
                     };
-                    if old < 0 {
-                        follower_in_upper = true;
-                        return Some(old);
-                    }
                     if old == 1 {
                         remove_upper = true;
                         return None;
@@ -1543,10 +1531,6 @@ impl AggregationUpdateQueue {
                             inner_in_upper = true;
                             return None;
                         };
-                        if old < 0 {
-                            inner_in_upper = true;
-                            return Some(old);
-                        }
                         if old == 1 {
                             removed_follower = true;
                             return None;
@@ -1570,7 +1554,7 @@ impl AggregationUpdateQueue {
                             task: lost_follower_id,
                         });
                     }
-                    // notify uppers about new follower
+                    // notify uppers about lost follower
                     if !upper_ids.is_empty() {
                         self.push(AggregationUpdateJob::InnerOfUppersLostFollower {
                             upper_ids,
@@ -2461,7 +2445,7 @@ const MAX_YIELD_DURATION: Duration = Duration::from_millis(1);
 const MAX_RETRIES: u16 = 10000;
 
 /// Retry the passed function for a few milliseconds, while yielding to other threads.
-/// Returns an error if the function was not ablue to complete and the timeout was reached.
+/// Returns an error if the function was not able to complete and the timeout was reached.
 ///
 /// Each graph modification will only lock one or two tasks at a time, but updates usually also
 /// require follow-up updates to connected tasks. So an update will "slowly" propagate through the
@@ -2472,7 +2456,7 @@ const MAX_RETRIES: u16 = 10000;
 /// update yet). So we will retry (with this method) removals until the thing is there. So this is
 /// basically a busy loop that waits for the "add" update to complete. If the busy loop is not
 /// sucessful, the update is added to the end of the queue again. This is important as the "add"
-/// update might even be in the curreent thread and in the same queue. If that's the case yielding
+/// update might even be in the current thread and in the same queue. If that's the case yielding
 /// won't help and the update need to be requeued.
 fn retry_loop(mut f: impl FnMut() -> ControlFlow<()>) -> Result<(), RetryTimeout> {
     let mut time: Option<Instant> = None;

filename: turbopack/crates/turbo-tasks-backend/src/backend/storage.rs
patch: @@ -137,7 +137,7 @@ pub struct InnerStorageSnapshot {
     aggregation_number: OptionStorage<AggregationNumber>,
     output_dependent: AutoMapStorage<TaskId, ()>,
     output: OptionStorage<OutputValue>,
-    upper: AutoMapStorage<TaskId, i32>,
+    upper: AutoMapStorage<TaskId, u32>,
     dynamic: DynamicStorage,
     pub meta_modified: bool,
     pub data_modified: bool,
@@ -205,7 +205,7 @@ pub struct InnerStorage {
     aggregation_number: OptionStorage<AggregationNumber>,
     output_dependent: AutoMapStorage<TaskId, ()>,
     output: OptionStorage<OutputValue>,
-    upper: AutoMapStorage<TaskId, i32>,
+    upper: AutoMapStorage<TaskId, u32>,
     dynamic: DynamicStorage,
     state: InnerStorageState,
 }

filename: turbopack/crates/turbo-tasks-backend/src/data.rs
patch: @@ -421,11 +421,11 @@ pub enum CachedDataItem {
     },
     Follower {
         task: TaskId,
-        value: i32,
+        value: u32,
     },
     Upper {
         task: TaskId,
-        value: i32,
+        value: u32,
     },
 
     // Aggregated Data