mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Throw CompilerError (todo) for unused conditional/logical
If a logical or conditional expression is unused, then a phi node isn't created for the identifier it assigns to. Then when we leave SSA form the two branches will assign to separate values, and we aren't sure which identifier to use as the lvalue of the resulting ReactiveInstruction (remember that logicals/conditionals decompose into control flow in HIR, but are a single compound instruction in ReactiveFunction). If the two sides don't assign to the same location, it could be because of a bug in the compiler or because the value wasn't used. Ideally we'd represent this explicitly, but for now i'm just making this a TODO since most logicals/conditionals should have their value used.
This commit is contained in:
@@ -115,6 +115,19 @@ export class CompilerError extends Error {
|
||||
throw errors;
|
||||
}
|
||||
|
||||
static todo(reason: string, loc: SourceLocation): never {
|
||||
const errors = new CompilerError();
|
||||
errors.pushErrorDetail(
|
||||
new CompilerErrorDetail({
|
||||
codeframe: null,
|
||||
loc: typeof loc === "symbol" ? null : loc,
|
||||
reason,
|
||||
severity: ErrorSeverity.Todo,
|
||||
})
|
||||
);
|
||||
throw errors;
|
||||
}
|
||||
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
@@ -681,10 +682,12 @@ class Driver {
|
||||
testBlock.terminal.alternate,
|
||||
terminal.loc
|
||||
);
|
||||
invariant(
|
||||
leftFinal.place.identifier === right.place.identifier,
|
||||
"Expected the left and right side of a logical expression to store a value to the same place"
|
||||
);
|
||||
if (leftFinal.place.identifier !== right.place.identifier) {
|
||||
CompilerError.todo(
|
||||
"TODO: Support LogicalExpression whose value is unused",
|
||||
leftFinal.place.loc
|
||||
);
|
||||
}
|
||||
const value: ReactiveLogicalValue = {
|
||||
kind: "LogicalExpression",
|
||||
operator: terminal.operator,
|
||||
@@ -722,10 +725,13 @@ class Driver {
|
||||
alternate: alternate.value,
|
||||
loc: terminal.loc,
|
||||
};
|
||||
invariant(
|
||||
consequent.place.identifier === alternate.place.identifier,
|
||||
"Expected the consequent and alternate of a ternary to store a value to the same place"
|
||||
);
|
||||
if (consequent.place.identifier !== alternate.place.identifier) {
|
||||
CompilerError.todo(
|
||||
"TODO: Support ConditionalExpression whose value is unused",
|
||||
consequent.place.loc
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
place: { ...consequent.place },
|
||||
value,
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
let x = 0;
|
||||
(x = 1) && (x = 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] Todo: TODO: Support LogicalExpression whose value is unused (3:3)
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
function Component(props) {
|
||||
let x = 0;
|
||||
(x = 1) && (x = 2);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
let x = 0;
|
||||
props.cond ? (x = 1) : (x = 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] Todo: TODO: Support ConditionalExpression whose value is unused (3:3)
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
function Component(props) {
|
||||
let x = 0;
|
||||
props.cond ? (x = 1) : (x = 2);
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user