-
Notifications
You must be signed in to change notification settings - Fork 47.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[compiler] Improve handling of refs #30902
Conversation
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]
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
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-source-id: 7904093878454046d80749d2988d91dd7b6a0180 Pull Request resolved: #30902
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]
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]
Internal sync results A few runtime errors that need to be addressed before this can land but a significant reduction in bailouts |
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]
Updated sync results from the top of this stack at #30917 (including some unrelated PRs), looks good |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so good
} | ||
|
||
function joinRefTypes(...types: Array<RefAccessType>): RefAccessType { | ||
function joinRefRefTypes( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naming is hard
} | ||
|
||
override set(key: IdentifierId, value: RefAccessType): this { | ||
function tyEqual(a: RefAccessType, b: RefAccessType): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract into a static function?
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]
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-source-id: afb0b0cb014ffcf21ef4d0ede6511330fd975ec3 Pull Request resolved: #30902
**breaking change for canary users: Bumps peer dependency of React from `19.0.0-rc-206df66e-20240912` to `19.0.0-rc-a99d8e8d-20240916`** [diff facebook/react@206df66e...a99d8e8d](facebook/react@206df66...a99d8e8) <details> <summary>React upstream changes</summary> - facebook/react#30977 - facebook/react#30971 - facebook/react#30922 - facebook/react#30917 - facebook/react#30902 - facebook/react#30912 - facebook/react#30970 - facebook/react#30969 - facebook/react#30967 - facebook/react#30966 - facebook/react#30960 - facebook/react#30968 - facebook/react#30961 - facebook/react#28255 - facebook/react#30957 - facebook/react#30958 - facebook/react#30959 - facebook/react#30951 - facebook/react#30954 - facebook/react#30920 - facebook/react#30942 </details>
Stack from ghstack (oldest at bottom):
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 typeRef
, then{ x: ref }
and[ref]
have typeStructural(value=Ref)
and{x: ref}.anything
and[ref][anything]
have typeRef
).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
we end up giving
x
the typeStructural(value=Ref)
.