Skip to main content

turbo_tasks/vc/
ord.rs

1use std::{
2    cmp::Ordering,
3    fmt::{self, Debug},
4    hash::{Hash, Hasher},
5    ops::Deref,
6    slice,
7};
8
9use bincode::{Decode, Encode};
10use serde::{Deserialize, Serialize};
11
12use crate::{ResolvedVc, Vc, vc::into_future};
13#[cfg(debug_assertions)]
14use crate::{
15    UpcastStrict,
16    debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString},
17};
18
19/// A thin wrapper on [`ResolvedVc`] that implements [`Ord`]. You must not depend on this to provide
20/// deterministic execution (i.e. to produce externally-visible outputs, like when performing
21/// chunking) as task ids are non-deterministic across cold executions.
22///
23/// This can be useful to provide a cache key. Given a single instance of `turbo-tasks`, this will
24/// give stable results.
25#[derive(Serialize, Deserialize, Encode, Decode)]
26#[serde(transparent, bound = "")]
27#[bincode(bounds = "T: ?Sized")]
28#[repr(transparent)]
29pub struct OrdResolvedVc<T>
30where
31    T: ?Sized,
32{
33    node: ResolvedVc<T>,
34}
35
36impl<T> OrdResolvedVc<T>
37where
38    T: ?Sized,
39{
40    /// Wraps a [`ResolvedVc`] so that it can be ordered. See the type-level documentation for the
41    /// caveats around determinism.
42    pub fn new(node: ResolvedVc<T>) -> Self {
43        Self { node }
44    }
45
46    /// Cheaply converts a [`Vec`] of ordered [`ResolvedVc`]s to a [`Vec`] of [`ResolvedVc`]s.
47    pub fn deref_vec(vec: Vec<OrdResolvedVc<T>>) -> Vec<ResolvedVc<T>> {
48        debug_assert!(size_of::<OrdResolvedVc<T>>() == size_of::<ResolvedVc<T>>());
49        let (ptr, len, capacity) = vec.into_raw_parts();
50        // Safety: The memory layout of `OrdResolvedVc<T>` and `ResolvedVc<T>` is
51        // the same.
52        unsafe { Vec::from_raw_parts(ptr as *mut ResolvedVc<T>, len, capacity) }
53    }
54
55    /// Cheaply converts a slice of [`OrdResolvedVc`]s to a slice of
56    /// [`ResolvedVc`]s.
57    pub fn deref_slice(s: &[OrdResolvedVc<T>]) -> &[ResolvedVc<T>] {
58        debug_assert!(size_of::<OrdResolvedVc<T>>() == size_of::<ResolvedVc<T>>());
59        // Safety: The memory layout of `OrdResolvedVc<T>` and `ResolvedVc<T>` is
60        // the same.
61        unsafe { slice::from_raw_parts(s.as_ptr() as *const ResolvedVc<T>, s.len()) }
62    }
63}
64
65impl<T> From<ResolvedVc<T>> for OrdResolvedVc<T>
66where
67    T: ?Sized,
68{
69    fn from(node: ResolvedVc<T>) -> Self {
70        Self::new(node)
71    }
72}
73
74impl<T> PartialEq<OrdResolvedVc<T>> for OrdResolvedVc<T>
75where
76    T: ?Sized,
77{
78    fn eq(&self, other: &Self) -> bool {
79        self.node == other.node
80    }
81}
82
83impl<T> Eq for OrdResolvedVc<T> where T: ?Sized {}
84
85impl<T> Hash for OrdResolvedVc<T>
86where
87    T: ?Sized,
88{
89    fn hash<H: Hasher>(&self, state: &mut H) {
90        self.node.hash(state);
91    }
92}
93
94impl<T> PartialOrd for OrdResolvedVc<T>
95where
96    T: ?Sized,
97{
98    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
99        Some(self.cmp(other))
100    }
101}
102impl<T> Ord for OrdResolvedVc<T>
103where
104    T: ?Sized,
105{
106    fn cmp(&self, other: &Self) -> Ordering {
107        Vc::into_raw(*self.node)
108            .bits()
109            .cmp(&Vc::into_raw(*other.node).bits())
110    }
111}
112
113impl<T> Copy for OrdResolvedVc<T> where T: ?Sized {}
114
115impl<T> Clone for OrdResolvedVc<T>
116where
117    T: ?Sized,
118{
119    fn clone(&self) -> Self {
120        *self
121    }
122}
123
124impl<T> Debug for OrdResolvedVc<T>
125where
126    T: ?Sized,
127{
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        f.debug_tuple("OrdResolvedVc")
130            .field(&self.node.node.node)
131            .finish()
132    }
133}
134
135#[cfg(debug_assertions)]
136impl<T> ValueDebugFormat for OrdResolvedVc<T>
137where
138    T: UpcastStrict<Box<dyn ValueDebug>> + Send + Sync + ?Sized,
139{
140    fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
141        self.node.value_debug_format(depth)
142    }
143}
144
145impl<T> Deref for OrdResolvedVc<T>
146where
147    T: ?Sized,
148{
149    type Target = ResolvedVc<T>;
150
151    fn deref(&self) -> &Self::Target {
152        &self.node
153    }
154}
155
156into_future!(OrdResolvedVc<T>, |this| (*this).into_future());
157into_future!(&OrdResolvedVc<T>, |this| (*this).into_future());
158into_future!(&mut OrdResolvedVc<T>, |this| (*this).into_future());