-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Make ReadRef using VcCellMode
semantics, add VcCellMode::raw_cell
API
#8847
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
8 Skipped Deployments
|
🟢 Turbopack Benchmark CI successful 🟢Thanks |
✅ This change can build |
|
VcCellMode::raw_cell
APIVcCellMode
semantics, add VcCellMode::raw_cell
API
pub fn cell(read_ref: ReadRef<T>) -> Vc<T> { | ||
let type_id = T::get_value_type_id(); | ||
let local_cell = find_cell_by_type(type_id); | ||
// SAFETY: `T` and `T::Read::Repr` must have equivalent memory representations, | ||
// guaranteed by the unsafe implementation of `VcValueType`. | ||
local_cell.update_shared_reference(SharedReference::new(unsafe { | ||
let value = unsafe { | ||
unchecked_sidecast_triomphe_arc::<T, <T::Read as VcRead<T>>::Repr>(read_ref.0) | ||
})); | ||
}; | ||
Vc { | ||
node: local_cell.into(), | ||
node: <T::CellMode as VcCellMode<T>>::raw_cell( | ||
SharedReference::new(value).typed(type_id), | ||
), | ||
_t: PhantomData, | ||
} | ||
} |
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.
Essentially the problem here was that ReadRef
can't/shouldn't implement cell
itself. It must defer to VcCellMode
's implementation, as only that trait's implementation knows how to correctly construct a cell.
Ok( | ||
// Safety: the `VcValueType` implementor must guarantee that both `T` and | ||
// `Repr` are #[repr(transparent)]. | ||
unsafe { | ||
// Downcast the cell content to the expected representation type, then | ||
// transmute it to the expected type. | ||
// See https://users.rust-lang.org/t/transmute-doesnt-work-on-generic-types/87272/9 | ||
std::mem::transmute_copy::< | ||
ManuallyDrop<ReadRef<<T::Read as VcRead<T>>::Repr>>, | ||
Self::Output, | ||
>(&ManuallyDrop::new(content.cast()?)) | ||
}, | ||
) |
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.
It turns out that this transmute wasn't entirely correct. You can't do a straight transmute between two ReadRef<T>
s because it contains a triomphe::Arc<T>
, and the vtable half of triomphe::Arc<T>
's fat pointer is different depending on the type of T
.
You need to use something like unchecked_sidecast_triomphe_arc
so that the fat pointer is constructed correctly. I modified the TypedCellContent::cast
method in this PR to do the cast of Arc
for us before constructing the ReadRef
.
/// Create a type-erased `RawVc` cell given a pre-existing type-erased | ||
/// `SharedReference`. In some cases, we will re-use the shared value. | ||
fn raw_cell(value: TypedSharedReference) -> RawVc; |
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.
Local Vc resolution needs this VcCellMode::raw_cell
method too because we need to be able to construct a new cell inside of RawVc
where we don't have compile-time information about the concrete type T
(but we do have the type id).
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.
In some cases, we will re-use the shared value.
When is this the case?
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.
When constructing a Vc
from a ReadRef
or when converting a local Vc
to a global resolved Vc
we already have a SharedReference
or triomphe::Arc
, so we can re-use that value and avoid any need to clone the underlying value.
(I'll update the comment in the code here to provide this context)
// See Safety clause above. | ||
let TypedSharedReference(ty, shared_ref) = trait_ref.shared_reference; | ||
let local_cell = find_cell_by_type(ty); | ||
local_cell.update_shared_reference(shared_ref); | ||
local_cell.update_with_shared_reference(shared_ref); | ||
let raw_vc: RawVc = local_cell.into(); | ||
raw_vc.into() | ||
} |
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.
TraitRef::cell
has similar problems to ReadRef::cell
here, and needs to also call VcCellMode::raw_cell
, but that's a bit more complicated as I need a mapping of type ids to raw_vc
function pointers. I'll do that in a subsequent PR.
Edit: Fixed in #8870
83869a1
to
6bb3574
Compare
6bb3574
to
88a3dea
Compare
/// Replace the current cell's content with `new_shared_reference` if the | ||
/// current content is not equal by value with the existing content. | ||
/// | ||
/// If you already have a `SharedReference`, this is a faster version of |
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.
Perhaps it is useful to have the reciprocal comment?
Migrated to the next.js repo: vercel/next.js#68467 |
…e::raw_cell` API (#68467) *This is a migrated PR. This was in the turbo repository before the next.js merge.* **Migrated From:** vercel/turborepo#8847 ## Description More fixes to `ReadRef` on top of vercel/turborepo#8845. There's a bit of a cascade of changes that needed to happen here: - `ReadRef::cell` should actually use `VcCellMode` so that it supports new/shared semantics correctly. - ... however, `VcCellMode` needs to expose an API (`raw_cell`) for working with `SharedReference` so that we can reuse the `SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data inside of it. - ... however, `CurrentCellRef` needs to expose a `compare_and_update` method that works for `SharedReference` (`compare_and_update_with_shared_reference`). - ... however, the naming conventions for the `CurrentCellRef` methods are a bit confusing at this point, so rename them. ## Bigger Picture This my sneaky way of introducing the `raw_cell` API as part of a smaller PR, since that API will be needed for converting a local `Vc` to a resolved `Vc`. That's a similar problem of needing to reuse a `SharedReference` along with `VcCellMode` semantics. ## Testing Instructions ``` cargo nextest r -p turbo-tasks -p turbo-tasks-memory ```
…e::raw_cell` API (#68467) *This is a migrated PR. This was in the turbo repository before the next.js merge.* **Migrated From:** vercel/turborepo#8847 ## Description More fixes to `ReadRef` on top of vercel/turborepo#8845. There's a bit of a cascade of changes that needed to happen here: - `ReadRef::cell` should actually use `VcCellMode` so that it supports new/shared semantics correctly. - ... however, `VcCellMode` needs to expose an API (`raw_cell`) for working with `SharedReference` so that we can reuse the `SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data inside of it. - ... however, `CurrentCellRef` needs to expose a `compare_and_update` method that works for `SharedReference` (`compare_and_update_with_shared_reference`). - ... however, the naming conventions for the `CurrentCellRef` methods are a bit confusing at this point, so rename them. ## Bigger Picture This my sneaky way of introducing the `raw_cell` API as part of a smaller PR, since that API will be needed for converting a local `Vc` to a resolved `Vc`. That's a similar problem of needing to reuse a `SharedReference` along with `VcCellMode` semantics. ## Testing Instructions ``` cargo nextest r -p turbo-tasks -p turbo-tasks-memory ```
…e::raw_cell` API (#68467) *This is a migrated PR. This was in the turbo repository before the next.js merge.* **Migrated From:** vercel/turborepo#8847 ## Description More fixes to `ReadRef` on top of vercel/turborepo#8845. There's a bit of a cascade of changes that needed to happen here: - `ReadRef::cell` should actually use `VcCellMode` so that it supports new/shared semantics correctly. - ... however, `VcCellMode` needs to expose an API (`raw_cell`) for working with `SharedReference` so that we can reuse the `SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data inside of it. - ... however, `CurrentCellRef` needs to expose a `compare_and_update` method that works for `SharedReference` (`compare_and_update_with_shared_reference`). - ... however, the naming conventions for the `CurrentCellRef` methods are a bit confusing at this point, so rename them. ## Bigger Picture This my sneaky way of introducing the `raw_cell` API as part of a smaller PR, since that API will be needed for converting a local `Vc` to a resolved `Vc`. That's a similar problem of needing to reuse a `SharedReference` along with `VcCellMode` semantics. ## Testing Instructions ``` cargo nextest r -p turbo-tasks -p turbo-tasks-memory ```
…e::raw_cell` API (#68467) *This is a migrated PR. This was in the turbo repository before the next.js merge.* **Migrated From:** vercel/turborepo#8847 ## Description More fixes to `ReadRef` on top of vercel/turborepo#8845. There's a bit of a cascade of changes that needed to happen here: - `ReadRef::cell` should actually use `VcCellMode` so that it supports new/shared semantics correctly. - ... however, `VcCellMode` needs to expose an API (`raw_cell`) for working with `SharedReference` so that we can reuse the `SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data inside of it. - ... however, `CurrentCellRef` needs to expose a `compare_and_update` method that works for `SharedReference` (`compare_and_update_with_shared_reference`). - ... however, the naming conventions for the `CurrentCellRef` methods are a bit confusing at this point, so rename them. ## Bigger Picture This my sneaky way of introducing the `raw_cell` API as part of a smaller PR, since that API will be needed for converting a local `Vc` to a resolved `Vc`. That's a similar problem of needing to reuse a `SharedReference` along with `VcCellMode` semantics. ## Testing Instructions ``` cargo nextest r -p turbo-tasks -p turbo-tasks-memory ```
Description
More fixes to
ReadRef
on top of #8845. There's a bit of a cascade of changes that needed to happen here:ReadRef::cell
should actually useVcCellMode
so that it supports new/shared semantics correctly.VcCellMode
needs to expose an API (raw_cell
) for working withSharedReference
so that we can reuse theSharedReference
/Arc
inside ofReadRef
instead of cloning the data inside of it.CurrentCellRef
needs to expose acompare_and_update
method that works forSharedReference
(compare_and_update_with_shared_reference
).CurrentCellRef
methods are a bit confusing at this point, so rename them.Bigger Picture
This my sneaky way of introducing the
raw_cell
API as part of a smaller PR, since that API will be needed for converting a localVc
to a resolvedVc
. That's a similar problem of needing to reuse aSharedReference
along withVcCellMode
semantics.Testing Instructions