mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[compiler][fixtures] Bug repros: codegen, alignScope, phis
[ghstack-poisoned]
This commit is contained in:
+92
@@ -0,0 +1,92 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { makeArray, print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* Exposes bug involving iife inlining + codegen.
|
||||
* We currently inline iifes to labeled blocks (not value-blocks).
|
||||
*
|
||||
* Here, print(1) and the evaluation of makeArray(...) get the same scope
|
||||
* as the compiler infers that the makeArray call may mutate its arguments.
|
||||
* Since print(1) does not get its own scope (and is thus not a declaration
|
||||
* or dependency), it does not get promoted.
|
||||
* As a result, print(1) gets reordered across the labeled-block instructions
|
||||
* to be inlined at the makeArray callsite.
|
||||
*
|
||||
* Current evaluator results:
|
||||
* Found differences in evaluator results
|
||||
* Non-forget (expected):
|
||||
* (kind: ok) [null,2]
|
||||
* logs: [1,2]
|
||||
* Forget:
|
||||
* (kind: ok) [null,2]
|
||||
* logs: [2,1]
|
||||
*/
|
||||
function useTest() {
|
||||
return makeArray<number | void>(
|
||||
print(1),
|
||||
(function foo() {
|
||||
print(2);
|
||||
return 2;
|
||||
})()
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useTest,
|
||||
params: [],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { makeArray, print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* Exposes bug involving iife inlining + codegen.
|
||||
* We currently inline iifes to labeled blocks (not value-blocks).
|
||||
*
|
||||
* Here, print(1) and the evaluation of makeArray(...) get the same scope
|
||||
* as the compiler infers that the makeArray call may mutate its arguments.
|
||||
* Since print(1) does not get its own scope (and is thus not a declaration
|
||||
* or dependency), it does not get promoted.
|
||||
* As a result, print(1) gets reordered across the labeled-block instructions
|
||||
* to be inlined at the makeArray callsite.
|
||||
*
|
||||
* Current evaluator results:
|
||||
* Found differences in evaluator results
|
||||
* Non-forget (expected):
|
||||
* (kind: ok) [null,2]
|
||||
* logs: [1,2]
|
||||
* Forget:
|
||||
* (kind: ok) [null,2]
|
||||
* logs: [2,1]
|
||||
*/
|
||||
function useTest() {
|
||||
const $ = _c(1);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
let t1;
|
||||
|
||||
print(2);
|
||||
t1 = 2;
|
||||
t0 = makeArray(print(1), t1);
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useTest,
|
||||
params: [],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import { makeArray, print } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* Exposes bug involving iife inlining + codegen.
|
||||
* We currently inline iifes to labeled blocks (not value-blocks).
|
||||
*
|
||||
* Here, print(1) and the evaluation of makeArray(...) get the same scope
|
||||
* as the compiler infers that the makeArray call may mutate its arguments.
|
||||
* Since print(1) does not get its own scope (and is thus not a declaration
|
||||
* or dependency), it does not get promoted.
|
||||
* As a result, print(1) gets reordered across the labeled-block instructions
|
||||
* to be inlined at the makeArray callsite.
|
||||
*
|
||||
* Current evaluator results:
|
||||
* Found differences in evaluator results
|
||||
* Non-forget (expected):
|
||||
* (kind: ok) [null,2]
|
||||
* logs: [1,2]
|
||||
* Forget:
|
||||
* (kind: ok) [null,2]
|
||||
* logs: [2,1]
|
||||
*/
|
||||
function useTest() {
|
||||
return makeArray<number | void>(
|
||||
print(1),
|
||||
(function foo() {
|
||||
print(2);
|
||||
return 2;
|
||||
})()
|
||||
);
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useTest,
|
||||
params: [],
|
||||
};
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { arrayPush } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* Evaluator error:
|
||||
* Found differences in evaluator results
|
||||
* Non-forget (expected):
|
||||
* (kind: ok) [2]
|
||||
* [2]
|
||||
* Forget:
|
||||
* (kind: ok) [2]
|
||||
* [2,2]
|
||||
*/
|
||||
function Foo(cond) {
|
||||
let x = null;
|
||||
if (cond) {
|
||||
x = [];
|
||||
} else {
|
||||
}
|
||||
// Here, x = phi(x$null, x$[]) does not receive the correct ValueKind
|
||||
arrayPush(x, 2);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{ cond: true }],
|
||||
sequentialRenders: [{ cond: true }, { cond: true }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { arrayPush } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* Evaluator error:
|
||||
* Found differences in evaluator results
|
||||
* Non-forget (expected):
|
||||
* (kind: ok) [2]
|
||||
* [2]
|
||||
* Forget:
|
||||
* (kind: ok) [2]
|
||||
* [2,2]
|
||||
*/
|
||||
function Foo(cond) {
|
||||
const $ = _c(1);
|
||||
let x = null;
|
||||
if (cond) {
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = [];
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
x = t0;
|
||||
}
|
||||
|
||||
arrayPush(x, 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{ cond: true }],
|
||||
sequentialRenders: [{ cond: true }, { cond: true }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { arrayPush } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* Evaluator error:
|
||||
* Found differences in evaluator results
|
||||
* Non-forget (expected):
|
||||
* (kind: ok) [2]
|
||||
* [2]
|
||||
* Forget:
|
||||
* (kind: ok) [2]
|
||||
* [2,2]
|
||||
*/
|
||||
function Foo(cond) {
|
||||
let x = null;
|
||||
if (cond) {
|
||||
x = [];
|
||||
} else {
|
||||
}
|
||||
// Here, x = phi(x$null, x$[]) does not receive the correct ValueKind
|
||||
arrayPush(x, 2);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Foo,
|
||||
params: [{ cond: true }],
|
||||
sequentialRenders: [{ cond: true }, { cond: true }],
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Similar fixture to `error.todo-align-scopes-nested-block-structure`, but
|
||||
* a simpler case.
|
||||
*/
|
||||
function useFoo(cond) {
|
||||
let s = null;
|
||||
if (cond) {
|
||||
s = {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
mutate(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Invariant: Invalid nesting in program blocks or scopes. Items overlap but are not nested: 4:10(5:13)
|
||||
```
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Similar fixture to `error.todo-align-scopes-nested-block-structure`, but
|
||||
* a simpler case.
|
||||
*/
|
||||
function useFoo(cond) {
|
||||
let s = null;
|
||||
if (cond) {
|
||||
s = {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
mutate(s);
|
||||
return s;
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Fixture showing that it's not sufficient to only align direct scoped
|
||||
* accesses of a block-fallthrough pair.
|
||||
* Below is a simplified view of HIR blocks in this fixture.
|
||||
* Note that here, s is mutated in both bb1 and bb4. However, neither
|
||||
* bb1 nor bb4 have terminal fallthroughs or are fallthroughs themselves.
|
||||
*
|
||||
* This means that we need to recursively visit all scopes accessed between
|
||||
* a block and its fallthrough and extend the range of those scopes which overlap
|
||||
* with an active block/fallthrough pair,
|
||||
*
|
||||
* bb0
|
||||
* ┌──────────────┐
|
||||
* │let s = null │
|
||||
* │test cond1 │
|
||||
* │ <fallthr=bb3>│
|
||||
* └┬─────────────┘
|
||||
* │ bb1
|
||||
* ├─►┌───────┐
|
||||
* │ │s = {} ├────┐
|
||||
* │ └───────┘ │
|
||||
* │ bb2 │
|
||||
* └─►┌───────┐ │
|
||||
* │return;│ │
|
||||
* └───────┘ │
|
||||
* bb3 │
|
||||
* ┌──────────────┐◄┘
|
||||
* │test cond2 │
|
||||
* │ <fallthr=bb5>│
|
||||
* └┬─────────────┘
|
||||
* │ bb4
|
||||
* ├─►┌─────────┐
|
||||
* │ │mutate(s)├─┐
|
||||
* ▼ └─────────┘ │
|
||||
* bb5 │
|
||||
* ┌───────────┐ │
|
||||
* │return s; │◄──┘
|
||||
* └───────────┘
|
||||
*/
|
||||
function useFoo(cond1, cond2) {
|
||||
let s = null;
|
||||
if (cond1) {
|
||||
s = {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cond2) {
|
||||
mutate(s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Invariant: Invalid nesting in program blocks or scopes. Items overlap but are not nested: 4:10(5:15)
|
||||
```
|
||||
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Fixture showing that it's not sufficient to only align direct scoped
|
||||
* accesses of a block-fallthrough pair.
|
||||
* Below is a simplified view of HIR blocks in this fixture.
|
||||
* Note that here, s is mutated in both bb1 and bb4. However, neither
|
||||
* bb1 nor bb4 have terminal fallthroughs or are fallthroughs themselves.
|
||||
*
|
||||
* This means that we need to recursively visit all scopes accessed between
|
||||
* a block and its fallthrough and extend the range of those scopes which overlap
|
||||
* with an active block/fallthrough pair,
|
||||
*
|
||||
* bb0
|
||||
* ┌──────────────┐
|
||||
* │let s = null │
|
||||
* │test cond1 │
|
||||
* │ <fallthr=bb3>│
|
||||
* └┬─────────────┘
|
||||
* │ bb1
|
||||
* ├─►┌───────┐
|
||||
* │ │s = {} ├────┐
|
||||
* │ └───────┘ │
|
||||
* │ bb2 │
|
||||
* └─►┌───────┐ │
|
||||
* │return;│ │
|
||||
* └───────┘ │
|
||||
* bb3 │
|
||||
* ┌──────────────┐◄┘
|
||||
* │test cond2 │
|
||||
* │ <fallthr=bb5>│
|
||||
* └┬─────────────┘
|
||||
* │ bb4
|
||||
* ├─►┌─────────┐
|
||||
* │ │mutate(s)├─┐
|
||||
* ▼ └─────────┘ │
|
||||
* bb5 │
|
||||
* ┌───────────┐ │
|
||||
* │return s; │◄──┘
|
||||
* └───────────┘
|
||||
*/
|
||||
function useFoo(cond1, cond2) {
|
||||
let s = null;
|
||||
if (cond1) {
|
||||
s = {};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cond2) {
|
||||
mutate(s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -488,6 +488,8 @@ const skipFilter = new Set([
|
||||
"bug-invalid-hoisting-functionexpr",
|
||||
"original-reactive-scopes-fork/bug-nonmutating-capture-in-unsplittable-memo-block",
|
||||
"original-reactive-scopes-fork/bug-hoisted-declaration-with-scope",
|
||||
"bug-codegen-inline-iife",
|
||||
"bug-phi-reference-effect",
|
||||
|
||||
// 'react-compiler-runtime' not yet supported
|
||||
"flag-enable-emit-hook-guards",
|
||||
|
||||
Reference in New Issue
Block a user