1use std::{
2 collections::{BTreeMap, BTreeSet},
3 fmt::Debug,
4 future::Future,
5 hash::Hash,
6 ops::{Deref, DerefMut},
7 pin::Pin,
8 sync::Arc,
9 task::{Context, Poll},
10 time::Duration,
11};
12
13use anyhow::Result;
14use bincode::{
15 Decode, Encode,
16 de::Decoder,
17 enc::Encoder,
18 error::{DecodeError, EncodeError},
19};
20use either::Either;
21use turbo_frozenmap::{FrozenMap, FrozenSet};
22use turbo_rcstr::RcStr;
23use turbo_tasks_hash::HashAlgorithm;
24
25use crate::{self as turbo_tasks, OrdResolvedVc, ReadRef};
28use crate::{
29 DynTaskInputs, ResolvedVc, TaskId, TransientInstance, TransientValue, ValueTypeId, Vc,
30 trace::TraceRawVcs,
31};
32
33struct CloneReady<'a, T> {
38 pub inner: Option<&'a T>,
39}
40
41impl<'a, T: Clone> Future for CloneReady<'a, T> {
42 type Output = Result<T>;
43
44 fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
45 Poll::Ready(Ok(self
46 .inner
47 .take()
48 .expect("future already polled to completion")
49 .clone()))
50 }
51}
52
53impl<'a, T> Unpin for CloneReady<'a, T> {}
55
56pub trait TaskInput:
114 Send + Sync + Clone + Debug + PartialEq + Eq + Hash + TraceRawVcs + Encode + Decode<()>
115{
116 fn resolve_input(&self) -> impl Future<Output = Result<Self>> + Send + '_ {
120 CloneReady { inner: Some(self) }
121 }
122
123 fn is_resolved(&self) -> bool {
135 true
136 }
137
138 fn is_transient(&self) -> bool;
148}
149
150macro_rules! impl_task_input {
151 ($($t:ty),*) => {
152 $(
153 impl TaskInput for $t {
154 fn is_transient(&self) -> bool {
155 false
156 }
157 }
158 )*
159 };
160}
161
162impl_task_input! {
163 (),
164 bool,
165 u8,
166 u16,
167 u32,
168 i32,
169 u64,
170 u128,
171 usize,
172 RcStr,
173 TaskId,
174 ValueTypeId,
175 Duration,
176 String,
177 HashAlgorithm
178}
179
180impl<T> TaskInput for Vec<T>
181where
182 T: TaskInput,
183{
184 fn is_resolved(&self) -> bool {
185 self.iter().all(TaskInput::is_resolved)
186 }
187
188 fn is_transient(&self) -> bool {
189 self.iter().any(TaskInput::is_transient)
190 }
191
192 async fn resolve_input(&self) -> Result<Self> {
193 let mut resolved = Vec::with_capacity(self.len());
194 for value in self {
195 resolved.push(value.resolve_input().await?);
196 }
197 Ok(resolved)
198 }
199}
200
201impl<T> TaskInput for Box<T>
202where
203 T: TaskInput,
204{
205 fn is_resolved(&self) -> bool {
206 self.as_ref().is_resolved()
207 }
208
209 fn is_transient(&self) -> bool {
210 self.as_ref().is_transient()
211 }
212
213 async fn resolve_input(&self) -> Result<Self> {
214 Ok(Box::new(Box::pin(self.as_ref().resolve_input()).await?))
215 }
216}
217
218impl<T> TaskInput for Arc<T>
219where
220 T: TaskInput,
221{
222 fn is_resolved(&self) -> bool {
223 self.as_ref().is_resolved()
224 }
225
226 fn is_transient(&self) -> bool {
227 self.as_ref().is_transient()
228 }
229
230 async fn resolve_input(&self) -> Result<Self> {
231 Ok(Arc::new(Box::pin(self.as_ref().resolve_input()).await?))
232 }
233}
234
235impl<T> TaskInput for ReadRef<T>
236where
237 T: TaskInput,
238{
239 fn is_resolved(&self) -> bool {
240 Self::as_raw_ref(self).is_resolved()
241 }
242
243 fn is_transient(&self) -> bool {
244 Self::as_raw_ref(self).is_transient()
245 }
246
247 async fn resolve_input(&self) -> Result<Self> {
248 Ok(ReadRef::new_owned(
249 Box::pin(Self::as_raw_ref(self).resolve_input()).await?,
250 ))
251 }
252}
253
254impl<T> TaskInput for Option<T>
255where
256 T: TaskInput,
257{
258 fn is_resolved(&self) -> bool {
259 match self {
260 Some(value) => value.is_resolved(),
261 None => true,
262 }
263 }
264
265 fn is_transient(&self) -> bool {
266 match self {
267 Some(value) => value.is_transient(),
268 None => false,
269 }
270 }
271
272 async fn resolve_input(&self) -> Result<Self> {
273 match self {
274 Some(value) => Ok(Some(value.resolve_input().await?)),
275 None => Ok(None),
276 }
277 }
278}
279
280impl<T> TaskInput for Vc<T>
281where
282 T: Send + Sync + ?Sized,
283{
284 fn is_resolved(&self) -> bool {
285 Vc::is_resolved(*self)
286 }
287
288 fn is_transient(&self) -> bool {
289 self.node.is_transient()
290 }
291
292 fn resolve_input(&self) -> impl Future<Output = Result<Self>> + Send + '_ {
293 (*self).resolve()
296 }
297}
298
299impl<T> TaskInput for ResolvedVc<T>
302where
303 T: Send + Sync + ?Sized,
304{
305 fn is_resolved(&self) -> bool {
306 true
307 }
308
309 fn is_transient(&self) -> bool {
310 self.node.is_transient()
311 }
312}
313
314impl<T> TaskInput for OrdResolvedVc<T>
315where
316 T: Send + Sync + ?Sized,
317{
318 fn is_resolved(&self) -> bool {
319 true
320 }
321
322 fn is_transient(&self) -> bool {
323 self.node.is_transient()
324 }
325}
326
327impl<T> TaskInput for TransientValue<T>
328where
329 T: DynTaskInputs + Clone + Debug + Hash + Eq + TraceRawVcs + 'static,
330{
331 fn is_transient(&self) -> bool {
332 true
333 }
334}
335
336impl<T> Encode for TransientValue<T> {
337 fn encode<E: Encoder>(&self, _encoder: &mut E) -> Result<(), EncodeError> {
338 Err(EncodeError::Other("cannot encode transient task inputs"))
339 }
340}
341
342impl<Context, T> Decode<Context> for TransientValue<T> {
343 fn decode<D: Decoder<Context = Context>>(_decoder: &mut D) -> Result<Self, DecodeError> {
344 Err(DecodeError::Other("cannot decode transient task inputs"))
345 }
346}
347
348impl<T> TaskInput for TransientInstance<T>
349where
350 T: Sync + Send + TraceRawVcs + 'static,
351{
352 fn is_transient(&self) -> bool {
353 true
354 }
355}
356
357impl<T> Encode for TransientInstance<T> {
358 fn encode<E: Encoder>(&self, _encoder: &mut E) -> Result<(), EncodeError> {
359 Err(EncodeError::Other("cannot encode transient task inputs"))
360 }
361}
362
363impl<Context, T> Decode<Context> for TransientInstance<T> {
364 fn decode<D: Decoder<Context = Context>>(_decoder: &mut D) -> Result<Self, DecodeError> {
365 Err(DecodeError::Other("cannot decode transient task inputs"))
366 }
367}
368
369impl<K, V> TaskInput for BTreeMap<K, V>
370where
371 K: TaskInput + Ord,
372 V: TaskInput,
373{
374 async fn resolve_input(&self) -> Result<Self> {
375 let mut new_map = BTreeMap::new();
376 for (k, v) in self {
377 new_map.insert(
378 TaskInput::resolve_input(k).await?,
379 TaskInput::resolve_input(v).await?,
380 );
381 }
382 Ok(new_map)
383 }
384
385 fn is_resolved(&self) -> bool {
386 self.iter()
387 .all(|(k, v)| TaskInput::is_resolved(k) && TaskInput::is_resolved(v))
388 }
389
390 fn is_transient(&self) -> bool {
391 self.iter()
392 .any(|(k, v)| TaskInput::is_transient(k) || TaskInput::is_transient(v))
393 }
394}
395
396impl<T> TaskInput for BTreeSet<T>
397where
398 T: TaskInput + Ord,
399{
400 async fn resolve_input(&self) -> Result<Self> {
401 let mut new_set = BTreeSet::new();
402 for value in self {
403 new_set.insert(TaskInput::resolve_input(value).await?);
404 }
405 Ok(new_set)
406 }
407
408 fn is_resolved(&self) -> bool {
409 self.iter().all(TaskInput::is_resolved)
410 }
411
412 fn is_transient(&self) -> bool {
413 self.iter().any(TaskInput::is_transient)
414 }
415}
416
417impl<K, V> TaskInput for FrozenMap<K, V>
418where
419 K: TaskInput + Ord + 'static,
420 V: TaskInput + 'static,
421{
422 async fn resolve_input(&self) -> Result<Self> {
423 let mut new_entries = Vec::with_capacity(self.len());
424 for (k, v) in self {
425 new_entries.push((
426 TaskInput::resolve_input(k).await?,
427 TaskInput::resolve_input(v).await?,
428 ));
429 }
430 Ok(Self::from(new_entries))
432 }
433
434 fn is_resolved(&self) -> bool {
435 self.iter()
436 .all(|(k, v)| TaskInput::is_resolved(k) && TaskInput::is_resolved(v))
437 }
438
439 fn is_transient(&self) -> bool {
440 self.iter()
441 .any(|(k, v)| TaskInput::is_transient(k) || TaskInput::is_transient(v))
442 }
443}
444
445impl<T> TaskInput for FrozenSet<T>
446where
447 T: TaskInput + Ord + 'static,
448{
449 async fn resolve_input(&self) -> Result<Self> {
450 let mut new_set = Vec::with_capacity(self.len());
451 for value in self {
452 new_set.push(TaskInput::resolve_input(value).await?);
453 }
454 Ok(Self::from_iter(new_set))
455 }
456
457 fn is_resolved(&self) -> bool {
458 self.iter().all(TaskInput::is_resolved)
459 }
460
461 fn is_transient(&self) -> bool {
462 self.iter().any(TaskInput::is_transient)
463 }
464}
465
466#[derive(Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs)]
469pub struct EitherTaskInput<L, R>(pub Either<L, R>);
470
471impl<L, R> Deref for EitherTaskInput<L, R> {
472 type Target = Either<L, R>;
473
474 fn deref(&self) -> &Self::Target {
475 &self.0
476 }
477}
478
479impl<L, R> DerefMut for EitherTaskInput<L, R> {
480 fn deref_mut(&mut self) -> &mut Self::Target {
481 &mut self.0
482 }
483}
484
485impl<L, R> Encode for EitherTaskInput<L, R>
486where
487 L: Encode,
488 R: Encode,
489{
490 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
491 turbo_bincode::either::encode(self, encoder)
492 }
493}
494
495impl<Context, L, R> Decode<Context> for EitherTaskInput<L, R>
496where
497 L: Decode<Context>,
498 R: Decode<Context>,
499{
500 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
501 turbo_bincode::either::decode(decoder).map(Self)
502 }
503}
504
505impl<L, R> TaskInput for EitherTaskInput<L, R>
506where
507 L: TaskInput,
508 R: TaskInput,
509{
510 fn resolve_input(&self) -> impl Future<Output = Result<Self>> + Send + '_ {
511 self.as_ref().map_either(
512 |l| async move { anyhow::Ok(Self(Either::Left(l.resolve_input().await?))) },
513 |r| async move { anyhow::Ok(Self(Either::Right(r.resolve_input().await?))) },
514 )
515 }
516
517 fn is_resolved(&self) -> bool {
518 self.as_ref()
519 .either(TaskInput::is_resolved, TaskInput::is_resolved)
520 }
521
522 fn is_transient(&self) -> bool {
523 self.as_ref()
524 .either(TaskInput::is_transient, TaskInput::is_transient)
525 }
526}
527
528macro_rules! tuple_impls {
529 ( $( $name:ident )+ ) => {
530 impl<$($name: TaskInput),+> TaskInput for ($($name,)+)
531 where $($name: TaskInput),+
532 {
533 #[allow(non_snake_case)]
534 fn is_resolved(&self) -> bool {
535 let ($($name,)+) = self;
536 $($name.is_resolved() &&)+ true
537 }
538
539 #[allow(non_snake_case)]
540 fn is_transient(&self) -> bool {
541 let ($($name,)+) = self;
542 $($name.is_transient() ||)+ false
543 }
544
545 #[allow(non_snake_case)]
546 async fn resolve_input(&self) -> Result<Self> {
547 let ($($name,)+) = self;
548 Ok(($($name.resolve_input().await?,)+))
549 }
550 }
551 };
552}
553
554tuple_impls! { A }
556tuple_impls! { A B }
557tuple_impls! { A B C }
558tuple_impls! { A B C D }
559tuple_impls! { A B C D E }
560tuple_impls! { A B C D E F }
561tuple_impls! { A B C D E F G }
562tuple_impls! { A B C D E F G H }
563tuple_impls! { A B C D E F G H I }
564tuple_impls! { A B C D E F G H I J }
565tuple_impls! { A B C D E F G H I J K }
566tuple_impls! { A B C D E F G H I J K L }
567
568#[cfg(test)]
569mod tests {
570 use turbo_rcstr::rcstr;
571
572 use super::*;
573
574 fn assert_task_input<T>(_: T)
575 where
576 T: TaskInput,
577 {
578 }
579
580 #[test]
581 fn test_no_fields() -> Result<()> {
582 #[turbo_tasks::task_input]
583 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
584 struct NoFields;
585
586 assert_task_input(NoFields);
587 Ok(())
588 }
589
590 #[test]
591 fn test_one_unnamed_field() -> Result<()> {
592 #[turbo_tasks::task_input]
593 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
594 struct OneUnnamedField(u32);
595
596 assert_task_input(OneUnnamedField(42));
597 Ok(())
598 }
599
600 #[test]
601 fn test_multiple_unnamed_fields() -> Result<()> {
602 #[turbo_tasks::task_input]
603 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
604 struct MultipleUnnamedFields(u32, RcStr);
605
606 assert_task_input(MultipleUnnamedFields(42, rcstr!("42")));
607 Ok(())
608 }
609
610 #[test]
611 fn test_one_named_field() -> Result<()> {
612 #[turbo_tasks::task_input]
613 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
614 struct OneNamedField {
615 named: u32,
616 }
617
618 assert_task_input(OneNamedField { named: 42 });
619 Ok(())
620 }
621
622 #[test]
623 fn test_multiple_named_fields() -> Result<()> {
624 #[turbo_tasks::task_input]
625 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
626 struct MultipleNamedFields {
627 named: u32,
628 other: RcStr,
629 }
630
631 assert_task_input(MultipleNamedFields {
632 named: 42,
633 other: rcstr!("42"),
634 });
635 Ok(())
636 }
637
638 #[test]
639 fn test_generic_field() -> Result<()> {
640 #[turbo_tasks::task_input]
641 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
642 struct GenericField<T>(T);
643
644 assert_task_input(GenericField(42));
645 assert_task_input(GenericField(rcstr!("42")));
646 Ok(())
647 }
648
649 #[turbo_tasks::task_input]
650 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
651 enum OneVariant {
652 Variant,
653 }
654
655 #[test]
656 fn test_one_variant() -> Result<()> {
657 assert_task_input(OneVariant::Variant);
658 Ok(())
659 }
660
661 #[test]
662 fn test_multiple_variants() -> Result<()> {
663 #[turbo_tasks::task_input]
664 #[derive(Clone, PartialEq, Eq, Hash, Debug, Encode, Decode, TraceRawVcs)]
665 enum MultipleVariants {
666 Variant1,
667 Variant2,
668 }
669
670 assert_task_input(MultipleVariants::Variant2);
671 Ok(())
672 }
673
674 #[turbo_tasks::task_input]
675 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
676 enum MultipleVariantsAndHeterogeneousFields {
677 Variant1,
678 Variant2(u32),
679 Variant3 { named: u32 },
680 Variant4(u32, RcStr),
681 Variant5 { named: u32, other: RcStr },
682 }
683
684 #[test]
685 fn test_multiple_variants_and_heterogeneous_fields() -> Result<()> {
686 assert_task_input(MultipleVariantsAndHeterogeneousFields::Variant5 {
687 named: 42,
688 other: rcstr!("42"),
689 });
690 Ok(())
691 }
692
693 #[test]
694 fn test_nested_variants() -> Result<()> {
695 #[turbo_tasks::task_input]
696 #[derive(Clone, Eq, PartialEq, Hash, Debug, Encode, Decode, TraceRawVcs)]
697 enum NestedVariants {
698 Variant1,
699 Variant2(MultipleVariantsAndHeterogeneousFields),
700 Variant3 { named: OneVariant },
701 Variant4(OneVariant, RcStr),
702 Variant5 { named: OneVariant, other: RcStr },
703 }
704
705 assert_task_input(NestedVariants::Variant5 {
706 named: OneVariant::Variant,
707 other: rcstr!("42"),
708 });
709 assert_task_input(NestedVariants::Variant2(
710 MultipleVariantsAndHeterogeneousFields::Variant5 {
711 named: 42,
712 other: rcstr!("42"),
713 },
714 ));
715 Ok(())
716 }
717}