compiler/packages/babel-plugin-react-compiler/docs/passes/07-analyseFunctions.md MARKDOWN 85 lines View on github.com → Search inside
1# analyseFunctions23## File4`src/Inference/AnalyseFunctions.ts`56## Purpose7Recursively analyzes all nested function expressions and object methods in a function to infer their aliasing effect signatures, which describe how the function affects its captured variables when invoked.89## Input Invariants10- The HIR has been through SSA conversion and type inference11- FunctionExpression and ObjectMethod instructions have an empty `aliasingEffects` array (`@aliasingEffects=[]`)12- Context variables (captured variables from outer scope) exist on `fn.context` but do not have their effect populated1314## Output Guarantees15- Every FunctionExpression and ObjectMethod has its `aliasingEffects` array populated with the effects the function performs when called (mutations, captures, aliasing to return value, etc.)16- Each context variable's `effect` property is set to either `Effect.Capture` (if the variable is captured or mutated by the inner function) or `Effect.Read` (if only read)17- Context variable mutable ranges are reset to `{start: 0, end: 0}` and scopes are set to `null` to prepare for the outer function's subsequent `inferMutationAliasingRanges` pass1819## Algorithm201. **Recursive traversal**: Iterates through all blocks and instructions looking for `FunctionExpression` or `ObjectMethod` instructions212. **Depth-first processing**: For each function expression found, calls `lowerWithMutationAliasing()` which:22   - Recursively calls `analyseFunctions()` on the inner function (handles nested functions)23   - Runs `inferMutationAliasingEffects()` on the inner function to determine effects24   - Runs `deadCodeElimination()` to clean up25   - Runs `inferMutationAliasingRanges()` to compute mutable ranges and extract externally-visible effects26   - Runs `rewriteInstructionKindsBasedOnReassignment()` and `inferReactiveScopeVariables()`27   - Stores the computed effects in `fn.aliasingEffects`283. **Context variable effect classification**: Scans the computed effects to determine which context variables are captured/mutated vs only read:29   - Effects like `Capture`, `Alias`, `Assign`, `MaybeAlias`, `CreateFrom` mark the source as captured30   - Mutation effects (`Mutate`, `MutateTransitive`, etc.) mark the target as captured31   - Sets `operand.effect = Effect.Capture` or `Effect.Read` accordingly324. **Range reset**: Resets mutable ranges and scopes on context variables to prepare for outer function analysis3334## Key Data Structures35- **HIRFunction.aliasingEffects**: Array of `AliasingEffect` storing the externally-visible behavior of a function when called36- **Place.effect**: Effect enum value (`Capture` or `Read`) describing how a context variable is used37- **AliasingEffect**: Union type describing data flow (Capture, Alias, Assign, etc.) and mutations (Mutate, MutateTransitive, etc.)38- **FunctionExpression/ObjectMethod.loweredFunc.func**: The inner HIRFunction to analyze3940## Edge Cases41- **Nested functions**: Handled via recursive call to `analyseFunctions()` before processing the current function - innermost functions are analyzed first42- **ObjectMethod**: Treated identically to FunctionExpression43- **Apply effects invariant**: The pass asserts that no `Apply` effects remain in the function's signature - these should have been resolved to more precise effects by `inferMutationAliasingRanges()`44- **Conditional mutations**: Effects like `MutateTransitiveConditionally` are tracked - a function that conditionally mutates a captured variable will have that effect in its signature45- **Immutable captures**: `ImmutableCapture`, `Freeze`, `Create`, `Impure`, `Render` effects do not contribute to marking context variables as `Capture`4647## TODOs48- No TODO comments in the pass itself4950## Example51Consider a function that captures and conditionally mutates a variable:5253```javascript54function useHook(a, b) {55  let z = {a};56  let y = b;57  let x = function () {58    if (y) {59      maybeMutate(z);  // Unknown function, may mutate z60    }61  };62  return x;63}64```6566**Before AnalyseFunctions:**67```68Function @context[y$28, z$25] @aliasingEffects=[]69```7071**After AnalyseFunctions:**72```73Function @context[read y$28, capture z$25] @aliasingEffects=[74  MutateTransitiveConditionally z$25,75  Create $14 = primitive76]77```7879The pass infers:80- `y` is only read (used in the condition)81- `z` is captured into the function and conditionally mutated transitively (because `maybeMutate()` is unknown)82- The inner function's signature includes `MutateTransitiveConditionally z$25` to indicate this potential mutation8384This signature is then used by `InferMutationAliasingEffects` on the outer function to understand that creating this function captures `z`, and calling the function may mutate `z`.

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.