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};
18
19use anyhow::Result;
20use bincode::{Decode, Encode};
21use serde::{Deserialize, Serialize};
22use shrink_to_fit::ShrinkToFit;
23
24pub use self::{
25 cast::{VcCast, VcValueTraitCast, VcValueTypeCast},
26 cell_mode::{
27 VcCellCompareMode, VcCellHashedCompareMode, VcCellKeyedCompareMode, VcCellMode,
28 VcCellNewMode,
29 },
30 default::ValueDefault,
31 local::NonLocalValue,
32 operation::{OperationValue, OperationVc},
33 read::{ReadOwnedVcFuture, ReadVcFuture, VcDefaultRead, VcRead, VcTransparentRead},
34 resolved::ResolvedVc,
35 traits::{Dynamic, Upcast, UpcastStrict, VcValueTrait, VcValueType},
36};
37use crate::{
38 CellId, RawVc,
39 debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString},
40 keyed::{KeyedAccess, KeyedEq},
41 registry,
42 trace::{TraceRawVcs, TraceRawVcsContext},
43 vc::read::{ReadContainsKeyedVcFuture, ReadKeyedVcFuture},
44};
45
46type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
47
48#[doc = include_str!("README.md")]
49#[must_use]
50#[derive(Serialize, Deserialize, Encode, Decode)]
51#[serde(transparent, bound = "")]
52#[bincode(bounds = "T: ?Sized")]
53#[repr(transparent)]
54pub struct Vc<T>
55where
56 T: ?Sized,
57{
58 pub(crate) node: RawVc,
59 #[doc(hidden)]
60 pub(crate) _t: PhantomData<T>,
61}
62
63pub struct VcDeref<T>
67where
68 T: ?Sized,
69{
70 _t: PhantomData<T>,
71}
72
73macro_rules! do_not_use_or_you_will_be_fired {
74 ($($name:ident)*) => {
75 impl<T> VcDeref<T>
76 where
77 T: ?Sized,
78 {
79 $(
80 #[doc(hidden)]
81 #[allow(unused)]
82 #[allow(clippy::wrong_self_convention)]
83 #[deprecated = "This is not the method you are looking for."]
84 pub fn $name(self) {}
85 )*
86 }
87 };
88}
89
90do_not_use_or_you_will_be_fired!(
95 add
96 addr
97 align_offset
98 as_mut
99 as_mut_ptr
100 as_ptr
101 as_ref
102 as_uninit_mut
103 as_uninit_ref
104 as_uninit_slice
105 as_uninit_slice_mut
106 byte_add
107 byte_offset
108 byte_offset_from
109 byte_sub
110 cast
111 cast_const
112 cast_mut
113 copy_from
114 copy_from_nonoverlapping
115 copy_to
116 copy_to_nonoverlapping
117 drop_in_place
118 expose_addr
119 from_bits
120 get_unchecked
121 get_unchecked_mut
122 guaranteed_eq
123 guaranteed_ne
124 is_aligned
125 is_aligned_to
126 is_empty
127 is_null
128 len
129 map_addr
130 mask
131 offset
132 offset_from
133 read
134 read_unaligned
135 read_volatile
136 replace
137 split_at_mut
138 split_at_mut_unchecked
139 sub
140 sub_ptr
141 swap
142 to_bits
143 to_raw_parts
144 with_addr
145 with_metadata_of
146 wrapping_add
147 wrapping_byte_add
148 wrapping_byte_offset
149 wrapping_byte_sub
150 wrapping_offset
151 wrapping_sub
152 write
153 write_bytes
154 write_unaligned
155 write_volatile
156);
157
158#[doc(hidden)]
161impl<T> Deref for VcDeref<T>
162where
163 T: ?Sized,
164{
165 type Target = *const *mut *const T;
169
170 fn deref(&self) -> &Self::Target {
171 unsafe extern "C" {
172 #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
173 fn trigger() -> !;
174 }
175
176 unsafe { trigger() };
177 }
178}
179
180#[doc(hidden)]
190impl<T> Deref for Vc<T>
191where
192 T: ?Sized,
193{
194 type Target = VcDeref<T>;
195
196 fn deref(&self) -> &Self::Target {
197 unsafe extern "C" {
198 #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
199 fn trigger() -> !;
200 }
201
202 unsafe { trigger() };
203 }
204}
205
206impl<T> Copy for Vc<T> where T: ?Sized {}
207
208impl<T> Clone for Vc<T>
209where
210 T: ?Sized,
211{
212 fn clone(&self) -> Self {
213 *self
214 }
215}
216
217impl<T> Hash for Vc<T>
218where
219 T: ?Sized,
220{
221 fn hash<H: Hasher>(&self, state: &mut H) {
222 self.node.hash(state);
223 }
224}
225
226impl<T> PartialEq<Vc<T>> for Vc<T>
227where
228 T: ?Sized,
229{
230 fn eq(&self, other: &Self) -> bool {
231 self.node == other.node
232 }
233}
234
235impl<T> Eq for Vc<T> where T: ?Sized {}
236
237impl<T> Debug for Vc<T>
243where
244 T: ?Sized,
245{
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 f.debug_tuple("Vc").field(&self.node).finish()
248 }
249}
250
251impl<T> Vc<T>
252where
253 T: VcValueType,
254{
255 #[doc(hidden)]
257 pub fn cell_private(mut inner: <T::Read as VcRead<T>>::Target) -> Self {
258 ShrinkToFit::shrink_to_fit(<T::Read as VcRead<T>>::target_to_value_mut_ref(&mut inner));
260 <T::CellMode as VcCellMode<T>>::cell(inner)
261 }
262}
263
264impl<T, Inner> Vc<T>
265where
266 T: VcValueType<Read = VcTransparentRead<T, Inner>>,
267 Inner: Any + Send + Sync,
268{
269 pub fn cell(inner: Inner) -> Self {
270 Self::cell_private(inner)
271 }
272}
273
274impl<T> Vc<T>
275where
276 T: ?Sized,
277{
278 pub async fn debug_identifier(vc: Self) -> Result<String> {
280 let resolved = vc.to_resolved().await?;
281 let raw_vc: RawVc = resolved.node.node;
282 if let RawVc::TaskCell(task_id, CellId { type_id, index }) = raw_vc {
283 let value_ty = registry::get_value_type(type_id);
284 Ok(format!("{}#{}: {}", value_ty.ty.name, index, task_id))
285 } else {
286 unreachable!()
287 }
288 }
289
290 pub fn into_raw(vc: Self) -> RawVc {
292 vc.node
293 }
294
295 #[inline(always)]
299 pub fn upcast<K>(vc: Self) -> Vc<K>
300 where
301 T: UpcastStrict<K>,
302 K: VcValueTrait + ?Sized,
303 {
304 Self::upcast_non_strict(vc)
305 }
306
307 #[inline(always)]
326 pub fn upcast_non_strict<K>(vc: Self) -> Vc<K>
327 where
328 T: Upcast<K>,
329 K: VcValueTrait + ?Sized,
330 {
331 Vc {
332 node: vc.node,
333 _t: PhantomData,
334 }
335 }
336 pub async fn as_side_effect(self) -> Result<()> {
339 self.node.resolve().await?;
340 Ok(())
341 }
342
343 pub async fn to_resolved(self) -> Result<ResolvedVc<T>> {
347 Ok(ResolvedVc {
348 node: Vc {
349 node: self.node.resolve().await?,
350 _t: PhantomData,
351 },
352 })
353 }
354
355 pub fn is_resolved(self) -> bool {
363 self.node.is_resolved()
364 }
365
366 pub fn is_local(self) -> bool {
373 self.node.is_local()
374 }
375
376 #[cfg(feature = "non_operation_vc_strongly_consistent")]
378 pub async fn resolve_strongly_consistent(self) -> Result<Self> {
379 Ok(Self {
380 node: self.node.resolve_strongly_consistent().await?,
381 _t: PhantomData,
382 })
383 }
384}
385
386impl<T> From<RawVc> for Vc<T>
387where
388 T: ?Sized,
389{
390 fn from(node: RawVc) -> Self {
391 Self {
392 node,
393 _t: PhantomData,
394 }
395 }
396}
397
398impl<T> TraceRawVcs for Vc<T>
399where
400 T: ?Sized,
401{
402 fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
403 TraceRawVcs::trace_raw_vcs(&self.node, trace_context);
404 }
405}
406
407impl<T> ValueDebugFormat for Vc<T>
408where
409 T: UpcastStrict<Box<dyn ValueDebug>> + Send + Sync + ?Sized,
410{
411 fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
412 ValueDebugFormatString::Async(Box::pin(async move {
413 Ok({
414 let vc_value_debug = Vc::upcast::<Box<dyn ValueDebug>>(*self);
415 vc_value_debug.dbg_depth(depth).await?.to_string()
416 })
417 }))
418 }
419}
420
421macro_rules! into_future {
422 ($ty:ty) => {
423 impl<T> IntoFuture for $ty
424 where
425 T: VcValueType,
426 {
427 type Output = <ReadVcFuture<T> as Future>::Output;
428 type IntoFuture = ReadVcFuture<T>;
429 fn into_future(self) -> Self::IntoFuture {
430 self.node.into_read(T::has_serialization()).into()
431 }
432 }
433 };
434}
435
436into_future!(Vc<T>);
437into_future!(&Vc<T>);
438into_future!(&mut Vc<T>);
439
440impl<T> Vc<T>
441where
442 T: VcValueType,
443{
444 #[cfg(feature = "non_operation_vc_strongly_consistent")]
446 pub fn strongly_consistent(self) -> ReadVcFuture<T> {
447 self.node
448 .into_read(T::has_serialization())
449 .strongly_consistent()
450 .into()
451 }
452
453 pub fn untracked(self) -> ReadVcFuture<T> {
456 self.node
457 .into_read(T::has_serialization())
458 .untracked()
459 .into()
460 }
461
462 pub fn final_read_hint(self) -> ReadVcFuture<T> {
465 self.node
466 .into_read(T::has_serialization())
467 .final_read_hint()
468 .into()
469 }
470}
471
472impl<T> Vc<T>
473where
474 T: VcValueType,
475 VcReadTarget<T>: Clone,
476{
477 pub fn owned(self) -> ReadOwnedVcFuture<T> {
479 let future: ReadVcFuture<T> = self.node.into_read(T::has_serialization()).into();
480 future.owned()
481 }
482}
483
484impl<T> Vc<T>
485where
486 T: VcValueType,
487 VcReadTarget<T>: KeyedEq,
488{
489 pub fn get<'l, Q>(self, key: &'l Q) -> ReadKeyedVcFuture<'l, T, Q>
492 where
493 Q: Hash + ?Sized,
494 VcReadTarget<T>: KeyedAccess<Q>,
495 {
496 let future: ReadVcFuture<T> = self.node.into_read(T::has_serialization()).into();
497 future.get(key)
498 }
499
500 pub fn contains_key<'l, Q>(self, key: &'l Q) -> ReadContainsKeyedVcFuture<'l, T, Q>
503 where
504 Q: Hash + ?Sized,
505 VcReadTarget<T>: KeyedAccess<Q>,
506 {
507 let future: ReadVcFuture<T> = self.node.into_read(T::has_serialization()).into();
508 future.contains_key(key)
509 }
510}
511
512impl<T> Unpin for Vc<T> where T: ?Sized {}
513
514impl<T> Vc<T>
515where
516 T: VcValueTrait + ?Sized,
517{
518 pub fn into_trait_ref(self) -> ReadVcFuture<T, VcValueTraitCast<T>> {
524 self.node
525 .into_read_with_unknown_is_serializable_cell_content()
526 .into()
527 }
528}
529
530impl<T> Default for Vc<T>
531where
532 T: ValueDefault,
533{
534 fn default() -> Self {
535 T::value_default()
536 }
537}
538
539pub trait OptionVcExt<T>
540where
541 T: VcValueType,
542{
543 fn to_resolved(self) -> impl Future<Output = Result<Option<ResolvedVc<T>>>> + Send;
544}
545
546impl<T> OptionVcExt<T> for Option<Vc<T>>
547where
548 T: VcValueType,
549{
550 async fn to_resolved(self) -> Result<Option<ResolvedVc<T>>> {
551 if let Some(vc) = self {
552 Ok(Some(vc.to_resolved().await?))
553 } else {
554 Ok(None)
555 }
556 }
557}