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