diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index bb3dcdcf72b39..ec495506a42b7 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -44,7 +44,6 @@ impl AutoTraitResult { pub struct AutoTraitInfo<'cx> { pub full_user_env: ty::ParamEnv<'cx>, pub region_data: RegionConstraintData<'cx>, - pub names_map: FxHashSet, pub vid_to_region: FxHashMap>, } @@ -77,15 +76,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { /// in the future. pub fn find_auto_trait_generics( &self, - did: DefId, + ty: Ty<'tcx>, + orig_env: ty::ParamEnv<'tcx>, trait_did: DefId, - generics: &ty::Generics, auto_trait_callback: impl for<'i> Fn(&InferCtxt<'_, 'tcx, 'i>, AutoTraitInfo<'i>) -> A, ) -> AutoTraitResult { let tcx = self.tcx; - let ty = self.tcx.type_of(did); - - let orig_params = tcx.param_env(did); let trait_ref = ty::TraitRef { def_id: trait_did, @@ -98,16 +94,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut selcx = SelectionContext::with_negative(&infcx, true); let result = selcx.select(&Obligation::new( ObligationCause::dummy(), - orig_params, + orig_env, trait_pred.to_poly_trait_predicate(), )); match result { Ok(Some(Vtable::VtableImpl(_))) => { debug!( - "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): \ + "find_auto_trait_generics({:?}): \ manual impl found, bailing out", - did, trait_did, generics + trait_ref ); true } @@ -158,11 +154,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let (new_env, user_env) = match self.evaluate_predicates( &mut infcx, - did, trait_did, ty, - orig_params.clone(), - orig_params, + orig_env, + orig_env, &mut fresh_preds, false, ) { @@ -172,24 +167,23 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let (full_env, full_user_env) = self.evaluate_predicates( &mut infcx, - did, trait_did, ty, - new_env.clone(), + new_env, user_env, &mut fresh_preds, true, ).unwrap_or_else(|| { panic!( "Failed to fully process: {:?} {:?} {:?}", - ty, trait_did, orig_params + ty, trait_did, orig_env ) }); debug!( - "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): fulfilling \ + "find_auto_trait_generics({:?}): fulfilling \ with {:?}", - did, trait_did, generics, full_env + trait_ref, full_env ); infcx.clear_caches(); @@ -211,15 +205,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ) }); - let names_map: FxHashSet = generics - .params - .iter() - .filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()), - _ => None, - }) - .collect(); - let body_id_map: FxHashMap<_, _> = infcx .region_obligations .borrow() @@ -227,7 +212,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .map(|&(id, _)| (id, vec![])) .collect(); - infcx.process_registered_region_obligations(&body_id_map, None, full_env.clone()); + infcx.process_registered_region_obligations(&body_id_map, None, full_env); let region_data = infcx .borrow_region_constraints() @@ -239,7 +224,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let info = AutoTraitInfo { full_user_env, region_data, - names_map, vid_to_region, }; @@ -286,10 +270,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // the final synthesized generics: we don't want our generated docs page to contain something // like 'T: Copy + Clone', as that's redundant. Therefore, we keep track of a separate // 'user_env', which only holds the predicates that will actually be displayed to the user. - pub fn evaluate_predicates<'b, 'gcx, 'c>( + fn evaluate_predicates<'b, 'gcx, 'c>( &self, infcx: &InferCtxt<'b, 'tcx, 'c>, - ty_did: DefId, trait_did: DefId, ty: Ty<'c>, param_env: ty::ParamEnv<'c>, @@ -314,13 +297,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds.iter().cloned().collect(); - let mut new_env = param_env.clone(); + let mut new_env = param_env; let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID); while let Some(pred) = predicates.pop_front() { infcx.clear_caches(); - if !already_visited.insert(pred.clone()) { + if !already_visited.insert(pred) { continue; } @@ -368,7 +351,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { already_visited.remove(&pred); self.add_user_pred( &mut user_computed_preds, - ty::Predicate::Trait(pred.clone()), + ty::Predicate::Trait(pred), ); predicates.push_back(pred); } else { @@ -387,7 +370,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { computed_preds.extend(user_computed_preds.iter().cloned()); let normalized_preds = - elaborate_predicates(tcx, computed_preds.clone().into_iter().collect()); + elaborate_predicates(tcx, computed_preds.iter().cloned().collect()); new_env = ty::ParamEnv::new( tcx.mk_predicates(normalized_preds), param_env.reveal, @@ -401,9 +384,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { None ); debug!( - "evaluate_nested_obligations(ty_did={:?}, trait_did={:?}): succeeded with '{:?}' \ + "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \ '{:?}'", - ty_did, trait_did, new_env, final_user_env + ty, trait_did, new_env, final_user_env ); return Some((new_env, final_user_env)); @@ -522,28 +505,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } - pub fn region_name(&self, region: Region<'_>) -> Option { - match region { - &ty::ReEarlyBound(r) => Some(r.name.to_string()), - _ => None, - } - } - - pub fn get_lifetime(&self, region: Region<'_>, - names_map: &FxHashMap) -> String { - self.region_name(region) - .map(|name| - names_map.get(&name).unwrap_or_else(|| - panic!("Missing lifetime with name {:?} for {:?}", name, region) - ) - ) - .cloned() - .unwrap_or_else(|| "'static".to_owned()) - } - // This is very similar to handle_lifetimes. However, instead of matching ty::Region's // to each other, we match ty::RegionVid's to ty::Region's - pub fn map_vid_to_region<'cx>( + fn map_vid_to_region<'cx>( &self, regions: &RegionConstraintData<'cx>, ) -> FxHashMap> { @@ -653,7 +617,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } - pub fn evaluate_nested_obligations< + fn evaluate_nested_obligations< 'b, 'c, 'd, @@ -672,10 +636,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID); for (obligation, mut predicate) in nested - .map(|o| (o.clone(), o.predicate.clone())) + .map(|o| (o.clone(), o.predicate)) { let is_new_pred = - fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone())); + fresh_preds.insert(self.clean_pred(select.infcx(), predicate)); // Resolve any inference variables that we can, to help selection succeed predicate = select.infcx().resolve_type_vars_if_possible(&predicate); @@ -693,14 +657,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // We check this by calling is_of_param on the relevant types // from the various possible predicates match &predicate { - &ty::Predicate::Trait(ref p) => { + &ty::Predicate::Trait(p) => { if self.is_param_no_infer(p.skip_binder().trait_ref.substs) && !only_projections && is_new_pred { self.add_user_pred(computed_preds, predicate); } - predicates.push_back(p.clone()); + predicates.push_back(p); } &ty::Predicate::Projection(p) => { debug!("evaluate_nested_obligations: examining projection predicate {:?}", @@ -742,7 +706,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if p.ty().skip_binder().has_infer_types() { debug!("Projecting and unifying projection predicate {:?}", predicate); - match poly_project_and_unify_type(select, &obligation.with(p.clone())) { + match poly_project_and_unify_type(select, &obligation.with(p)) { Err(e) => { debug!( "evaluate_nested_obligations: Unable to unify predicate \ diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a33b3a9312e4b..11e8192521d79 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -1,125 +1,89 @@ 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 { - 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 { - 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( + // 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, - ) -> Vec - 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 { + 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( - &self, - def_id: DefId, - name: Option, - generics: ty::Generics, - def_ctor: &F, - trait_def_id: DefId, - ) -> Option - 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; @@ -140,83 +104,38 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // Instead, we generate `impl !Send for Foo`, which better // expresses the fact that `Foo` 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), &Default::default()) + .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( @@ -530,16 +449,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { 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, vid_to_region: FxHashMap>, ) -> 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 @@ -553,7 +471,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { 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() @@ -568,11 +487,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { (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(); @@ -757,10 +675,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .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), } } }; diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 570c61f1ffc99..5c42d705bd579 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -9,8 +9,6 @@ use crate::core::DocAccessLevels; use super::*; -use self::def_ctor::{get_def_from_def_id, get_def_from_hir_id}; - pub struct BlanketImplFinder<'a, 'tcx> { pub cx: &'a core::DocContext<'tcx>, } @@ -20,67 +18,36 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { BlanketImplFinder { cx } } - pub fn get_with_def_id(&self, def_id: DefId) -> Vec { - get_def_from_def_id(&self.cx, def_id, &|def_ctor| { - self.get_blanket_impls(def_id, &def_ctor, None) - }) - } - - pub fn get_with_hir_id(&self, id: hir::HirId, name: String) -> Vec { - 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_blanket_impls(did, &def_ctor, Some(name)) - }) - } - - pub fn get_blanket_impls( + // FIXME(eddyb) figure out a better way to pass information about + // parametrization of `ty` than `param_env_def_id`. + pub fn get_blanket_impls( &self, - def_id: DefId, - def_ctor: &F, - name: Option, - ) -> Vec - where F: Fn(DefId) -> Def { - debug!("get_blanket_impls(def_id={:?}, ...)", def_id); + ty: Ty<'tcx>, + param_env_def_id: DefId, + ) -> Vec { + let param_env = self.cx.tcx.param_env(param_env_def_id); + + debug!("get_blanket_impls({:?})", ty); let mut impls = Vec::new(); - if self.cx - .tcx - .get_attrs(def_id) - .lists("doc") - .has_word("hidden") - { - debug!( - "get_blanket_impls(def_id={:?}, def_ctor=...): item has doc('hidden'), \ - aborting", - def_id - ); - return impls; - } - let ty = self.cx.tcx.type_of(def_id); - let generics = self.cx.tcx.generics_of(def_id); - let real_name = name.map(|name| Ident::from_str(&name)); - let param_env = self.cx.tcx.param_env(def_id); for &trait_def_id in self.cx.all_traits.iter() { if !self.cx.renderinfo.borrow().access_levels.is_doc_reachable(trait_def_id) || self.cx.generated_synthetics .borrow_mut() - .get(&(def_id, trait_def_id)) + .get(&(ty, trait_def_id)) .is_some() { continue } self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { - self.cx.tcx.infer_ctxt().enter(|infcx| { - debug!("get_blanet_impls: Considering impl for trait '{:?}' {:?}", - trait_def_id, impl_def_id); - let t_generics = infcx.tcx.generics_of(impl_def_id); - let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) - .expect("Cannot get impl trait"); - + debug!("get_blanket_impls: Considering impl for trait '{:?}' {:?}", + trait_def_id, impl_def_id); + let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap(); + let may_apply = self.cx.tcx.infer_ctxt().enter(|infcx| { match trait_ref.self_ty().sty { ty::Param(_) => {}, - _ => return, + _ => return false, } - let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id); + let substs = infcx.fresh_substs_for_item(DUMMY_SP, param_env_def_id); let ty = ty.subst(infcx.tcx, substs); let param_env = param_env.subst(infcx.tcx, substs); @@ -100,7 +67,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", param_env, trait_ref, ty ); - let may_apply = match infcx.evaluate_obligation( + match infcx.evaluate_obligation( &traits::Obligation::new( cause, param_env, @@ -109,56 +76,53 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { ) { Ok(eval_result) => eval_result.may_apply(), Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no - }; - debug!("get_blanket_impls: found applicable impl: {}\ - for trait_ref={:?}, ty={:?}", - may_apply, trait_ref, ty); - - if !may_apply { - return } - self.cx.generated_synthetics.borrow_mut() - .insert((def_id, trait_def_id)); - let trait_ = hir::TraitRef { - path: get_path_for_type(infcx.tcx, - trait_def_id, - hir::def::Def::Trait), - hir_ref_id: hir::DUMMY_HIR_ID, - }; - let provided_trait_methods = - infcx.tcx.provided_trait_methods(trait_def_id) - .into_iter() - .map(|meth| meth.ident.to_string()) - .collect(); - - let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics); - let predicates = infcx.tcx.explicit_predicates_of(impl_def_id); - - impls.push(Item { - source: infcx.tcx.def_span(impl_def_id).clean(self.cx), - name: None, - attrs: Default::default(), - visibility: None, - def_id: self.cx.next_def_id(impl_def_id.krate), - stability: None, - deprecation: None, - inner: ImplItem(Impl { - unsafety: hir::Unsafety::Normal, - generics: (t_generics, &predicates).clean(self.cx), - provided_trait_methods, - trait_: Some(trait_.clean(self.cx)), - for_: ty.clean(self.cx), - items: infcx.tcx.associated_items(impl_def_id) - .collect::>() - .clean(self.cx), - polarity: None, - synthetic: false, - blanket_impl: Some(infcx.tcx.type_of(impl_def_id) - .clean(self.cx)), - }), - }); + } else { + false } }); + debug!("get_blanket_impls: found applicable impl: {}\ + for trait_ref={:?}, ty={:?}", + may_apply, trait_ref, ty); + if !may_apply { + return; + } + + self.cx.generated_synthetics.borrow_mut() + .insert((ty, trait_def_id)); + let provided_trait_methods = + self.cx.tcx.provided_trait_methods(trait_def_id) + .into_iter() + .map(|meth| meth.ident.to_string()) + .collect(); + + impls.push(Item { + source: self.cx.tcx.def_span(impl_def_id).clean(self.cx), + name: None, + attrs: Default::default(), + visibility: None, + def_id: self.cx.next_def_id(impl_def_id.krate), + stability: None, + deprecation: None, + inner: ImplItem(Impl { + unsafety: hir::Unsafety::Normal, + generics: ( + self.cx.tcx.generics_of(impl_def_id), + &self.cx.tcx.explicit_predicates_of(impl_def_id), + ).clean(self.cx), + provided_trait_methods, + // FIXME(eddyb) compute both `trait_` and `for_` from + // the post-inference `trait_ref`, as it's more accurate. + trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), + for_: ty.clean(self.cx), + items: self.cx.tcx.associated_items(impl_def_id) + .collect::>() + .clean(self.cx), + polarity: None, + synthetic: false, + blanket_impl: Some(trait_ref.self_ty().clean(self.cx)), + }), + }); }); } impls diff --git a/src/librustdoc/clean/def_ctor.rs b/src/librustdoc/clean/def_ctor.rs deleted file mode 100644 index 405a2e66d6e5c..0000000000000 --- a/src/librustdoc/clean/def_ctor.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::core::DocContext; - -use super::*; - -pub fn get_def_from_def_id(cx: &DocContext<'_>, - def_id: DefId, - callback: &F, -) -> Vec -where F: Fn(& dyn Fn(DefId) -> Def) -> Vec { - let ty = cx.tcx.type_of(def_id); - - match ty.sty { - ty::Adt(adt, _) => callback(&match adt.adt_kind() { - AdtKind::Struct => Def::Struct, - AdtKind::Enum => Def::Enum, - AdtKind::Union => Def::Union, - }), - ty::Int(_) | - ty::Uint(_) | - ty::Float(_) | - ty::Str | - ty::Bool | - ty::Char => callback(&move |_: DefId| { - match ty.sty { - ty::Int(x) => Def::PrimTy(hir::Int(x)), - ty::Uint(x) => Def::PrimTy(hir::Uint(x)), - ty::Float(x) => Def::PrimTy(hir::Float(x)), - ty::Str => Def::PrimTy(hir::Str), - ty::Bool => Def::PrimTy(hir::Bool), - ty::Char => Def::PrimTy(hir::Char), - _ => unreachable!(), - } - }), - _ => { - debug!("Unexpected type {:?}", def_id); - Vec::new() - } - } -} - -pub fn get_def_from_hir_id(cx: &DocContext<'_>, - id: hir::HirId, - name: String, - callback: &F, -) -> Vec -where F: Fn(& dyn Fn(DefId) -> Def, String) -> Vec { - let item = &cx.tcx.hir().expect_item_by_hir_id(id).node; - - callback(&match *item { - hir::ItemKind::Struct(_, _) => Def::Struct, - hir::ItemKind::Union(_, _) => Def::Union, - hir::ItemKind::Enum(_, _) => Def::Enum, - _ => panic!("Unexpected type {:?} {:?}", item, id), - }, name) -} diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8232254cdec14..dd4900cfaeec6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -8,7 +8,6 @@ pub mod cfg; mod simplify; mod auto_trait; mod blanket_impl; -pub mod def_ctor; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::sync::Lrc; @@ -22,8 +21,7 @@ use rustc::mir::interpret::{GlobalId, ConstValue}; use rustc::hir::{self, HirVec}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::hir::map::DisambiguatedDefPathData; -use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind}; +use rustc::ty::subst::{InternalSubsts, SubstsRef, UnpackedKind}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; use rustc::ty::layout::VariantIdx; @@ -35,7 +33,7 @@ use syntax::source_map::{dummy_spanned, Spanned}; use syntax::ptr::P; use syntax::symbol::keywords::{self, Keyword}; use syntax::symbol::InternedString; -use syntax_pos::{self, DUMMY_SP, Pos, FileName}; +use syntax_pos::{self, Pos, FileName}; use std::collections::hash_map::Entry; use std::fmt; @@ -3776,40 +3774,13 @@ pub struct Impl { pub blanket_impl: Option, } -pub fn get_auto_traits_with_hir_id( - cx: &DocContext<'_>, - id: hir::HirId, - name: String -) -> Vec { - let finder = AutoTraitFinder::new(cx); - finder.get_with_hir_id(id, name) -} - -pub fn get_auto_traits_with_def_id( - cx: &DocContext<'_>, - id: DefId -) -> Vec { - let finder = AutoTraitFinder::new(cx); - - finder.get_with_def_id(id) -} - -pub fn get_blanket_impls_with_hir_id( - cx: &DocContext<'_>, - id: hir::HirId, - name: String -) -> Vec { - let finder = BlanketImplFinder::new(cx); - finder.get_with_hir_id(id, name) -} - -pub fn get_blanket_impls_with_def_id( - cx: &DocContext<'_>, - id: DefId -) -> Vec { - let finder = BlanketImplFinder::new(cx); - - finder.get_with_def_id(id) +pub fn get_auto_trait_and_blanket_impls( + cx: &DocContext<'tcx>, + ty: Ty<'tcx>, + param_env_def_id: DefId, +) -> impl Iterator { + AutoTraitFinder::new(cx).get_auto_trait_impls(ty, param_env_def_id).into_iter() + .chain(BlanketImplFinder::new(cx).get_blanket_impls(ty, param_env_def_id)) } impl Clean> for doctree::Impl { @@ -4461,125 +4432,8 @@ pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[&str]) -> Option { } } -pub fn get_path_for_type( - tcx: TyCtxt<'_, '_, '_>, - def_id: DefId, - def_ctor: impl Fn(DefId) -> Def, -) -> hir::Path { - use rustc::ty::print::Printer; - - struct AbsolutePathPrinter<'a, 'tcx> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - } - - impl Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> { - type Error = !; - - type Path = Vec; - type Region = (); - type Type = (); - type DynExistential = (); - - fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { - self.tcx - } - - fn print_region( - self, - _region: ty::Region<'_>, - ) -> Result { - Ok(()) - } - - fn print_type( - self, - _ty: Ty<'tcx>, - ) -> Result { - Ok(()) - } - - fn print_dyn_existential( - self, - _predicates: &'tcx ty::List>, - ) -> Result { - Ok(()) - } - - fn path_crate( - self, - cnum: CrateNum, - ) -> Result { - Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) - } - fn path_qualified( - self, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - // This shouldn't ever be needed, but just in case: - Ok(vec![match trait_ref { - Some(trait_ref) => format!("{:?}", trait_ref), - None => format!("<{}>", self_ty), - }]) - } - - fn path_append_impl( - self, - print_prefix: impl FnOnce(Self) -> Result, - _disambiguated_data: &DisambiguatedDefPathData, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - let mut path = print_prefix(self)?; - - // This shouldn't ever be needed, but just in case: - path.push(match trait_ref { - Some(trait_ref) => { - format!("", trait_ref, self_ty) - } - None => format!("", self_ty), - }); - - Ok(path) - } - fn path_append( - self, - print_prefix: impl FnOnce(Self) -> Result, - disambiguated_data: &DisambiguatedDefPathData, - ) -> Result { - let mut path = print_prefix(self)?; - path.push(disambiguated_data.data.as_interned_str().to_string()); - Ok(path) - } - fn path_generic_args( - self, - print_prefix: impl FnOnce(Self) -> Result, - _args: &[Kind<'tcx>], - ) -> Result { - print_prefix(self) - } - } - - let names = AbsolutePathPrinter { tcx: tcx.global_tcx() } - .print_def_path(def_id, &[]) - .unwrap(); - - hir::Path { - span: DUMMY_SP, - def: def_ctor(def_id), - segments: hir::HirVec::from_vec(names.iter().map(|s| hir::PathSegment { - ident: ast::Ident::from_str(&s), - hir_id: None, - def: None, - args: None, - infer_types: false, - }).collect()) - } -} - // End of code copied from rust-clippy - #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] enum RegionTarget<'tcx> { Region(Region<'tcx>), @@ -4598,21 +4452,6 @@ enum SimpleBound { Outlives(Lifetime), } -enum AutoTraitResult { - ExplicitImpl, - PositiveImpl(Generics), - NegativeImpl, -} - -impl AutoTraitResult { - fn is_auto(&self) -> bool { - match *self { - AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true, - _ => false, - } - } -} - impl From for SimpleBound { fn from(bound: GenericBound) -> Self { match bound.clone() { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2274f4e81d43c..831adb301efcb 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -2,10 +2,10 @@ use rustc_lint; use rustc::session::{self, config}; use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CrateNum, LOCAL_CRATE}; use rustc::hir::def::Def; -use rustc::hir::{self, HirId, HirVec}; +use rustc::hir::HirId; use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{Ty, TyCtxt}; use rustc::lint::{self, LintPass}; use rustc::session::config::ErrorOutputType; use rustc::session::DiagnosticOutput; @@ -16,13 +16,9 @@ use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; use rustc_target::spec::TargetTriple; -use syntax::ast::{self, Ident}; use syntax::source_map; use syntax::feature_gate::UnstableFeatures; use syntax::json::JsonEmitter; -use syntax::ptr::P; -use syntax::symbol::keywords; -use syntax_pos::DUMMY_SP; use errors; use errors::emitter::{Emitter, EmitterWriter}; use parking_lot::ReentrantMutex; @@ -36,7 +32,7 @@ use std::rc::Rc; use crate::visit_ast::RustdocVisitor; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::clean; -use crate::clean::{get_path_for_type, Clean, MAX_DEF_ID, AttributesExt}; +use crate::clean::{Clean, MAX_DEF_ID, AttributesExt}; use crate::html::render::RenderInfo; use crate::passes; @@ -74,8 +70,9 @@ pub struct DocContext<'tcx> { pub send_trait: Option, pub fake_def_ids: RefCell>, pub all_fake_def_ids: RefCell>, - /// Maps (type_id, trait_id) -> auto trait impl - pub generated_synthetics: RefCell>, + /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. + // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set. + pub generated_synthetics: RefCell, DefId)>>, pub all_traits: Vec, } @@ -173,98 +170,6 @@ impl<'tcx> DocContext<'tcx> { self.tcx.hir().as_local_hir_id(def_id) } } - - pub fn get_real_ty(&self, - def_id: DefId, - def_ctor: &F, - real_name: &Option, - generics: &ty::Generics, - ) -> hir::Ty - where F: Fn(DefId) -> Def { - let path = get_path_for_type(self.tcx, def_id, def_ctor); - let mut segments = path.segments.into_vec(); - let last = segments.pop().expect("segments were empty"); - - segments.push(hir::PathSegment::new( - real_name.unwrap_or(last.ident), - None, - None, - self.generics_to_path_params(generics.clone()), - false, - )); - - let new_path = hir::Path { - span: path.span, - def: path.def, - segments: HirVec::from_vec(segments), - }; - - hir::Ty { - node: hir::TyKind::Path(hir::QPath::Resolved(None, P(new_path))), - span: DUMMY_SP, - hir_id: hir::DUMMY_HIR_ID, - } - } - - pub fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs { - let mut args = vec![]; - - for param in generics.params.iter() { - match param.kind { - ty::GenericParamDefKind::Lifetime => { - let name = if param.name == "" { - hir::ParamName::Plain(keywords::StaticLifetime.ident()) - } else { - hir::ParamName::Plain(ast::Ident::from_interned_str(param.name)) - }; - - args.push(hir::GenericArg::Lifetime(hir::Lifetime { - hir_id: hir::DUMMY_HIR_ID, - span: DUMMY_SP, - name: hir::LifetimeName::Param(name), - })); - } - ty::GenericParamDefKind::Type { .. } => { - args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone()))); - } - ty::GenericParamDefKind::Const => { - args.push(hir::GenericArg::Const(hir::ConstArg { - value: hir::AnonConst { - hir_id: hir::DUMMY_HIR_ID, - body: hir::BodyId { - hir_id: hir::DUMMY_HIR_ID, - } - }, - span: DUMMY_SP, - })) - } - } - } - - hir::GenericArgs { - args: HirVec::from_vec(args), - bindings: HirVec::new(), - parenthesized: false, - } - } - - pub fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty { - debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id); - hir::Ty { - node: hir::TyKind::Path(hir::QPath::Resolved( - None, - P(hir::Path { - span: DUMMY_SP, - def: Def::TyParam(param.def_id), - segments: HirVec::from_vec(vec![ - hir::PathSegment::from_ident(Ident::from_interned_str(param.name)) - ]), - }), - )), - span: DUMMY_SP, - hir_id: hir::DUMMY_HIR_ID, - } - } } pub trait DocAccessLevels { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 611291c2688f5..8d33cd72e29aa 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -67,16 +67,14 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { if !def_id.is_local() { inline::build_impl(cx, def_id, &mut new_items); - let auto_impls = get_auto_traits_with_def_id(cx, def_id); - let blanket_impls = get_blanket_impls_with_def_id(cx, def_id); - let mut renderinfo = cx.renderinfo.borrow_mut(); + // FIXME(eddyb) is this `doc(hidden)` check needed? + if !cx.tcx.get_attrs(def_id).lists("doc").has_word("hidden") { + let self_ty = cx.tcx.type_of(def_id); + let impls = get_auto_trait_and_blanket_impls(cx, self_ty, def_id); + let mut renderinfo = cx.renderinfo.borrow_mut(); - let new_impls: Vec = auto_impls.into_iter() - .chain(blanket_impls.into_iter()) - .filter(|i| renderinfo.inlined.insert(i.def_id)) - .collect(); - - new_items.extend(new_impls); + new_items.extend(impls.filter(|i| renderinfo.inlined.insert(i.def_id))); + } } } @@ -155,14 +153,13 @@ impl<'a, 'tcx> SyntheticImplCollector<'a, 'tcx> { impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { if i.is_struct() || i.is_enum() || i.is_union() { - if let (Some(hir_id), Some(name)) = - (self.cx.tcx.hir().as_local_hir_id(i.def_id), i.name.clone()) - { - self.impls.extend(get_auto_traits_with_hir_id(self.cx, hir_id, name.clone())); - self.impls.extend(get_blanket_impls_with_hir_id(self.cx, hir_id, name)); - } else { - self.impls.extend(get_auto_traits_with_def_id(self.cx, i.def_id)); - self.impls.extend(get_blanket_impls_with_def_id(self.cx, i.def_id)); + // FIXME(eddyb) is this `doc(hidden)` check needed? + if !self.cx.tcx.get_attrs(i.def_id).lists("doc").has_word("hidden") { + self.impls.extend(get_auto_trait_and_blanket_impls( + self.cx, + self.cx.tcx.type_of(i.def_id), + i.def_id, + )); } } diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs index a1db90d7606d9..f247ee637b975 100644 --- a/src/test/rustdoc/blanket-reexport-item.rs +++ b/src/test/rustdoc/blanket-reexport-item.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @has foo/struct.S.html '//h3[@id="impl-Into"]//code' 'impl Into for T' +// @has foo/struct.S.html '//h3[@id="impl-Into%3CU%3E"]//code' 'impl Into for T' pub struct S2 {} mod m { pub struct S {} diff --git a/src/test/rustdoc/issue-34473.rs b/src/test/rustdoc/issue-34473.rs index 3f824e6404431..d96301f3ae736 100644 --- a/src/test/rustdoc/issue-34473.rs +++ b/src/test/rustdoc/issue-34473.rs @@ -7,6 +7,5 @@ mod second { // @has foo/index.html // @!has - SomeTypeWithLongName // @has foo/struct.SomeType.html -// @!has - SomeTypeWithLongName // @!has foo/struct.SomeTypeWithLongName.html pub use second::{SomeTypeWithLongName as SomeType}; diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index 609cefc7115e2..80a717718c22b 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -21,7 +21,7 @@ mod foo { // @has complex/struct.NotOuter.html // @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a, T, K: \ -// ?Sized> Send for NotOuter<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ +// ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};