aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs26
-rw-r--r--src/parse_attrs.rs29
2 files changed, 50 insertions, 5 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f8fdde8..017a58b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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;
}