mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[effects] Allow capture-store effects in rvals
--- Some typed functions need to annotate callees or arguments as `Effect.Store`. This PR modifies alias analysis (`InferAliasForStores`) to account for this
This commit is contained in:
@@ -159,7 +159,7 @@ addObject(BUILTIN_SHAPES, BuiltInArrayId, [
|
||||
positionalParams: [],
|
||||
restParam: Effect.Capture,
|
||||
returnType: PRIMITIVE_TYPE,
|
||||
calleeEffect: Effect.Mutate,
|
||||
calleeEffect: Effect.Store,
|
||||
}),
|
||||
],
|
||||
// TODO: rest of Array properties
|
||||
|
||||
@@ -25,7 +25,15 @@ export function inferAliasForStores(
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
for (const instr of block.instructions) {
|
||||
const { value, lvalue } = instr;
|
||||
if (lvalue.effect !== Effect.Store) {
|
||||
const isStore =
|
||||
lvalue.effect === Effect.Store ||
|
||||
// Some typed functions annotate callees or arguments
|
||||
// as Effect.Store.
|
||||
![...eachInstructionValueOperand(value)].every(
|
||||
(operand) => operand.effect !== Effect.Store
|
||||
);
|
||||
|
||||
if (!isStore) {
|
||||
continue;
|
||||
}
|
||||
for (const operand of eachInstructionLValue(instr)) {
|
||||
|
||||
@@ -323,6 +323,20 @@ class InferenceState {
|
||||
break;
|
||||
}
|
||||
case Effect.Store: {
|
||||
if (
|
||||
valueKind !== ValueKind.Mutable &&
|
||||
valueKind !== ValueKind.Context &&
|
||||
shouldError
|
||||
) {
|
||||
CompilerError.invalidInput(
|
||||
`InferReferenceEffects: inferred mutation of known immutable value`,
|
||||
place.loc,
|
||||
`Found mutation of ${printIdentifier(place.identifier)}${printType(
|
||||
place.identifier.type
|
||||
)} (${valueKind})`
|
||||
);
|
||||
}
|
||||
|
||||
// TODO(gsn): This should be bailout once we add bailout infra.
|
||||
//
|
||||
// invariant(
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
// a's mutable range should be the same as x's mutable range,
|
||||
// since a is captured into x (which gets mutated later)
|
||||
let a = someObj();
|
||||
|
||||
let x = [];
|
||||
x.push(a);
|
||||
|
||||
mutate(x);
|
||||
return [x, a];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component() {
|
||||
const $ = useMemoCache(3);
|
||||
let x;
|
||||
let a;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
a = someObj();
|
||||
|
||||
x = [];
|
||||
x.push(a);
|
||||
|
||||
mutate(x);
|
||||
$[0] = x;
|
||||
$[1] = a;
|
||||
} else {
|
||||
x = $[0];
|
||||
a = $[1];
|
||||
}
|
||||
let t0;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = [x, a];
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
function Component() {
|
||||
// a's mutable range should be the same as x's mutable range,
|
||||
// since a is captured into x (which gets mutated later)
|
||||
let a = someObj();
|
||||
|
||||
let x = [];
|
||||
x.push(a);
|
||||
|
||||
mutate(x);
|
||||
return [x, a];
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
// a's mutable range should be limited
|
||||
// the following line
|
||||
let a = someObj();
|
||||
|
||||
let x = [];
|
||||
x.push(a);
|
||||
|
||||
return [x, a];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component() {
|
||||
const $ = useMemoCache(3);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = someObj();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const a = t0;
|
||||
let x;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = [];
|
||||
x.push(a);
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
let t1;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = [x, a];
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component() {
|
||||
// a's mutable range should be limited
|
||||
// the following line
|
||||
let a = someObj();
|
||||
|
||||
let x = [];
|
||||
x.push(a);
|
||||
|
||||
return [x, a];
|
||||
}
|
||||
Reference in New Issue
Block a user