blanket/
default.rs

1use syn::spanned::Spanned;
2
3use super::utils::{prepend_function_path, signature_to_function_call};
4
5/// Update the method declarations of `trait_` to use default implementation from `default` module.
6pub fn defer_trait_methods(
7    mut trait_: syn::ItemTrait,
8    default: syn::Path,
9) -> syn::Result<syn::ItemTrait> {
10    for item in trait_.items.iter_mut() {
11        if let syn::TraitItem::Fn(ref mut m) = item {
12            // check no default implementation was provided for the current
13            // trait method
14            if m.default.is_some() {
15                let msg = "method should not have default implementation if using #[blanket(default = \"...\")]";
16                return Err(syn::Error::new(item.span(), msg));
17            }
18            // update the declaration to include a default implementation
19            // deferring the method call to a function call in the `default_mod`
20            // module
21            let mut call = signature_to_function_call(&m.sig)?;
22            prepend_function_path(&mut call, default.clone())?;
23            m.default = Some(syn::Block {
24                brace_token: syn::token::Brace::default(),
25                stmts: vec![syn::Stmt::Expr(syn::Expr::Call(call), None)],
26            });
27        }
28    }
29    Ok(trait_)
30}