diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 26 | ||||
-rw-r--r-- | src/parse_attrs.rs | 29 |
2 files changed, 50 insertions, 5 deletions
@@ -83,6 +83,15 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream { Err(err) => return err.to_compile_error().into(), }; + for dyn_supertrait in &method_attrs.dynamized_supertraits { + if !trait_bounds(&original_trait.supertraits).any(|t| t.path.is_ident(dyn_supertrait)) { + return abort!( + dyn_supertrait.span(), + "this trait definition has no such supertrait" + ); + } + } + let mut type_converter = TypeConverter { collections: method_attrs.collections, assoc_type_conversions: HashMap::new(), @@ -185,11 +194,20 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream { supertraits: original_trait .supertraits .iter() - .filter(|t| match t { - TypeParamBound::Trait(t) => !t.path.is_ident("Sized"), - TypeParamBound::Lifetime(_) => true, + .filter_map(|t| { + if let TypeParamBound::Trait(trait_bound) = t { + if let Some(ident) = trait_bound.path.get_ident() { + if ident == "Sized" { + return None; + } else if method_attrs.dynamized_supertraits.contains(ident) { + let mut bound = trait_bound.clone(); + bound.path.segments[0].ident = format_ident!("Dyn{}", ident); + return Some(TypeParamBound::Trait(bound)); + } + } + } + Some(t.clone()) }) - .cloned() .collect(), brace_token: Brace::default(), items: Vec::new(), diff --git a/src/parse_attrs.rs b/src/parse_attrs.rs index 03b5377..d9725ff 100644 --- a/src/parse_attrs.rs +++ b/src/parse_attrs.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use proc_macro2::{Group, TokenStream}; use quote::quote; @@ -33,6 +33,21 @@ pub struct TraitAttrs { pub blanket_impl_attrs: Vec<TokenStream>, pub dyn_trait_attrs: Vec<TokenStream>, pub collections: HashMap<Ident, usize>, + pub dynamized_supertraits: HashSet<Ident>, +} + +struct Dynamized { + ident: Ident, +} + +impl Parse for Dynamized { + fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { + let inner; + parenthesized!(inner in input); + Ok(Self { + ident: inner.parse()?, + }) + } } impl TraitAttrs { @@ -84,6 +99,18 @@ impl TraitAttrs { ), )); } + } else if attrs[i].path.is_ident("dynamized") { + let attr = attrs.remove(i); + let dynamized: Dynamized = syn::parse2(attr.tokens)?; + let span = dynamized.ident.span(); + + if !parsed.dynamized_supertraits.insert(dynamized.ident) { + // FUTURE: relax to warning once proc_macro::Diagnostic is stable + return Err(Error::new( + span, + format_args!("dynamized attribute is defined multiple times"), + )); + } } else { i += 1; } |