turbo_tasks/
macro_helpers.rs

1//! Runtime helpers for [turbo-tasks-macro].
2
3use std::ptr::DynMetadata;
4
5pub use async_trait::async_trait;
6pub use once_cell::sync::{Lazy, OnceCell};
7pub use serde;
8pub use shrink_to_fit;
9pub use tracing;
10
11use crate::{
12    FxDashMap, NonLocalValue, RawVc, TaskInput, TaskPersistence, ValueTypeId, Vc, VcValueTrait,
13    debug::ValueDebugFormatString, task::TaskOutput,
14};
15pub use crate::{
16    magic_any::MagicAny,
17    manager::{find_cell_by_type, notify_scheduled_tasks, spawn_detached_for_testing},
18    native_function::{FunctionMeta, NativeFunction, downcast_args_owned, downcast_args_ref},
19};
20
21#[inline(never)]
22pub async fn value_debug_format_field(value: ValueDebugFormatString<'_>) -> String {
23    match value.try_to_value_debug_string().await {
24        Ok(result) => match result.await {
25            Ok(result) => result.to_string(),
26            Err(err) => format!("{err:?}"),
27        },
28        Err(err) => format!("{err:?}"),
29    }
30}
31
32pub fn get_non_local_persistence_from_inputs(inputs: &impl TaskInput) -> TaskPersistence {
33    if inputs.is_transient() {
34        TaskPersistence::Transient
35    } else {
36        TaskPersistence::Persistent
37    }
38}
39
40pub fn get_non_local_persistence_from_inputs_and_this(
41    this: RawVc,
42    inputs: &impl TaskInput,
43) -> TaskPersistence {
44    if this.is_transient() || inputs.is_transient() {
45        TaskPersistence::Transient
46    } else {
47        TaskPersistence::Persistent
48    }
49}
50
51pub fn assert_returns_non_local_value<ReturnType, Rv>()
52where
53    ReturnType: TaskOutput<Return = Vc<Rv>>,
54    Rv: NonLocalValue + Send,
55{
56}
57
58pub fn assert_argument_is_non_local_value<Argument: NonLocalValue>() {}
59
60#[macro_export]
61macro_rules! stringify_path {
62    ($path:path) => {
63        stringify!($path)
64    };
65}
66
67/// Rexport std::ptr::metadata so not every crate needs to enable the feature when they use our
68/// macros.
69#[inline(always)]
70pub fn metadata<T: ?Sized>(ptr: *const T) -> <T as std::ptr::Pointee>::Metadata {
71    // Ideally we would just `pub use std::ptr::metadata;` but this doesn't seem to work.
72    std::ptr::metadata(ptr)
73}
74
75/// A registry of all the impl vtables for a given VcValue trait
76/// This is constructed in the macro gencode and populated by the registry.
77#[derive(Default)]
78pub struct VTableRegistry<T: ?Sized> {
79    map: FxDashMap<ValueTypeId, std::ptr::DynMetadata<T>>,
80}
81
82impl<T: ?Sized> VTableRegistry<T> {
83    pub fn new() -> Self {
84        Self {
85            map: FxDashMap::default(),
86        }
87    }
88
89    pub(crate) fn register(&self, id: ValueTypeId, vtable: std::ptr::DynMetadata<T>) {
90        let prev = self.map.insert(id, vtable);
91        debug_assert!(prev.is_none(), "{id} was already registered");
92    }
93
94    pub(crate) fn get(&self, id: ValueTypeId) -> DynMetadata<T> {
95        *self.map.get(&id).unwrap().value()
96    }
97}
98
99pub fn register_trait_impl<V: 'static + ?Sized, T: VcValueTrait<ValueTrait = V>>(
100    id: ValueTypeId,
101    metadata: std::ptr::DynMetadata<V>,
102) {
103    <T as VcValueTrait>::get_impl_vtables().register(id, metadata);
104}