diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-captures-value-later-frozen-jsx.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-captures-value-later-frozen-jsx.expect.md
new file mode 100644
index 0000000000..f4507d3e5a
--- /dev/null
+++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-captures-value-later-frozen-jsx.expect.md
@@ -0,0 +1,27 @@
+
+## Input
+
+```javascript
+function Component(props) {
+ let x = {};
+ // onChange should be inferred as immutable, because the value
+ // it captures (`x`) is frozen by the time the function is referenced
+ const onChange = (e) => {
+ maybeMutate(x, e.target.value);
+ };
+ if (props.cond) {
+
{x}
;
+ }
+ return ;
+}
+
+```
+
+
+## Error
+
+```
+[ReactForget] InvalidInput: Cannot use a mutable function where an immutable value is expected (11:11)
+```
+
+
\ No newline at end of file
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-captures-value-later-frozen-jsx.js b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-captures-value-later-frozen-jsx.js
new file mode 100644
index 0000000000..7e694fa1bd
--- /dev/null
+++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-captures-value-later-frozen-jsx.js
@@ -0,0 +1,12 @@
+function Component(props) {
+ let x = {};
+ // onChange should be inferred as immutable, because the value
+ // it captures (`x`) is frozen by the time the function is referenced
+ const onChange = (e) => {
+ maybeMutate(x, e.target.value);
+ };
+ if (props.cond) {
+ {x}
;
+ }
+ return ;
+}
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-maybe-mutates-hook-return-value.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-maybe-mutates-hook-return-value.expect.md
new file mode 100644
index 0000000000..9427787184
--- /dev/null
+++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-maybe-mutates-hook-return-value.expect.md
@@ -0,0 +1,27 @@
+
+## Input
+
+```javascript
+function Component(props) {
+ const id = useSelectedEntitytId();
+ // this example should infer `id` as mutable, and then infer `onLoad` as mutable,
+ // and be rejected because onLoad cannot be passed as a frozen value in the JSX.
+ // however, we likely have to allow this example to work, because hook return
+ // values are generally immutable in practice and are also widely referenced in
+ // callbacks.
+ const onLoad = () => {
+ log(id);
+ };
+ return ;
+}
+
+```
+
+
+## Error
+
+```
+[ReactForget] InvalidInput: Cannot use a mutable function where an immutable value is expected (11:11)
+```
+
+
\ No newline at end of file
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-maybe-mutates-hook-return-value.js b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-maybe-mutates-hook-return-value.js
new file mode 100644
index 0000000000..fcf38652b1
--- /dev/null
+++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-function-expression-maybe-mutates-hook-return-value.js
@@ -0,0 +1,12 @@
+function Component(props) {
+ const id = useSelectedEntitytId();
+ // this example should infer `id` as mutable, and then infer `onLoad` as mutable,
+ // and be rejected because onLoad cannot be passed as a frozen value in the JSX.
+ // however, we likely have to allow this example to work, because hook return
+ // values are generally immutable in practice and are also widely referenced in
+ // callbacks.
+ const onLoad = () => {
+ log(id);
+ };
+ return ;
+}
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.expect.md
new file mode 100644
index 0000000000..3e276ce3ee
--- /dev/null
+++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.expect.md
@@ -0,0 +1,58 @@
+
+## Input
+
+```javascript
+function Component(props) {
+ let x = {};
+ // onChange should be inferred as immutable, because the value
+ // it captures (`x`) is frozen by the time the function is referenced
+ const onChange = (e) => {
+ maybeMutate(x, e.target.value);
+ };
+ if (props.cond) {
+ {x}
;
+ }
+ // ideally this call would be outside the memoization block for `x`
+ onChange();
+ return ;
+}
+
+```
+
+## Code
+
+```javascript
+import { unstable_useMemoCache as useMemoCache } from "react";
+function Component(props) {
+ const $ = useMemoCache(4);
+ const c_0 = $[0] !== props.cond;
+ let x;
+ if (c_0) {
+ x = {};
+
+ const onChange = (e) => {
+ maybeMutate(x, e.target.value);
+ };
+ if (props.cond) {
+ }
+
+ onChange();
+ $[0] = props.cond;
+ $[1] = x;
+ } else {
+ x = $[1];
+ }
+ const c_2 = $[2] !== x;
+ let t0;
+ if (c_2) {
+ t0 = ;
+ $[2] = x;
+ $[3] = t0;
+ } else {
+ t0 = $[3];
+ }
+ return t0;
+}
+
+```
+
\ No newline at end of file
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.js b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.js
new file mode 100644
index 0000000000..a5e39b4254
--- /dev/null
+++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-function-expression-captures-value-later-frozen.js
@@ -0,0 +1,14 @@
+function Component(props) {
+ let x = {};
+ // onChange should be inferred as immutable, because the value
+ // it captures (`x`) is frozen by the time the function is referenced
+ const onChange = (e) => {
+ maybeMutate(x, e.target.value);
+ };
+ if (props.cond) {
+ {x}
;
+ }
+ // ideally this call would be outside the memoization block for `x`
+ onChange();
+ return ;
+}
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/invalid-freeze-mutable-lambda.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-invalid-function-expression-mutates-immutable-value.expect.md
similarity index 100%
rename from compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/invalid-freeze-mutable-lambda.expect.md
rename to compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-invalid-function-expression-mutates-immutable-value.expect.md
diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/invalid-freeze-mutable-lambda.js b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-invalid-function-expression-mutates-immutable-value.js
similarity index 100%
rename from compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/invalid-freeze-mutable-lambda.js
rename to compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/todo-invalid-function-expression-mutates-immutable-value.js