self_ty: Option<String>,
parent: Option<&'b GenericTypes<'b, 'b>>,
typed_generics: HashMap<&'a syn::Ident, String>,
- default_generics: HashMap<&'a syn::Ident, (syn::Type, syn::Type)>,
+ default_generics: HashMap<&'a syn::Ident, (syn::Type, syn::Type, syn::Type)>,
}
impl<'a, 'p: 'a> GenericTypes<'a, 'p> {
pub fn new(self_ty: Option<String>) -> Self {
if non_lifetimes_processed { return false; }
non_lifetimes_processed = true;
if path != "std::ops::Deref" && path != "core::ops::Deref" {
+ let p = string_path_to_syn_path(&path);
+ let ref_ty = parse_quote!(&#p);
+ let mut_ref_ty = parse_quote!(&mut #p);
+ self.default_generics.insert(&type_param.ident, (syn::Type::Path(syn::TypePath { qself: None, path: p }), ref_ty, mut_ref_ty));
new_typed_generics.insert(&type_param.ident, Some(path));
- } else if trait_bound.path.segments.len() == 1 {
+ } else {
// If we're templated on Deref<Target = ConcreteThing>, store
// the reference type in `default_generics` which handles full
// types and not just paths.
if let syn::PathArguments::AngleBracketed(ref args) =
trait_bound.path.segments[0].arguments {
+ assert_eq!(trait_bound.path.segments.len(), 1);
for subargument in args.args.iter() {
match subargument {
syn::GenericArgument::Lifetime(_) => {},
syn::GenericArgument::Binding(ref b) => {
if &format!("{}", b.ident) != "Target" { return false; }
let default = &b.ty;
- self.default_generics.insert(&type_param.ident, (parse_quote!(&#default), parse_quote!(&#default)));
+ self.default_generics.insert(&type_param.ident, (parse_quote!(&#default), parse_quote!(&#default), parse_quote!(&mut #default)));
break 'bound_loop;
},
_ => unimplemented!(),
}
if let Some(default) = type_param.default.as_ref() {
assert!(type_param.bounds.is_empty());
- self.default_generics.insert(&type_param.ident, (default.clone(), parse_quote!(&#default)));
+ self.default_generics.insert(&type_param.ident, (default.clone(), parse_quote!(&#default), parse_quote!(&mut #default)));
}
},
_ => {},
if p.qself.is_some() { return false; }
if p.path.leading_colon.is_some() { return false; }
let mut p_iter = p.path.segments.iter();
- if let Some(gen) = new_typed_generics.get_mut(&p_iter.next().unwrap().ident) {
+ let p_ident = &p_iter.next().unwrap().ident;
+ if let Some(gen) = new_typed_generics.get_mut(p_ident) {
if gen.is_some() { return false; }
if &format!("{}", p_iter.next().unwrap().ident) != "Target" {return false; }
if non_lifetimes_processed { return false; }
non_lifetimes_processed = true;
assert_simple_bound(&trait_bound);
- *gen = Some(types.resolve_path(&trait_bound.path, None));
+ let resolved = types.resolve_path(&trait_bound.path, None);
+ let ty = syn::Type::Path(syn::TypePath {
+ qself: None, path: string_path_to_syn_path(&resolved)
+ });
+ let ref_ty = parse_quote!(&#ty);
+ let mut_ref_ty = parse_quote!(&mut #ty);
+ if types.crate_types.traits.get(&resolved).is_some() {
+ self.default_generics.insert(p_ident, (ty, ref_ty, mut_ref_ty));
+ } else {
+ self.default_generics.insert(p_ident, (ref_ty.clone(), ref_ty, mut_ref_ty));
+ }
+
+ *gen = Some(resolved);
}
}
} else { return false; }
match ty {
syn::Type::Path(p) => {
if let Some(ident) = p.path.get_ident() {
- if let Some((ty, _)) = us.default_generics.get(ident) {
- return ty;
+ if let Some((ty, _, _)) = us.default_generics.get(ident) {
+ return self.resolve_type(ty);
}
}
},
- syn::Type::Reference(syn::TypeReference { elem, .. }) => {
+ syn::Type::Reference(syn::TypeReference { elem, mutability, .. }) => {
if let syn::Type::Path(p) = &**elem {
if let Some(ident) = p.path.get_ident() {
- if let Some((_, refty)) = us.default_generics.get(ident) {
- return refty;
+ if let Some((_, refty, mut_ref_ty)) = us.default_generics.get(ident) {
+ if mutability.is_some() {
+ return self.resolve_type(mut_ref_ty);
+ } else {
+ return self.resolve_type(refty);
+ }
}
}
}
new_path = format!("{}::{}{}", crate_name, $ident, $path_suffix);
let crate_name_ident = format_ident!("{}", crate_name);
path.push(parse_quote!(#crate_name_ident));
+ } else if format!("{}", $ident) == "self" {
+ let mut path_iter = partial_path.rsplitn(2, "::");
+ path_iter.next().unwrap();
+ new_path = path_iter.next().unwrap().to_owned();
} else {
new_path = format!("{}{}{}", partial_path, $ident, $path_suffix);
}
},
syn::UseTree::Name(n) => {
push_path!(n.ident, "");
- imports.insert(n.ident.clone(), (new_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path }));
+ let imported_ident = syn::Ident::new(new_path.rsplitn(2, "::").next().unwrap(), Span::call_site());
+ imports.insert(imported_ident, (new_path, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path }));
},
syn::UseTree::Group(g) => {
for i in g.items.iter() {
if let Some(t) = single_contained {
match t {
- syn::Type::Reference(_)|syn::Type::Path(_)|syn::Type::Slice(_) => {
+ syn::Type::Reference(_)|syn::Type::Path(_)|syn::Type::Slice(_)|syn::Type::Array(_) => {
let mut v = Vec::new();
let ret_ref = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
let s = String::from_utf8(v).unwrap();
syn::Type::Path(p) => {
let resolved = self.resolve_path(&p.path, generics);
if let Some(arr_ty) = self.is_real_type_array(&resolved) {
- write!(w, ".data").unwrap();
return self.write_empty_rust_val_check_suffix(generics, w, &arr_ty);
}
if self.crate_types.opaques.get(&resolved).is_some() {
syn::Type::Array(a) => {
if let syn::Expr::Lit(l) = &a.len {
if let syn::Lit::Int(i) = &l.lit {
- write!(w, " == [0; {}]", i.base10_digits()).unwrap();
+ write!(w, ".data == [0; {}]", i.base10_digits()).unwrap();
EmptyValExpectedTy::NonPointer
} else { unimplemented!(); }
} else { unimplemented!(); }