Repository: facebook/react
Pull request: feat(compiler): implement constant folding for unary minus

## Summary
`-constant` is represented as a `UnaryExpression` node that is currently not part of constant folding. If the operand is a constant number, the node is folded to `constant * -1`. This also coerces `-0` to `0`, resulting in `0 === -0` being folded to `true`.

## How did you test this change?
See attached tests


Changed files:
filename: compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts
patch: @@ -327,6 +327,23 @@ function evaluateInstruction(
           }
           return null;
         }
+        case '-': {
+          const operand = read(constants, value.value);
+          if (
+            operand !== null &&
+            operand.kind === 'Primitive' &&
+            typeof operand.value === 'number'
+          ) {
+            const result: Primitive = {
+              kind: 'Primitive',
+              value: operand.value * -1,
+              loc: value.loc,
+            };
+            instr.value = result;
+            return result;
+          }
+          return null;
+        }
         default:
           return null;
       }

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary-number.expect.md
patch: @@ -0,0 +1,74 @@
+
+## Input
+
+```javascript
+import {Stringify} from 'shared-runtime';
+
+function foo() {
+  const a = -1;
+  return (
+    <Stringify
+      value={[
+        2 * a,
+        -0,
+        0 === -0,
+        -Infinity,
+        -NaN,
+        a * NaN,
+        a * Infinity,
+        a * -Infinity,
+      ]}
+    />
+  );
+}
+
+export const FIXTURE_ENTRYPOINT = {
+  fn: foo,
+  params: [],
+  isComponent: false,
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime";
+import { Stringify } from "shared-runtime";
+
+function foo() {
+  const $ = _c(1);
+  let t0;
+  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+    t0 = (
+      <Stringify
+        value={[
+          -2,
+          0,
+          true,
+          -Infinity,
+          -NaN,
+
+          -1 * NaN,
+          -1 * Infinity,
+          -1 * -Infinity,
+        ]}
+      />
+    );
+    $[0] = t0;
+  } else {
+    t0 = $[0];
+  }
+  return t0;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+  fn: foo,
+  params: [],
+  isComponent: false,
+};
+
+```
+      
+### Eval output
+(kind: ok) <div>{"value":[-2,0,true,null,null,null,null,null]}</div>
\ No newline at end of file

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary-number.js
patch: @@ -0,0 +1,25 @@
+import {Stringify} from 'shared-runtime';
+
+function foo() {
+  const a = -1;
+  return (
+    <Stringify
+      value={[
+        2 * a,
+        -0,
+        0 === -0,
+        -Infinity,
+        -NaN,
+        a * NaN,
+        a * Infinity,
+        a * -Infinity,
+      ]}
+    />
+  );
+}
+
+export const FIXTURE_ENTRYPOINT = {
+  fn: foo,
+  params: [],
+  isComponent: false,
+};

filename: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary.expect.md
patch: @@ -58,7 +58,7 @@ function foo() {
           n0: true,
           n1: false,
           n2: false,
-          n3: !-1,
+          n3: false,
           s0: true,
           s1: false,
           s2: false,