-
Notifications
You must be signed in to change notification settings - Fork 47.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[compiler] Repro for aliased captures within inner function expressio…
…ns (#31770) see fixture
- Loading branch information
Showing
3 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
129 changes: 129 additions & 0 deletions
129
...sts__/fixtures/compiler/bug-capturing-func-maybealias-captured-mutate.expect.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
|
||
## Input | ||
|
||
```javascript | ||
import {makeArray, mutate} from 'shared-runtime'; | ||
|
||
/** | ||
* Bug repro: | ||
* Found differences in evaluator results | ||
* Non-forget (expected): | ||
* (kind: ok) | ||
* {"bar":4,"x":{"foo":3,"wat0":"joe"}} | ||
* {"bar":5,"x":{"foo":3,"wat0":"joe"}} | ||
* Forget: | ||
* (kind: ok) | ||
* {"bar":4,"x":{"foo":3,"wat0":"joe"}} | ||
* {"bar":5,"x":{"foo":3,"wat0":"joe","wat1":"joe"}} | ||
* | ||
* Fork of `capturing-func-alias-captured-mutate`, but instead of directly | ||
* aliasing `y` via `[y]`, we make an opaque call. | ||
* | ||
* Note that the bug here is that we don't infer that `a = makeArray(y)` | ||
* potentially captures a context variable into a local variable. As a result, | ||
* we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're | ||
* currently inferring that this lambda captures `y` (for a potential later | ||
* mutation) and simply reads `x`. | ||
* | ||
* Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not | ||
* used when we analyze CallExpressions. | ||
*/ | ||
function Component({foo, bar}: {foo: number; bar: number}) { | ||
let x = {foo}; | ||
let y: {bar: number; x?: {foo: number}} = {bar}; | ||
const f0 = function () { | ||
let a = makeArray(y); // a = [y] | ||
let b = x; | ||
// this writes y.x = x | ||
a[0].x = b; | ||
}; | ||
f0(); | ||
mutate(y.x); | ||
return y; | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: Component, | ||
params: [{foo: 3, bar: 4}], | ||
sequentialRenders: [ | ||
{foo: 3, bar: 4}, | ||
{foo: 3, bar: 5}, | ||
], | ||
}; | ||
|
||
``` | ||
|
||
## Code | ||
|
||
```javascript | ||
import { c as _c } from "react/compiler-runtime"; | ||
import { makeArray, mutate } from "shared-runtime"; | ||
|
||
/** | ||
* Bug repro: | ||
* Found differences in evaluator results | ||
* Non-forget (expected): | ||
* (kind: ok) | ||
* {"bar":4,"x":{"foo":3,"wat0":"joe"}} | ||
* {"bar":5,"x":{"foo":3,"wat0":"joe"}} | ||
* Forget: | ||
* (kind: ok) | ||
* {"bar":4,"x":{"foo":3,"wat0":"joe"}} | ||
* {"bar":5,"x":{"foo":3,"wat0":"joe","wat1":"joe"}} | ||
* | ||
* Fork of `capturing-func-alias-captured-mutate`, but instead of directly | ||
* aliasing `y` via `[y]`, we make an opaque call. | ||
* | ||
* Note that the bug here is that we don't infer that `a = makeArray(y)` | ||
* potentially captures a context variable into a local variable. As a result, | ||
* we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're | ||
* currently inferring that this lambda captures `y` (for a potential later | ||
* mutation) and simply reads `x`. | ||
* | ||
* Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not | ||
* used when we analyze CallExpressions. | ||
*/ | ||
function Component(t0) { | ||
const $ = _c(5); | ||
const { foo, bar } = t0; | ||
let t1; | ||
if ($[0] !== foo) { | ||
t1 = { foo }; | ||
$[0] = foo; | ||
$[1] = t1; | ||
} else { | ||
t1 = $[1]; | ||
} | ||
const x = t1; | ||
let y; | ||
if ($[2] !== bar || $[3] !== x) { | ||
y = { bar }; | ||
const f0 = function () { | ||
const a = makeArray(y); | ||
const b = x; | ||
|
||
a[0].x = b; | ||
}; | ||
|
||
f0(); | ||
mutate(y.x); | ||
$[2] = bar; | ||
$[3] = x; | ||
$[4] = y; | ||
} else { | ||
y = $[4]; | ||
} | ||
return y; | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: Component, | ||
params: [{ foo: 3, bar: 4 }], | ||
sequentialRenders: [ | ||
{ foo: 3, bar: 4 }, | ||
{ foo: 3, bar: 5 }, | ||
], | ||
}; | ||
|
||
``` | ||
48 changes: 48 additions & 0 deletions
48
...compiler/src/__tests__/fixtures/compiler/bug-capturing-func-maybealias-captured-mutate.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import {makeArray, mutate} from 'shared-runtime'; | ||
|
||
/** | ||
* Bug repro: | ||
* Found differences in evaluator results | ||
* Non-forget (expected): | ||
* (kind: ok) | ||
* {"bar":4,"x":{"foo":3,"wat0":"joe"}} | ||
* {"bar":5,"x":{"foo":3,"wat0":"joe"}} | ||
* Forget: | ||
* (kind: ok) | ||
* {"bar":4,"x":{"foo":3,"wat0":"joe"}} | ||
* {"bar":5,"x":{"foo":3,"wat0":"joe","wat1":"joe"}} | ||
* | ||
* Fork of `capturing-func-alias-captured-mutate`, but instead of directly | ||
* aliasing `y` via `[y]`, we make an opaque call. | ||
* | ||
* Note that the bug here is that we don't infer that `a = makeArray(y)` | ||
* potentially captures a context variable into a local variable. As a result, | ||
* we don't understand that `a[0].x = b` captures `x` into `y` -- instead, we're | ||
* currently inferring that this lambda captures `y` (for a potential later | ||
* mutation) and simply reads `x`. | ||
* | ||
* Concretely `InferReferenceEffects.hasContextRefOperand` is incorrectly not | ||
* used when we analyze CallExpressions. | ||
*/ | ||
function Component({foo, bar}: {foo: number; bar: number}) { | ||
let x = {foo}; | ||
let y: {bar: number; x?: {foo: number}} = {bar}; | ||
const f0 = function () { | ||
let a = makeArray(y); // a = [y] | ||
let b = x; | ||
// this writes y.x = x | ||
a[0].x = b; | ||
}; | ||
f0(); | ||
mutate(y.x); | ||
return y; | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: Component, | ||
params: [{foo: 3, bar: 4}], | ||
sequentialRenders: [ | ||
{foo: 3, bar: 4}, | ||
{foo: 3, bar: 5}, | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters