Skip to content

Commit

Permalink
Update on "[compiler] Improve handling of refs"
Browse files Browse the repository at this point in the history
Summary:
This change expands our handling of refs to build an understanding of nested refs within objects and functions that may return refs. It builds a special-purpose type system within the ref analysis that gives a very lightweight structural type to objects and array expressions (merging the types of all their members), and then propagating those types throughout the analysis (e.g., if `ref` has type `Ref`, then `{ x: ref }` and `[ref]` have type `Structural(value=Ref)` and `{x: ref}.anything` and `[ref][anything]` have type `Ref`).

This allows us to support structures that contain refs, and functions that operate over them, being created and passed around during rendering without at runtime accessing a ref value.

The analysis here uses a fixpoint to allow types to be fully propagated through the system, and we defend against diverging by widening the type of a variable if it could grow infinitely: so, in something like
```
let x = ref;
while (condition) {
  x = [x]
}
```
we end up giving `x` the type `Structural(value=Ref)`.

[ghstack-poisoned]
  • Loading branch information
mvitousek committed Sep 16, 2024
2 parents 37bbb75 + 87c3e8b commit 4c07998
Show file tree
Hide file tree
Showing 287 changed files with 11,500 additions and 3,001 deletions.
2 changes: 1 addition & 1 deletion compiler/apps/playground/components/Editor/EditorImpl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
name: result.name,
value: {
type: 'FunctionDeclaration',
id,
id: withIdentifier(result.value.id),
async: result.value.async,
generator: result.value.generator,
body: result.value.body,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import {propagatePhiTypes} from '../TypeInference/PropagatePhiTypes';
import {lowerContextAccess} from '../Optimization/LowerContextAccess';
import {validateNoSetStateInPassiveEffects} from '../Validation/ValidateNoSetStateInPassiveEffects';
import {validateNoJSXInTryStatement} from '../Validation/ValidateNoJSXInTryStatement';
import {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHIR';

export type CompilerPipelineValue =
| {kind: 'ast'; name: string; value: CodegenFunction}
Expand Down Expand Up @@ -341,6 +342,14 @@ function* runWithEnvironment(
});
assertTerminalSuccessorsExist(hir);
assertTerminalPredsExist(hir);
if (env.config.enablePropagateDepsInHIR) {
propagateScopeDependenciesHIR(hir);
yield log({
kind: 'hir',
name: 'PropagateScopeDependenciesHIR',
value: hir,
});
}

const reactiveFunction = buildReactiveFunction(hir);
yield log({
Expand All @@ -359,12 +368,14 @@ function* runWithEnvironment(
});
assertScopeInstructionsWithinScopes(reactiveFunction);

propagateScopeDependencies(reactiveFunction);
yield log({
kind: 'reactive',
name: 'PropagateScopeDependencies',
value: reactiveFunction,
});
if (!env.config.enablePropagateDepsInHIR) {
propagateScopeDependencies(reactiveFunction);
yield log({
kind: 'reactive',
name: 'PropagateScopeDependencies',
value: reactiveFunction,
});
}

pruneNonEscapingScopes(reactiveFunction);
yield log({
Expand Down
Loading

0 comments on commit 4c07998

Please sign in to comment.