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};