Skip to content

Commit 0ff1515

Browse files
committed
[compiler] ValidatePreservedManualMemoization reports detailed errors
This pass didn't previously report the precise difference btw inferred/manual dependencies unless a debug flag was set. But the error message is really good (nice job mofeiz): the only catch is that in theory the inferred dep could be a temporary that can't trivially be reported to the user. But the messages are really useful for quickly verifying why the compiler couldn't preserve memoization. So here we switch to outputting a detailed message about the discrepancy btw inferred/manual deps so long as the inferred dep root is a named variable. I also slightly adjusted the message to handle the case where there is no diagnostic, which can occur if there were no manual deps but the compiler inferred a dependency. ghstack-source-id: 534f6f1 Pull Request resolved: #33095 DiffTrain build for [73d7e81](73d7e81)
1 parent 904f866 commit 0ff1515

35 files changed

+127
-90
lines changed

compiled/eslint-plugin-react-hooks/index.js

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50010,7 +50010,7 @@ class ReactiveScopeDependencyTreeHIR {
5001050010
depCursor = nextDepCursor;
5001150011
hoistableCursor = nextHoistableCursor;
5001250012
}
50013-
depCursor.accessType = merge(depCursor.accessType, PropertyAccessType.OptionalDependency);
50013+
depCursor.accessType = merge$1(depCursor.accessType, PropertyAccessType.OptionalDependency);
5001450014
}
5001550015
deriveMinimalDependencies() {
5001650016
const results = new Set();
@@ -50068,7 +50068,7 @@ function isDependency(access) {
5006850068
return (access === PropertyAccessType.OptionalDependency ||
5006950069
access === PropertyAccessType.UnconditionalDependency);
5007050070
}
50071-
function merge(access1, access2) {
50071+
function merge$1(access1, access2) {
5007250072
const resultIsUnconditional = !(isOptional(access1) && isOptional(access2));
5007350073
const resultIsDependency = isDependency(access1) || isDependency(access2);
5007450074
if (resultIsUnconditional) {
@@ -50125,7 +50125,7 @@ function makeOrMergeProperty(node, property, accessType) {
5012550125
node.properties.set(property, child);
5012650126
}
5012750127
else {
50128-
child.accessType = merge(child.accessType, accessType);
50128+
child.accessType = merge$1(child.accessType, accessType);
5012950129
}
5013050130
return child;
5013150131
}
@@ -53319,6 +53319,17 @@ function validatePreservedManualMemoization(fn) {
5331953319
visitReactiveFunction(fn, new Visitor(), state);
5332053320
return state.errors.asResult();
5332153321
}
53322+
function prettyPrintScopeDependency(val) {
53323+
var _a;
53324+
let rootStr;
53325+
if (((_a = val.identifier.name) === null || _a === void 0 ? void 0 : _a.kind) === 'named') {
53326+
rootStr = val.identifier.name.value;
53327+
}
53328+
else {
53329+
rootStr = '[unnamed]';
53330+
}
53331+
return `${rootStr}${val.path.map(v => `${v.optional ? '?.' : '.'}${v.property}`).join('')}`;
53332+
}
5332253333
var CompareDependencyResult;
5332353334
(function (CompareDependencyResult) {
5332453335
CompareDependencyResult[CompareDependencyResult["Ok"] = 0] = "Ok";
@@ -53327,6 +53338,22 @@ var CompareDependencyResult;
5332753338
CompareDependencyResult[CompareDependencyResult["Subpath"] = 3] = "Subpath";
5332853339
CompareDependencyResult[CompareDependencyResult["RefAccessDifference"] = 4] = "RefAccessDifference";
5332953340
})(CompareDependencyResult || (CompareDependencyResult = {}));
53341+
function merge(a, b) {
53342+
return Math.max(a, b);
53343+
}
53344+
function getCompareDependencyResultDescription(result) {
53345+
switch (result) {
53346+
case CompareDependencyResult.Ok:
53347+
return 'Dependencies equal';
53348+
case CompareDependencyResult.RootDifference:
53349+
case CompareDependencyResult.PathDifference:
53350+
return 'Inferred different dependency than source';
53351+
case CompareDependencyResult.RefAccessDifference:
53352+
return 'Differences in ref.current access';
53353+
case CompareDependencyResult.Subpath:
53354+
return 'Inferred less specific property than source';
53355+
}
53356+
}
5333053357
function compareDeps(inferred, source) {
5333153358
const rootsEqual = (inferred.root.kind === 'Global' &&
5333253359
source.root.kind === 'Global' &&
@@ -53404,16 +53431,26 @@ function validateInferredDep(dep, temporaries, declsWithinMemoBlock, validDepsIn
5340453431
return;
5340553432
}
5340653433
}
53434+
let errorDiagnostic = null;
5340753435
for (const originalDep of validDepsInMemoBlock) {
5340853436
const compareResult = compareDeps(normalizedDep, originalDep);
5340953437
if (compareResult === CompareDependencyResult.Ok) {
5341053438
return;
5341153439
}
53440+
else {
53441+
errorDiagnostic = merge(errorDiagnostic !== null && errorDiagnostic !== void 0 ? errorDiagnostic : compareResult, compareResult);
53442+
}
5341253443
}
5341353444
errorState.push({
5341453445
severity: ErrorSeverity.CannotPreserveMemoization,
5341553446
reason: 'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected',
53416-
description: null,
53447+
description: (dep.identifier.name != null && dep.identifier.name.kind === 'named')
53448+
? `The inferred dependency was \`${prettyPrintScopeDependency(dep)}\`, but the source dependencies were [${validDepsInMemoBlock
53449+
.map(dep => printManualMemoDependency(dep, true))
53450+
.join(', ')}]. ${errorDiagnostic
53451+
? getCompareDependencyResultDescription(errorDiagnostic)
53452+
: 'Inferred dependency not present in source'}`
53453+
: null,
5341753454
loc: memoLocation,
5341853455
suggestions: null,
5341953456
});

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ac2cae524576b8091a6d78d9ab05627053949df1
1+
73d7e816b7746c700ab843964aaf11c17351fac1
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ac2cae524576b8091a6d78d9ab05627053949df1
1+
73d7e816b7746c700ab843964aaf11c17351fac1

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ __DEV__ &&
15381538
exports.useTransition = function () {
15391539
return resolveDispatcher().useTransition();
15401540
};
1541-
exports.version = "19.2.0-www-classic-ac2cae52-20250503";
1541+
exports.version = "19.2.0-www-classic-73d7e816-20250503";
15421542
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15431543
"function" ===
15441544
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ __DEV__ &&
15381538
exports.useTransition = function () {
15391539
return resolveDispatcher().useTransition();
15401540
};
1541-
exports.version = "19.2.0-www-modern-ac2cae52-20250503";
1541+
exports.version = "19.2.0-www-modern-73d7e816-20250503";
15421542
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15431543
"function" ===
15441544
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,4 @@ exports.useSyncExternalStore = function (
636636
exports.useTransition = function () {
637637
return ReactSharedInternals.H.useTransition();
638638
};
639-
exports.version = "19.2.0-www-classic-ac2cae52-20250503";
639+
exports.version = "19.2.0-www-classic-73d7e816-20250503";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,4 @@ exports.useSyncExternalStore = function (
636636
exports.useTransition = function () {
637637
return ReactSharedInternals.H.useTransition();
638638
};
639-
exports.version = "19.2.0-www-modern-ac2cae52-20250503";
639+
exports.version = "19.2.0-www-modern-73d7e816-20250503";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ exports.useSyncExternalStore = function (
640640
exports.useTransition = function () {
641641
return ReactSharedInternals.H.useTransition();
642642
};
643-
exports.version = "19.2.0-www-classic-ac2cae52-20250503";
643+
exports.version = "19.2.0-www-classic-73d7e816-20250503";
644644
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
645645
"function" ===
646646
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ exports.useSyncExternalStore = function (
640640
exports.useTransition = function () {
641641
return ReactSharedInternals.H.useTransition();
642642
};
643-
exports.version = "19.2.0-www-modern-ac2cae52-20250503";
643+
exports.version = "19.2.0-www-modern-73d7e816-20250503";
644644
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
645645
"function" ===
646646
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19014,10 +19014,10 @@ __DEV__ &&
1901419014
(function () {
1901519015
var internals = {
1901619016
bundleType: 1,
19017-
version: "19.2.0-www-classic-ac2cae52-20250503",
19017+
version: "19.2.0-www-classic-73d7e816-20250503",
1901819018
rendererPackageName: "react-art",
1901919019
currentDispatcherRef: ReactSharedInternals,
19020-
reconcilerVersion: "19.2.0-www-classic-ac2cae52-20250503"
19020+
reconcilerVersion: "19.2.0-www-classic-73d7e816-20250503"
1902119021
};
1902219022
internals.overrideHookState = overrideHookState;
1902319023
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -19051,7 +19051,7 @@ __DEV__ &&
1905119051
exports.Shape = Shape;
1905219052
exports.Surface = Surface;
1905319053
exports.Text = Text;
19054-
exports.version = "19.2.0-www-classic-ac2cae52-20250503";
19054+
exports.version = "19.2.0-www-classic-73d7e816-20250503";
1905519055
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1905619056
"function" ===
1905719057
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)