Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for #[turbo_tasks::value(resolved)] and #[turbo_tasks::value_trait(resolved)] #8720

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion crates/turbo-tasks-macros-shared/src/value_trait_arguments.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use proc_macro2::Span;
use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
spanned::Spanned,
Meta, Token,
};

Expand All @@ -10,11 +12,18 @@ pub struct ValueTraitArguments {
/// Whether the macro should generate a `ValueDebug`-like `dbg()`
/// implementation on the trait's `Vc`.
pub debug: bool,
/// Should the trait have a `turbo_tasks::ResolvedValue` constraint?
///
/// `Some(...)` if enabled, containing the span that enabled the constraint.
pub resolved: Option<Span>,
}

impl Default for ValueTraitArguments {
fn default() -> Self {
Self { debug: true }
Self {
debug: true,
resolved: None,
}
}
}

Expand All @@ -31,6 +40,9 @@ impl Parse for ValueTraitArguments {
Some("no_debug") => {
result.debug = false;
}
Some("resolved") => {
result.resolved = Some(meta.span());
}
_ => {
return Err(syn::Error::new_spanned(meta, "unknown parameter"));
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions crates/turbo-tasks-macros-tests/tests/trybuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,17 @@ fn derive_resolved_value() {
t.pass("tests/derive_resolved_value/pass_*.rs");
t.compile_fail("tests/derive_resolved_value/fail_*.rs");
}

#[test]
fn value() {
let t = trybuild::TestCases::new();
t.pass("tests/value/pass_*.rs");
t.compile_fail("tests/value/fail_*.rs");
}

#[test]
fn value_trait() {
let t = trybuild::TestCases::new();
t.pass("tests/value_trait/pass_*.rs");
t.compile_fail("tests/value_trait/fail_*.rs");
}
13 changes: 13 additions & 0 deletions crates/turbo-tasks-macros-tests/tests/value/fail_resolved.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![feature(arbitrary_self_types)]

use turbo_tasks::Vc;

#[turbo_tasks::value(resolved)]
struct MyValue {
value: Vc<i32>,
}

fn main() {
let v = MyValue { value: Vc::cell(0) };
let _ = v.value;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions crates/turbo-tasks-macros-tests/tests/value/pass_resolved.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#![feature(arbitrary_self_types)]

#[turbo_tasks::value(resolved)]
struct MyValue {
value: i32,
}

fn expects_resolved<T: turbo_tasks::ResolvedValue>(value: T) {}

fn main() {
let v = MyValue { value: 0 };
expects_resolved(v);
let _ = v.value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![feature(arbitrary_self_types)]

#[turbo_tasks::value_trait(resolved)]
trait MyTrait {}

fn expects_resolved<T: turbo_tasks::ResolvedValue + ?Sized>() {}

fn main() {
expects_resolved::<&dyn MyTrait>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn derive_resolved_value(input: TokenStream) -> TokenStream {

let (impl_generics, ty_generics, where_clause) = derive_input.generics.split_for_impl();
quote! {
unsafe impl #impl_generics ::turbo_tasks::ResolvedValue
unsafe impl #impl_generics turbo_tasks::ResolvedValue
for #ident #ty_generics #where_clause {}
#assertions
}
Expand Down Expand Up @@ -47,7 +47,9 @@ fn assert_fields_impl_resolved_value(generics: &Generics, data: &Data) -> TokenS
struct DeriveResolvedValueAssertion #impl_generics (#(#field_types),*) #where_clause;

impl #impl_generics DeriveResolvedValueAssertion #ty_generics #where_clause {
fn assert_impl_resolved_value<ExpectedResolvedValue: ResolvedValue + ?Sized>() {}
fn assert_impl_resolved_value<
ExpectedResolvedValue: turbo_tasks::ResolvedValue + ?Sized
>() {}
fn field_types() {
#(#assertion_calls)*
}
Expand Down
1 change: 0 additions & 1 deletion crates/turbo-tasks-macros/src/derive/value_macro.rs

This file was deleted.

25 changes: 25 additions & 0 deletions crates/turbo-tasks-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream {
///
/// Example: `#[turbo_tasks::value(transparent)]`
///
/// ### `resolved`
///
/// A shorthand syntax for
/// [`#[derive(turbo_tasks::ResolvedValue)]`][macro@turbo_tasks::ResolvedValue]
///
/// Example: `#[turbo_tasks::value(resolved)]`
///
/// TODO: add more documentation: presets, traits
#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)]
#[proc_macro_error]
Expand All @@ -127,6 +134,24 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
value_macro::value(args, input)
}

/// Allows this trait to be used as part of a trait object inside of a value
/// cell, in the form of `Vc<dyn MyTrait>`.
///
/// ## Arguments
///
/// Example: `#[turbo_tasks::value_trait(no_debug, resolved)]`
///
/// ### 'no_debug`
///
/// Disables the automatic implementation of [`turbo_tasks::debug::ValueDebug`].
///
/// Example: `#[turbo_tasks::value_trait(no_debug)]`
///
/// ### 'resolved`
///
/// Adds [`turbo_tasks::ResolvedValue`] as a supertrait of this trait.
///
/// Example: `#[turbo_tasks::value_trait(resolved)]`
#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)]
#[proc_macro_error]
#[proc_macro_attribute]
Expand Down
36 changes: 31 additions & 5 deletions crates/turbo-tasks-macros/src/value_macro.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::sync::OnceLock;

use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::{quote, ToTokens};
use proc_macro2::{Ident, Span};
use quote::{quote, quote_spanned, ToTokens};
use regex::Regex;
use syn::{
parse::{Parse, ParseStream},
Expand Down Expand Up @@ -110,6 +110,10 @@ struct ValueArguments {
cell_mode: CellMode,
manual_eq: bool,
transparent: bool,
/// Should we `#[derive(turbo_tasks::ResolvedValue)]`?
///
/// `Some(...)` if enabled, containing the span that enabled the derive.
resolved: Option<Span>,
}

impl Parse for ValueArguments {
Expand All @@ -119,6 +123,7 @@ impl Parse for ValueArguments {
into_mode: IntoMode::None,
cell_mode: CellMode::Shared,
manual_eq: false,
resolved: None,
transparent: false,
};
let punctuated: Punctuated<Meta, Token![,]> = input.parse_terminated(Meta::parse)?;
Expand Down Expand Up @@ -174,6 +179,9 @@ impl Parse for ValueArguments {
("transparent", Meta::Path(_)) => {
result.transparent = true;
}
("resolved", Meta::Path(path)) => {
result.resolved = Some(path.span());
}
(_, meta) => {
return Err(Error::new_spanned(
&meta,
Expand All @@ -199,6 +207,7 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
cell_mode,
manual_eq,
transparent,
resolved,
} = parse_macro_input!(args as ValueArguments);

let mut inner_type = None;
Expand Down Expand Up @@ -328,7 +337,12 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
}
}
SerializationMode::Auto | SerializationMode::AutoForInput => quote! {
#[derive(turbo_tasks::trace::TraceRawVcs, serde::Serialize, serde::Deserialize)]
#[derive(
turbo_tasks::trace::TraceRawVcs,
turbo_tasks::macro_helpers::serde::Serialize,
turbo_tasks::macro_helpers::serde::Deserialize,
)]
#[serde(crate = "turbo_tasks::macro_helpers::serde")]
},
};
let debug_derive = if inner_type.is_some() {
Expand All @@ -338,7 +352,10 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
}
} else {
quote! {
#[derive(turbo_tasks::debug::ValueDebugFormat, turbo_tasks::debug::internal::ValueDebug)]
#[derive(
turbo_tasks::debug::ValueDebugFormat,
turbo_tasks::debug::internal::ValueDebug,
)]
}
};
let eq_derive = if manual_eq {
Expand All @@ -348,6 +365,14 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
#[derive(PartialEq, Eq)]
)
};
let resolved_derive = if let Some(span) = resolved {
quote_spanned!(
span =>
#[derive(turbo_tasks::ResolvedValue)]
)
} else {
quote!()
};

let new_value_type = match serialization_mode {
SerializationMode::None => quote! {
Expand Down Expand Up @@ -406,8 +431,9 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {

let expanded = quote! {
#derive
#eq_derive
#debug_derive
#eq_derive
#resolved_derive
#item

impl #ident {
Expand Down
18 changes: 13 additions & 5 deletions crates/turbo-tasks-macros/src/value_trait_macro.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use proc_macro::TokenStream;
use proc_macro2::{Ident, TokenStream as TokenStream2};
use quote::quote;
use quote::{quote, quote_spanned};
use syn::{
parse_macro_input, parse_quote, spanned::Spanned, ExprPath, ItemTrait, TraitItem,
TraitItemMethod,
Expand All @@ -13,7 +13,7 @@ use turbo_tasks_macros_shared::{
use crate::func::{DefinitionContext, NativeFn, TurboFn};

pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream {
let ValueTraitArguments { debug } = parse_macro_input!(args as ValueTraitArguments);
let ValueTraitArguments { debug, resolved } = parse_macro_input!(args as ValueTraitArguments);

let item = parse_macro_input!(input as ItemTrait);

Expand Down Expand Up @@ -59,7 +59,7 @@ pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream {
.emit();
}

let supertraits = supertraits.into_iter().collect::<Vec<_>>();
let supertraits = supertraits.iter().collect::<Vec<_>>();

let trait_type_ident = get_trait_type_ident(trait_ident);
let trait_type_id_ident = get_trait_type_id_ident(trait_ident);
Expand Down Expand Up @@ -194,10 +194,18 @@ pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream {
quote! {}
};

let mut extended_supertraits = Vec::new();
if let Some(span) = resolved {
extended_supertraits.push(quote_spanned! {
span => turbo_tasks::ResolvedValue
});
}
extended_supertraits.push(quote!(::std::marker::Send));

let expanded = quote! {
#[must_use]
#(#attrs)*
#vis #trait_token #trait_ident: std::marker::Send + #(#supertraits)+*
#vis #trait_token #trait_ident: #(#supertraits +)* #(#extended_supertraits +)*
{
#(#items)*
}
Expand Down Expand Up @@ -230,7 +238,7 @@ pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream {

impl<T> #trait_ident for T
where
T: turbo_tasks::Dynamic<Box<dyn #trait_ident>> #(+ #supertraits)*,
T: turbo_tasks::Dynamic<Box<dyn #trait_ident>> + #(#supertraits +)* #(#extended_supertraits +)*,
{
#(#dynamic_trait_fns)*
}
Expand Down
1 change: 1 addition & 0 deletions crates/turbo-tasks/src/macro_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Runtime helpers for [turbo-tasks-macro].
pub use once_cell::sync::{Lazy, OnceCell};
pub use serde;
pub use tracing;

pub use super::manager::{find_cell_by_type, notify_scheduled_tasks, spawn_detached};
Expand Down
Loading