1pub(crate) mod cast;
2mod cell_mode;
3pub(crate) mod default;
4mod local;
5pub(crate) mod operation;
6mod ord;
7mod raw;
8mod read;
9pub(crate) mod resolved;
10mod traits;
11
12use std::{
13 any::Any,
14 fmt::Debug,
15 future::Future,
16 hash::{Hash, Hasher},
17 marker::PhantomData,
18 ops::Deref,
19 pin::Pin,
20 task::{Context, Poll},
21};
22
23use anyhow::Result;
24use bincode::{Decode, Encode};
25use serde::{Deserialize, Serialize};
26use shrink_to_fit::ShrinkToFit;
27
28#[cfg(debug_assertions)]
29use crate::debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString};
30pub use crate::vc::{
31 cast::{VcCast, VcValueTraitCast, VcValueTypeCast},
32 cell_mode::{
33 VcCellCompareMode, VcCellHashedCompareMode, VcCellKeyedCompareMode, VcCellMode,
34 VcCellNewMode,
35 },
36 default::ValueDefault,
37 local::NonLocalValue,
38 operation::{OperationValue, OperationVc, ResolveOperationVcFuture},
39 ord::OrdResolvedVc,
40 raw::{CellId, RawVc, RawVcUnpacked, ReadRawVcFuture, ResolveRawVcFuture},
41 read::{ReadOwnedVcFuture, ReadVcFuture, VcDefaultRead, VcRead, VcTransparentRead},
42 resolved::ResolvedVc,
43 traits::{Dynamic, Upcast, UpcastStrict, VcValueTrait, VcValueType},
44};
45use crate::{
46 keyed::{KeyedAccess, KeyedEq},
47 registry,
48 vc::read::{ReadContainsKeyedVcFuture, ReadKeyedVcFuture},
49};
50
51#[must_use]
57pub struct ResolveVcFuture<T>
58where
59 T: ?Sized,
60{
61 pub(crate) inner: ResolveRawVcFuture,
62 pub(crate) _t: PhantomData<T>,
63}
64
65impl<T: ?Sized> Future for ResolveVcFuture<T> {
66 type Output = Result<Vc<T>>;
67
68 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
69 let this = unsafe { self.get_unchecked_mut() };
71 Pin::new(&mut this.inner).poll(cx).map(|r| {
73 r.map(|node| Vc {
74 node,
75 _t: PhantomData,
76 })
77 })
78 }
79}
80
81impl<T: ?Sized> Unpin for ResolveVcFuture<T> {}
82
83#[must_use]
87pub struct ToResolvedVcFuture<T>
88where
89 T: ?Sized,
90{
91 inner: ResolveRawVcFuture,
92 _t: PhantomData<T>,
93}
94
95impl<T: ?Sized> ToResolvedVcFuture<T> {
96 pub fn strongly_consistent(mut self) -> Self {
98 self.inner = self.inner.strongly_consistent();
99 self
100 }
101}
102
103impl<T: ?Sized> Future for ToResolvedVcFuture<T> {
104 type Output = Result<ResolvedVc<T>>;
105
106 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
107 let this = unsafe { self.get_unchecked_mut() };
109 Pin::new(&mut this.inner).poll(cx).map(|r| {
111 r.map(|node| ResolvedVc {
112 node: Vc {
113 node,
114 _t: PhantomData,
115 },
116 })
117 })
118 }
119}
120
121impl<T: ?Sized> Unpin for ToResolvedVcFuture<T> {}
122
123type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
124
125#[doc = include_str!("README.md")]
126#[must_use]
127#[derive(Serialize, Deserialize, Encode, Decode)]
128#[serde(transparent, bound = "")]
129#[bincode(bounds = "T: ?Sized")]
130#[repr(transparent)]
131pub struct Vc<T>
132where
133 T: ?Sized,
134{
135 pub(crate) node: RawVc,
136 #[doc(hidden)]
137 pub(crate) _t: PhantomData<T>,
138}
139
140pub struct VcDeref<T>
144where
145 T: ?Sized,
146{
147 _t: PhantomData<T>,
148}
149
150macro_rules! do_not_use_or_you_will_be_fired {
151 ($($name:ident)*) => {
152 impl<T> VcDeref<T>
153 where
154 T: ?Sized,
155 {
156 $(
157 #[doc(hidden)]
158 #[allow(unused)]
159 #[allow(clippy::wrong_self_convention)]
160 #[deprecated = "This is not the method you are looking for."]
161 pub fn $name(self) {}
162 )*
163 }
164 };
165}
166
167do_not_use_or_you_will_be_fired!(
172 add
173 addr
174 align_offset
175 as_mut
176 as_mut_ptr
177 as_ptr
178 as_ref
179 as_uninit_mut
180 as_uninit_ref
181 as_uninit_slice
182 as_uninit_slice_mut
183 byte_add
184 byte_offset
185 byte_offset_from
186 byte_sub
187 cast
188 cast_const
189 cast_mut
190 copy_from
191 copy_from_nonoverlapping
192 copy_to
193 copy_to_nonoverlapping
194 drop_in_place
195 expose_addr
196 from_bits
197 get_unchecked
198 get_unchecked_mut
199 guaranteed_eq
200 guaranteed_ne
201 is_aligned
202 is_aligned_to
203 is_empty
204 is_null
205 len
206 map_addr
207 mask
208 offset
209 offset_from
210 read
211 read_unaligned
212 read_volatile
213 replace
214 split_at_mut
215 split_at_mut_unchecked
216 sub
217 sub_ptr
218 swap
219 to_bits
220 to_raw_parts
221 with_addr
222 with_metadata_of
223 wrapping_add
224 wrapping_byte_add
225 wrapping_byte_offset
226 wrapping_byte_sub
227 wrapping_offset
228 wrapping_sub
229 write
230 write_bytes
231 write_unaligned
232 write_volatile
233);
234
235#[doc(hidden)]
238impl<T> Deref for VcDeref<T>
239where
240 T: ?Sized,
241{
242 type Target = *const *mut *const T;
246
247 fn deref(&self) -> &Self::Target {
248 unsafe extern "C" {
249 #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
250 fn trigger() -> !;
251 }
252
253 unsafe { trigger() };
254 }
255}
256
257#[doc(hidden)]
267impl<T> Deref for Vc<T>
268where
269 T: ?Sized,
270{
271 type Target = VcDeref<T>;
272
273 fn deref(&self) -> &Self::Target {
274 unsafe extern "C" {
275 #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
276 fn trigger() -> !;
277 }
278
279 unsafe { trigger() };
280 }
281}
282
283impl<T> Copy for Vc<T> where T: ?Sized {}
284
285impl<T> Clone for Vc<T>
286where
287 T: ?Sized,
288{
289 fn clone(&self) -> Self {
290 *self
291 }
292}
293
294impl<T> Hash for Vc<T>
295where
296 T: ?Sized,
297{
298 fn hash<H: Hasher>(&self, state: &mut H) {
299 self.node.hash(state);
300 }
301}
302
303impl<T> PartialEq<Vc<T>> for Vc<T>
304where
305 T: ?Sized,
306{
307 fn eq(&self, other: &Self) -> bool {
308 self.node == other.node
309 }
310}
311
312impl<T> Eq for Vc<T> where T: ?Sized {}
313
314impl<T> Debug for Vc<T>
320where
321 T: ?Sized,
322{
323 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
324 f.debug_tuple("Vc").field(&self.node).finish()
325 }
326}
327
328impl<T> Vc<T>
329where
330 T: VcValueType,
331{
332 #[doc(hidden)]
334 pub fn cell_private(mut inner: <T::Read as VcRead<T>>::Target) -> Self {
335 ShrinkToFit::shrink_to_fit(<T::Read as VcRead<T>>::target_to_value_mut_ref(&mut inner));
337 <T::CellMode as VcCellMode<T>>::cell(inner)
338 }
339}
340
341impl<T, Inner> Vc<T>
342where
343 T: VcValueType<Read = VcTransparentRead<T, Inner>>,
344 Inner: Any + Send + Sync,
345{
346 pub fn cell(inner: Inner) -> Self {
347 Self::cell_private(inner)
348 }
349}
350
351impl<T> Vc<T>
352where
353 T: ?Sized,
354{
355 pub async fn debug_identifier(vc: Self) -> Result<String> {
357 let resolved = vc.to_resolved().await?;
358 let raw_vc: RawVc = resolved.node.node;
359 if let Some((task_id, cell_id)) = raw_vc.as_task_cell() {
360 let value_name = registry::get_value_type(cell_id.type_id()).ty.name;
361 Ok(format!(
362 "{value_name}#{index}: {task_id}",
363 index = cell_id.index(),
364 ))
365 } else {
366 unreachable!()
367 }
368 }
369
370 pub fn into_raw(vc: Self) -> RawVc {
372 vc.node
373 }
374
375 #[inline(always)]
379 pub fn upcast<K>(vc: Self) -> Vc<K>
380 where
381 T: UpcastStrict<K>,
382 K: VcValueTrait + ?Sized,
383 {
384 Self::upcast_non_strict(vc)
385 }
386
387 #[inline(always)]
406 pub fn upcast_non_strict<K>(vc: Self) -> Vc<K>
407 where
408 T: Upcast<K>,
409 K: VcValueTrait + ?Sized,
410 {
411 Vc {
412 node: vc.node,
413 _t: PhantomData,
414 }
415 }
416 pub async fn as_side_effect(self) -> Result<()> {
419 self.node.resolve().await?;
420 Ok(())
421 }
422
423 pub fn resolve(self) -> ResolveVcFuture<T> {
426 ResolveVcFuture {
427 inner: self.node.resolve(),
428 _t: PhantomData,
429 }
430 }
431
432 pub fn to_resolved(self) -> ToResolvedVcFuture<T> {
436 ToResolvedVcFuture {
437 inner: self.node.resolve(),
438 _t: PhantomData,
439 }
440 }
441
442 pub fn is_resolved(self) -> bool {
450 self.node.is_resolved()
451 }
452
453 pub fn is_local(self) -> bool {
460 self.node.is_local_output()
461 }
462}
463
464impl<T> From<RawVc> for Vc<T>
465where
466 T: ?Sized,
467{
468 fn from(node: RawVc) -> Self {
469 Self {
470 node,
471 _t: PhantomData,
472 }
473 }
474}
475
476#[cfg(debug_assertions)]
477impl<T> ValueDebugFormat for Vc<T>
478where
479 T: UpcastStrict<Box<dyn ValueDebug>> + Send + Sync + ?Sized,
480{
481 fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
482 ValueDebugFormatString::Async(Box::pin(async move {
483 let vc_value_debug = Vc::upcast::<Box<dyn ValueDebug>>(*self);
484 let trait_ref = vc_value_debug.into_trait_ref().await?;
485 trait_ref.dbg_depth(depth).await
486 }))
487 }
488}
489
490macro_rules! into_future {
491 ($ty:ty, |$this:ident| $into_future:expr $(,)?) => {
492 impl<T> ::std::future::IntoFuture for $ty
493 where
494 T: $crate::VcValueType,
495 {
496 type Output = <$crate::ReadVcFuture<T> as ::std::future::Future>::Output;
497 type IntoFuture = $crate::ReadVcFuture<T>;
498 fn into_future(self) -> Self::IntoFuture {
499 let $this = self;
500 $into_future
501 }
502 }
503 };
504}
505pub(crate) use into_future;
506
507into_future!(Vc<T>, |this| this.node.into_read().into());
508into_future!(&Vc<T>, |this| this.node.into_read().into());
509into_future!(&mut Vc<T>, |this| this.node.into_read().into());
510
511impl<T> Vc<T>
512where
513 T: VcValueType,
514{
515 #[cfg(feature = "non_operation_vc_strongly_consistent")]
517 pub fn strongly_consistent(self) -> ReadVcFuture<T> {
518 self.node.into_read().strongly_consistent().into()
519 }
520
521 pub fn untracked(self) -> ReadVcFuture<T> {
524 self.node.into_read().untracked().into()
525 }
526
527 pub fn final_read_hint(self) -> ReadVcFuture<T> {
530 self.node.into_read().final_read_hint().into()
531 }
532}
533
534impl<T> Vc<T>
535where
536 T: VcValueType,
537 VcReadTarget<T>: Clone,
538{
539 pub fn owned(self) -> ReadOwnedVcFuture<T> {
541 let future: ReadVcFuture<T> = self.node.into_read().into();
542 future.owned()
543 }
544}
545
546impl<T> Vc<T>
547where
548 T: VcValueType,
549 VcReadTarget<T>: KeyedEq,
550{
551 pub fn get<'l, Q>(self, key: &'l Q) -> ReadKeyedVcFuture<'l, T, Q>
554 where
555 Q: Hash + ?Sized,
556 VcReadTarget<T>: KeyedAccess<Q>,
557 {
558 let future: ReadVcFuture<T> = self.node.into_read().into();
559 future.get(key)
560 }
561
562 pub fn contains_key<'l, Q>(self, key: &'l Q) -> ReadContainsKeyedVcFuture<'l, T, Q>
565 where
566 Q: Hash + ?Sized,
567 VcReadTarget<T>: KeyedAccess<Q>,
568 {
569 let future: ReadVcFuture<T> = self.node.into_read().into();
570 future.contains_key(key)
571 }
572}
573
574impl<T> Unpin for Vc<T> where T: ?Sized {}
575
576impl<T> Vc<T>
577where
578 T: VcValueTrait + ?Sized,
579{
580 pub fn into_trait_ref(self) -> ReadVcFuture<T, VcValueTraitCast<T>> {
586 self.node.into_read().into()
587 }
588}
589
590impl<T> Default for Vc<T>
591where
592 T: ValueDefault,
593{
594 fn default() -> Self {
595 T::value_default()
596 }
597}
598
599pub trait OptionVcExt<T>
600where
601 T: VcValueType,
602{
603 fn to_resolved(self) -> impl Future<Output = Result<Option<ResolvedVc<T>>>> + Send;
604}
605
606impl<T> OptionVcExt<T> for Option<Vc<T>>
607where
608 T: VcValueType,
609{
610 async fn to_resolved(self) -> Result<Option<ResolvedVc<T>>> {
611 if let Some(vc) = self {
612 Ok(Some(vc.to_resolved().await?))
613 } else {
614 Ok(None)
615 }
616 }
617}