use std::env;
use std::fs::File;
use std::io::{Read, Write};
+use std::iter::FromIterator;
use std::process;
use proc_macro2::Span;
'alias_impls: for (alias_resolved, arguments) in aliases {
let mut new_ty_generics = Vec::new();
+ let mut new_ty_bounds = Vec::new();
let mut need_generics = false;
let alias_resolver_override;
alias_module, &types.crate_types.lib_ast.modules.get(alias_module).unwrap().items);
&alias_resolver_override
} else { &types.types };/*.maybe_resolve_path(&alias, None).unwrap();*/
+ let mut where_clause = Some(syn::WhereClause {
+ where_token: syn::Token![where](Span::call_site()),
+ predicates: syn::punctuated::Punctuated::new()
+ });
for (idx, gen) in i.generics.params.iter().enumerate() {
match gen {
syn::GenericParam::Type(type_param) => {
if let syn::PathArguments::AngleBracketed(ref t) = &arguments {
assert!(idx < t.args.len());
if let syn::GenericArgument::Type(syn::Type::Path(p)) = &t.args[idx] {
- if let Some(generic_arg) = alias_resolver.maybe_resolve_path(&p.path, None) {
+ let generic_bound = types.maybe_resolve_path(&trait_bound.path, None)
+ .unwrap_or_else(|| format!("{}::{}", types.module_path, single_ident_generic_path_to_ident(&trait_bound.path).unwrap()));
+ if let Some(generic_arg) = alias_resolver.maybe_resolve_path(&p.path, None) {
new_ty_generics.push((type_param.ident.clone(), syn::Type::Path(p.clone())));
- let generic_bound = types.maybe_resolve_path(&trait_bound.path, None)
- .unwrap_or_else(|| format!("{}::{}", types.module_path, single_ident_generic_path_to_ident(&trait_bound.path).unwrap()));
if let Some(traits_impld) = types.crate_types.trait_impls.get(&generic_arg) {
for trait_impld in traits_impld {
if *trait_impld == generic_bound { continue 'bounds_check; }
continue 'alias_impls;
}
} else if gen_types.is_some() {
- new_ty_generics.push((type_param.ident.clone(),
- gen_types.as_ref().resolve_type(&syn::Type::Path(p.clone())).clone()));
+ let resp = types.maybe_resolve_path(&p.path, gen_types.as_ref());
+ if generic_bound == "core::ops::Deref" && resp.is_some() {
+ new_ty_bounds.push((type_param.ident.clone(),
+ string_path_to_syn_path("core::ops::Deref")));
+ let mut bounds = syn::punctuated::Punctuated::new();
+ bounds.push(syn::TypeParamBound::Trait(syn::TraitBound {
+ paren_token: None,
+ modifier: syn::TraitBoundModifier::None,
+ lifetimes: None,
+ path: string_path_to_syn_path(&types.resolve_path(&p.path, gen_types.as_ref())),
+ }));
+ let mut path = string_path_to_syn_path(&format!("{}::Target", type_param.ident));
+ path.leading_colon = None;
+ where_clause.as_mut().unwrap().predicates.push(syn::WherePredicate::Type(syn::PredicateType {
+ lifetimes: None,
+ bounded_ty: syn::Type::Path(syn::TypePath { qself: None, path }),
+ colon_token: syn::Token![:](Span::call_site()),
+ bounds,
+ }));
+ } else {
+ new_ty_generics.push((type_param.ident.clone(),
+ gen_types.as_ref().resolve_type(&syn::Type::Path(p.clone())).clone()));
+ }
need_generics = true;
} else {
unimplemented!();
let alias_generics = types.crate_types.opaques.get(&alias_resolved).unwrap().1;
// If we need generics on the alias, create impl generic bounds...
- assert_eq!(new_ty_generics.len(), i.generics.params.len());
+ assert_eq!(new_ty_generics.len() + new_ty_bounds.len(), i.generics.params.len());
let mut args = syn::punctuated::Punctuated::new();
for (ident, param) in new_ty_generics.drain(..) {
// TODO: We blindly assume that generics in the type alias and
default: Some(param),
}));
}
+ for (ident, param) in new_ty_bounds.drain(..) {
+ // TODO: We blindly assume that generics in the type alias and
+ // the aliased type have the same names, which we really shouldn't.
+ if alias_generics.params.iter().any(|generic|
+ if let syn::GenericParam::Type(t) = generic { t.ident == ident } else { false })
+ {
+ args.push(parse_quote!(#ident));
+ }
+ params.push(syn::GenericParam::Type(syn::TypeParam {
+ attrs: Vec::new(),
+ ident,
+ colon_token: Some(syn::token::Colon(Span::call_site())),
+ bounds: syn::punctuated::Punctuated::from_iter(
+ Some(syn::TypeParamBound::Trait(syn::TraitBound {
+ path: param, paren_token: None, lifetimes: None,
+ modifier: syn::TraitBoundModifier::None,
+ }))
+ ),
+ eq_token: None,
+ default: None,
+ }));
+ }
// ... and swap the last segment of the impl self_ty to use the generic bounds.
let mut res = alias.clone();
res.segments.last_mut().unwrap().arguments = syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
lt_token: None,
params,
gt_token: None,
- where_clause: None,
+ where_clause,
},
impl_token: syn::Token![impl](Span::call_site()),
items: i.items.clone(),