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