-
Notifications
You must be signed in to change notification settings - Fork 50k
[compiler] Distingush optional/extraneous deps #35204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
842865e to
6bb6f89
Compare
In ValidateExhaustiveDependencies, I previously changed to allow extraneous dependencies as long as they were non-reactive. Here we make that more precise, and distinguish between values that are definitely referenced in the memo function but optional as dependencies vs values that are not even referenced in the memo function. The latter now error as extraneous even if they're non-reactive. This also turned up a case where constant-folded primitives could show up as false positives of the latter category, so now we track manual deps which quality for constant folding and don't error on them.
6bb6f89 to
87af9cd
Compare
| if ($[0] === Symbol.for("react.memo_cache_sentinel")) { | ||
| Component = Stringify; | ||
|
|
||
| Component; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like an existing bug where DCE isn't cleaning this up
| const isOptionalDependency = | ||
| !reactive.has(inferredDependency.identifier.id) && | ||
| (isStableType(inferredDependency.identifier) || | ||
| isPrimitiveType(inferredDependency.identifier)); | ||
| if (hasMatchingManualDependency || isOptionalDependency) { | ||
| continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this switches us back to special casing non-reactive deps allowed by exhaustive-deps rule.
This code should now bail out (right)?
hook useHook() {
const obj = {};
return useMemo(() => obj, []);
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tested in a follow-up
| /* | ||
| * Constant primitives can get constant-folded, which means we won't | ||
| * see a LoadLocal for the value within the memo function. | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense, thanks for the explanation
| const x = useMemo(() => { | ||
| return [state]; | ||
| // error: `setState` is a stable type, but not actually referenced | ||
| }, [state, setState]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
mofeiZ
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! Could we add something like this as a fixture?
// error.fixture
hook useHook() {
const obj = {};
return useMemo(() => obj, []);
}
// error.fixture2
hook useHook() {
// here, obj goes unmemoized
const obj = {};
useHook();
obj.x = 4;
return useMemo(() => obj, []);
}
In ValidateExhaustiveDependencies, I previously changed to allow extraneous dependencies as long as they were non-reactive. Here we make that more precise, and distinguish between values that are definitely referenced in the memo function but optional as dependencies vs values that are not even referenced in the memo function. The latter now error as extraneous even if they're non-reactive. This also turned up a case where constant-folded primitives could show up as false positives of the latter category, so now we track manual deps which quality for constant folding and don't error on them.
Stack created with Sapling. Best reviewed with ReviewStack.