mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Replace ShouldNotImplDomObject
with NoDomObjectInDomObject
(#33627)
This is https://github.com/jdm/servo/pull/1 rebased on servo/servo Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
cd803c8341
commit
634dbd2d78
1 changed files with 33 additions and 20 deletions
|
@ -5,8 +5,9 @@
|
||||||
#![recursion_limit = "128"]
|
#![recursion_limit = "128"]
|
||||||
|
|
||||||
use quote::{quote, TokenStreamExt};
|
use quote::{quote, TokenStreamExt};
|
||||||
use syn::parse_quote;
|
|
||||||
|
|
||||||
|
/// First field of DomObject must be either reflector or another dom_struct,
|
||||||
|
/// all other fields must not implement DomObject
|
||||||
#[proc_macro_derive(DomObject)]
|
#[proc_macro_derive(DomObject)]
|
||||||
pub fn expand_token_stream(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn expand_token_stream(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let input = syn::parse(input).unwrap();
|
let input = syn::parse(input).unwrap();
|
||||||
|
@ -65,33 +66,45 @@ fn expand_dom_object(input: syn::DeriveInput) -> proc_macro2::TokenStream {
|
||||||
crate::DomObject::reflector(self) == crate::DomObject::reflector(other)
|
crate::DomObject::reflector(self) == crate::DomObject::reflector(other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generic trait with a blanket impl over `()` for all types.
|
||||||
|
// becomes ambiguous if impl
|
||||||
|
trait NoDomObjectInDomObject<A> {
|
||||||
|
// Required for actually being able to reference the trait.
|
||||||
|
fn some_item() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> NoDomObjectInDomObject<()> for T {}
|
||||||
|
|
||||||
|
// Used for the specialized impl when DomObject is implemented.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct Invalid;
|
||||||
|
// forbids DomObject
|
||||||
|
impl<T> NoDomObjectInDomObject<Invalid> for T where T: ?Sized + crate::DomObject {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut params = proc_macro2::TokenStream::new();
|
let mut params = proc_macro2::TokenStream::new();
|
||||||
params.append_separated(input.generics.type_params().map(|param| ¶m.ident), ", ");
|
params.append_separated(
|
||||||
|
input.generics.type_params().map(|param| ¶m.ident),
|
||||||
|
quote! {,},
|
||||||
|
);
|
||||||
|
|
||||||
// For each field in the struct, we implement ShouldNotImplDomObject for a
|
items.append_all(field_types.iter().enumerate().map(|(i, ty)| {
|
||||||
// pair of all the type parameters of the DomObject and and the field type.
|
let s = syn::Ident::new(&format!("S{i}"), proc_macro2::Span::call_site());
|
||||||
// This allows us to support parameterized DOM objects
|
|
||||||
// such as IteratorIterable<T>.
|
|
||||||
items.append_all(field_types.iter().map(|ty| {
|
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics ShouldNotImplDomObject for ((#params), #ty) #where_clause {}
|
struct #s<#params>(#params);
|
||||||
|
|
||||||
|
impl #impl_generics #s<#params> #where_clause {
|
||||||
|
fn f() {
|
||||||
|
// If there is only one specialized trait impl, type inference with
|
||||||
|
// `_` can be resolved and this can compile. Fails to compile if
|
||||||
|
// ty implements `NoDomObjectInDomObject<Invalid>`.
|
||||||
|
let _ = <#ty as NoDomObjectInDomObject<_>>::some_item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut generics = input.generics.clone();
|
|
||||||
generics.params.push(parse_quote!(
|
|
||||||
__T: crate::DomObject
|
|
||||||
));
|
|
||||||
|
|
||||||
let (impl_generics, _, where_clause) = generics.split_for_impl();
|
|
||||||
|
|
||||||
items.append_all(quote! {
|
|
||||||
trait ShouldNotImplDomObject {}
|
|
||||||
impl #impl_generics ShouldNotImplDomObject for ((#params), __T) #where_clause {}
|
|
||||||
});
|
|
||||||
|
|
||||||
let dummy_const = syn::Ident::new(
|
let dummy_const = syn::Ident::new(
|
||||||
&format!("_IMPL_DOMOBJECT_FOR_{}", name),
|
&format!("_IMPL_DOMOBJECT_FOR_{}", name),
|
||||||
proc_macro2::Span::call_site(),
|
proc_macro2::Span::call_site(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue