use rustc::hir;
-use rustc::traits::auto_trait as auto;
+use rustc::traits::auto_trait::{self, AutoTraitResult};
use rustc::ty::{self, TypeFoldable};
use std::fmt::Debug;
-use self::def_ctor::{get_def_from_def_id, get_def_from_hir_id};
-
use super::*;
pub struct AutoTraitFinder<'a, 'tcx> {
pub cx: &'a core::DocContext<'tcx>,
- pub f: auto::AutoTraitFinder<'a, 'tcx>,
+ pub f: auto_trait::AutoTraitFinder<'a, 'tcx>,
}
impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
pub fn new(cx: &'a core::DocContext<'tcx>) -> Self {
- let f = auto::AutoTraitFinder::new(cx.tcx);
+ let f = auto_trait::AutoTraitFinder::new(cx.tcx);
AutoTraitFinder { cx, f }
}
- pub fn get_with_def_id(&self, def_id: DefId) -> Vec<Item> {
- get_def_from_def_id(&self.cx, def_id, &|def_ctor| {
- self.get_auto_trait_impls(def_id, &def_ctor, None)
- })
- }
-
- pub fn get_with_hir_id(&self, id: hir::HirId, name: String) -> Vec<Item> {
- get_def_from_hir_id(&self.cx, id, name, &|def_ctor, name| {
- let did = self.cx.tcx.hir().local_def_id_from_hir_id(id);
- self.get_auto_trait_impls(did, &def_ctor, Some(name))
- })
- }
-
- pub fn get_auto_trait_impls<F>(
+ // FIXME(eddyb) figure out a better way to pass information about
+ // parametrization of `ty` than `param_env_def_id`.
+ pub fn get_auto_trait_impls(
&self,
- def_id: DefId,
- def_ctor: &F,
- name: Option<String>,
- ) -> Vec<Item>
- where F: Fn(DefId) -> Def {
- if self.cx
- .tcx
- .get_attrs(def_id)
- .lists("doc")
- .has_word("hidden")
- {
- debug!(
- "get_auto_trait_impls(def_id={:?}, def_ctor=...): item has doc('hidden'), \
- aborting",
- def_id
- );
- return Vec::new();
- }
-
- let tcx = self.cx.tcx;
- let generics = self.cx.tcx.generics_of(def_id);
-
- debug!(
- "get_auto_trait_impls(def_id={:?}, def_ctor=..., generics={:?}",
- def_id, generics
+ ty: Ty<'tcx>,
+ param_env_def_id: DefId,
+ ) -> Vec<Item> {
+ let param_env = self.cx.tcx.param_env(param_env_def_id);
+
+ debug!("get_auto_trait_impls({:?})", ty);
+ let auto_traits = self.cx.send_trait.into_iter().chain(
+ Some(self.cx.tcx.require_lang_item(lang_items::SyncTraitLangItem))
);
- let auto_traits: Vec<_> = self.cx
- .send_trait
- .and_then(|send_trait| {
- self.get_auto_trait_impl_for(
- def_id,
- name.clone(),
- generics.clone(),
- def_ctor,
- send_trait,
- )
- })
- .into_iter()
- .chain(self.get_auto_trait_impl_for(
- def_id,
- name,
- generics.clone(),
- def_ctor,
- tcx.require_lang_item(lang_items::SyncTraitLangItem),
- ).into_iter())
- .collect();
+ auto_traits.filter_map(|trait_def_id| {
+ let trait_ref = ty::TraitRef {
+ def_id: trait_def_id,
+ substs: self.cx.tcx.mk_substs_trait(ty, &[]),
+ };
+ if !self.cx
+ .generated_synthetics
+ .borrow_mut()
+ .insert((ty, trait_def_id))
+ {
+ debug!(
+ "get_auto_trait_impl_for({:?}): already generated, aborting",
+ trait_ref
+ );
+ return None;
+ }
- debug!(
- "get_auto_traits: type {:?} auto_traits {:?}",
- def_id, auto_traits
- );
- auto_traits
- }
+ let result = self.f.find_auto_trait_generics(
+ ty,
+ param_env,
+ trait_def_id,
+ |infcx, info| {
+ let region_data = info.region_data;
- fn get_auto_trait_impl_for<F>(
- &self,
- def_id: DefId,
- name: Option<String>,
- generics: ty::Generics,
- def_ctor: &F,
- trait_def_id: DefId,
- ) -> Option<Item>
- where F: Fn(DefId) -> Def {
- if !self.cx
- .generated_synthetics
- .borrow_mut()
- .insert((def_id, trait_def_id))
- {
- debug!(
- "get_auto_trait_impl_for(def_id={:?}, generics={:?}, def_ctor=..., \
- trait_def_id={:?}): already generated, aborting",
- def_id, generics, trait_def_id
- );
- return None;
- }
+ let names_map = self.cx.tcx.generics_of(param_env_def_id)
+ .params
+ .iter()
+ .filter_map(|param| match param.kind {
+ ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
+ _ => None,
+ })
+ .map(|name| (name.clone(), Lifetime(name)))
+ .collect();
+ let lifetime_predicates =
+ self.handle_lifetimes(®ion_data, &names_map);
+ let new_generics = self.param_env_to_generics(
+ infcx.tcx,
+ param_env_def_id,
+ info.full_user_env,
+ lifetime_predicates,
+ info.vid_to_region,
+ );
- let result = self.find_auto_trait_generics(def_id, trait_def_id, &generics);
+ debug!(
+ "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}): \
+ finished with {:?}",
+ param_env_def_id, trait_def_id, new_generics
+ );
- if result.is_auto() {
- let trait_ = hir::TraitRef {
- path: get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait),
- hir_ref_id: hir::DUMMY_HIR_ID,
- };
+ new_generics
+ },
+ );
let polarity;
-
let new_generics = match result {
AutoTraitResult::PositiveImpl(new_generics) => {
polarity = None;
// Instead, we generate `impl !Send for Foo<T>`, which better
// expresses the fact that `Foo<T>` never implements `Send`,
// regardless of the choice of `T`.
- let real_generics = (&generics, &Default::default());
-
- // Clean the generics, but ignore the '?Sized' bounds generated
- // by the `Clean` impl
- let clean_generics = real_generics.clean(self.cx);
+ let params = (
+ self.cx.tcx.generics_of(param_env_def_id),
+ &&self.cx.tcx.common.empty_predicates,
+ ).clean(self.cx).params;
Generics {
- params: clean_generics.params,
+ params,
where_predicates: Vec::new(),
}
}
- _ => unreachable!(),
+ AutoTraitResult::ExplicitImpl => return None,
};
- let real_name = name.map(|name| Ident::from_str(&name));
- let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, &generics);
- return Some(Item {
+ Some(Item {
source: Span::empty(),
name: None,
attrs: Default::default(),
visibility: None,
- def_id: self.cx.next_def_id(def_id.krate),
+ def_id: self.cx.next_def_id(param_env_def_id.krate),
stability: None,
deprecation: None,
inner: ImplItem(Impl {
unsafety: hir::Unsafety::Normal,
generics: new_generics,
provided_trait_methods: Default::default(),
- trait_: Some(trait_.clean(self.cx)),
+ trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()),
for_: ty.clean(self.cx),
items: Vec::new(),
polarity,
synthetic: true,
blanket_impl: None,
}),
- });
- }
- None
- }
-
- fn find_auto_trait_generics(
- &self,
- did: DefId,
- trait_did: DefId,
- generics: &ty::Generics,
- ) -> AutoTraitResult {
- match self.f.find_auto_trait_generics(did, trait_did, generics,
- |infcx, mut info| {
- let region_data = info.region_data;
- let names_map =
- info.names_map
- .drain()
- .map(|name| (name.clone(), Lifetime(name)))
- .collect();
- let lifetime_predicates =
- self.handle_lifetimes(®ion_data, &names_map);
- let new_generics = self.param_env_to_generics(
- infcx.tcx,
- did,
- info.full_user_env,
- generics.clone(),
- lifetime_predicates,
- info.vid_to_region,
- );
-
- debug!(
- "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): \
- finished with {:?}",
- did, trait_did, generics, new_generics
- );
-
- new_generics
- }) {
- auto::AutoTraitResult::ExplicitImpl => AutoTraitResult::ExplicitImpl,
- auto::AutoTraitResult::NegativeImpl => AutoTraitResult::NegativeImpl,
- auto::AutoTraitResult::PositiveImpl(res) => AutoTraitResult::PositiveImpl(res),
- }
+ })
+ }).collect()
}
fn get_lifetime(
.collect()
}
- fn make_final_bounds<'b, 'c, 'cx>(
+ fn make_final_bounds(
&self,
ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)>,
fn param_env_to_generics<'b, 'c, 'cx>(
&self,
tcx: TyCtxt<'b, 'c, 'cx>,
- did: DefId,
+ param_env_def_id: DefId,
param_env: ty::ParamEnv<'cx>,
- type_generics: ty::Generics,
mut existing_predicates: Vec<WherePredicate>,
vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
) -> Generics {
debug!(
- "param_env_to_generics(did={:?}, param_env={:?}, type_generics={:?}, \
+ "param_env_to_generics(param_env_def_id={:?}, param_env={:?}, \
existing_predicates={:?})",
- did, param_env, type_generics, existing_predicates
+ param_env_def_id, param_env, existing_predicates
);
// The `Sized` trait must be handled specially, since we only display it when
tcx,
};
- let orig_bounds: FxHashSet<_> = self.cx.tcx.param_env(did).caller_bounds.iter().collect();
+ let orig_bounds: FxHashSet<_> =
+ self.cx.tcx.param_env(param_env_def_id).caller_bounds.iter().collect();
let clean_where_predicates = param_env
.caller_bounds
.iter()
(replaced.clone(), replaced.clean(self.cx))
});
- let full_generics = (&type_generics, &tcx.explicit_predicates_of(did));
- let Generics {
- params: mut generic_params,
- ..
- } = full_generics.clean(self.cx);
+ let mut generic_params = (
+ tcx.generics_of(param_env_def_id),
+ &tcx.explicit_predicates_of(param_env_def_id),
+ ).clean(self.cx).params;
let mut has_sized = FxHashSet::default();
let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
} => {
bindings.push(TypeBinding {
name: left_name.clone(),
- ty: rhs,
+ kind: TypeBindingKind::Equality {
+ ty: rhs,
+ },
});
}
&mut GenericArgs::Parenthesized { .. } => {
.or_default()
.insert(*trait_.clone());
}
- _ => panic!("Unexpected trait {:?} for {:?}", trait_, did),
+ _ => panic!(
+ "Unexpected trait {:?} for {:?}",
+ trait_,
+ param_env_def_id,
+ ),
}
}
- _ => panic!("Unexpected LHS {:?} for {:?}", lhs, did),
+ _ => panic!("Unexpected LHS {:?} for {:?}", lhs, param_env_def_id),
}
}
};