abi_stable_derive/impl_interfacetype/
macro_impl.rs1use super::*;
2
3use as_derive_utils::return_spanned_err;
4
5use proc_macro2::TokenStream as TokenStream2;
6
7use syn::{ImplItem, ImplItemType, ItemImpl, Visibility};
8
9pub fn the_macro(mut impl_: ItemImpl) -> Result<TokenStream2, syn::Error> {
14 let interfacetype: syn::Ident = syn::parse_str("InterfaceType").expect("BUG");
15
16 let mut const_name = (&impl_.self_ty).into_token_stream().to_string();
17 const_name.retain(|c| c.is_alphanumeric());
18 const_name.insert_str(0, "_impl_InterfaceType");
19 let const_name = parse_str_as_ident(&const_name);
20
21 let interface_path_s = impl_.trait_.as_ref().map(|x| &x.1.segments);
22 let is_interface_type = interface_path_s
23 .and_then(|x| x.last())
24 .map_or(false, |path_| path_.ident == interfacetype);
25
26 if !is_interface_type {
27 return_spanned_err!(
28 impl_,
29 "expected 'impl<...> InterfaceType for {} ' ",
30 impl_.self_ty.to_token_stream(),
31 );
32 }
33
34 let mut default_map = TRAIT_LIST
36 .iter()
37 .map(|ut| {
38 (
39 parse_str_as_ident(ut.name),
40 DefaultVal::from(ut.which_trait.default_value()),
41 )
42 })
43 .collect::<HashMap<_, _>>();
44
45 for item in &mut impl_.items {
51 if let ImplItem::Type(assoc_ty) = item {
52 assert_ne!(
53 assoc_ty.ident, "define_this_in_the_impl_InterfaceType_macro",
54 "you are not supposed to define\n\t\
55 the 'define_this_in_the_impl_InterfaceType_macro' associated type yourself"
56 );
57 default_map.remove(&assoc_ty.ident);
58
59 let old_ty = &assoc_ty.ty;
60 let name = &assoc_ty.ident;
61 let span = name.span();
62
63 assoc_ty.ty =
64 syn::Type::Verbatim(quote_spanned!(span=> ImplFrom<#old_ty, trait_marker::#name> ));
65 }
66 }
67
68 default_map.insert(private_associated_type(), DefaultVal::Hidden);
69
70 for (key, default_) in default_map {
73 let mut attrs = Vec::<syn::Attribute>::new();
74
75 let span = key.span();
76
77 let ty = match default_ {
78 DefaultVal::Unimplemented => quote_spanned!(span=> Unimplemented<trait_marker::#key> ),
79 DefaultVal::Implemented => quote_spanned!(span=> Implemented<trait_marker::#key> ),
80 DefaultVal::Hidden => {
81 attrs.extend(parse_syn_attributes("#[doc(hidden)]").expect("BUG"));
82 quote_spanned!(span=> () )
83 }
84 }
85 .piped(syn::Type::Verbatim);
86
87 let defaulted = ImplItemType {
88 attrs,
89 vis: Visibility::Inherited,
90 defaultness: None,
91 type_token: Default::default(),
92 ident: key,
93 generics: Default::default(),
94 eq_token: Default::default(),
95 ty,
96 semi_token: Default::default(),
97 };
98 impl_.items.push(ImplItem::Type(defaulted))
99 }
100
101 quote!(
102 const #const_name:()={
103 use ::abi_stable::derive_macro_reexports::{
104 Implemented,
105 Unimplemented,
106 ImplFrom,
107 trait_marker,
108 };
109
110 #impl_
111 };
112 )
113 .piped(Ok)
114}
115
116pub fn parse_syn_attributes(str_: &str) -> Result<Vec<syn::Attribute>, syn::Error> {
120 syn::parse_str::<ParseOuter>(str_).map(|x| x.attributes)
121}
122
123struct ParseOuter {
124 attributes: Vec<syn::Attribute>,
125}
126
127impl syn::parse::Parse for ParseOuter {
128 fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
129 Ok(Self {
130 attributes: syn::Attribute::parse_outer(input)?,
131 })
132 }
133}