Auto merge of #60137 - eddyb:rustdoc-rm-def-ctor-hax, r=petrochenkov
rustdoc: remove def_ctor hack. ~~No longer necessary since we have `describe_def`.~~ Turns out `def_ctor` was used in conjunction with abusing `tcx.type_of(def_id)` working on both type definitions and `impl`s (specifically, of builtin types), but also reimplementing a lot of the logic that `Clean` already provides on `Ty` / `ty::TraitRef`. The first commit now does the minimal refactor to keep it working, while the second commit contains the rest of the refactor I started (parts of which I'm not sure we need to keep).
This commit is contained in:
commit
6cc24f2603
@ -44,7 +44,6 @@ impl<A> AutoTraitResult<A> {
|
||||
pub struct AutoTraitInfo<'cx> {
|
||||
pub full_user_env: ty::ParamEnv<'cx>,
|
||||
pub region_data: RegionConstraintData<'cx>,
|
||||
pub names_map: FxHashSet<String>,
|
||||
pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
|
||||
}
|
||||
|
||||
@ -77,15 +76,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
/// in the future.
|
||||
pub fn find_auto_trait_generics<A>(
|
||||
&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<A> {
|
||||
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<String> = 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<String> {
|
||||
match region {
|
||||
&ty::ReEarlyBound(r) => Some(r.name.to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lifetime(&self, region: Region<'_>,
|
||||
names_map: &FxHashMap<String, String>) -> 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<ty::RegionVid, ty::Region<'cx>> {
|
||||
@ -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 \
|
||||
|
@ -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<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();
|
||||
}
|
||||
ty: Ty<'tcx>,
|
||||
param_env_def_id: DefId,
|
||||
) -> Vec<Item> {
|
||||
let param_env = self.cx.tcx.param_env(param_env_def_id);
|
||||
|
||||
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
|
||||
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();
|
||||
|
||||
debug!(
|
||||
"get_auto_traits: type {:?} auto_traits {:?}",
|
||||
def_id, auto_traits
|
||||
);
|
||||
auto_traits
|
||||
}
|
||||
|
||||
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 result = self.find_auto_trait_generics(def_id, trait_def_id, &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,
|
||||
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;
|
||||
}
|
||||
|
||||
let result = self.f.find_auto_trait_generics(
|
||||
ty,
|
||||
param_env,
|
||||
trait_def_id,
|
||||
|infcx, info| {
|
||||
let region_data = info.region_data;
|
||||
|
||||
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,
|
||||
);
|
||||
|
||||
debug!(
|
||||
"find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}): \
|
||||
finished with {:?}",
|
||||
param_env_def_id, trait_def_id, new_generics
|
||||
);
|
||||
|
||||
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<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), &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<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
|
||||
@ -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),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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<Item> {
|
||||
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<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_blanket_impls(did, &def_ctor, Some(name))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_blanket_impls<F>(
|
||||
// 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<String>,
|
||||
) -> Vec<Item>
|
||||
where F: Fn(DefId) -> Def {
|
||||
debug!("get_blanket_impls(def_id={:?}, ...)", def_id);
|
||||
ty: Ty<'tcx>,
|
||||
param_env_def_id: DefId,
|
||||
) -> Vec<Item> {
|
||||
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::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.clean(self.cx),
|
||||
polarity: None,
|
||||
synthetic: false,
|
||||
blanket_impl: Some(trait_ref.self_ty().clean(self.cx)),
|
||||
}),
|
||||
});
|
||||
});
|
||||
}
|
||||
impls
|
||||
|
@ -1,55 +0,0 @@
|
||||
use crate::core::DocContext;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn get_def_from_def_id<F>(cx: &DocContext<'_>,
|
||||
def_id: DefId,
|
||||
callback: &F,
|
||||
) -> Vec<Item>
|
||||
where F: Fn(& dyn Fn(DefId) -> Def) -> Vec<Item> {
|
||||
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<F>(cx: &DocContext<'_>,
|
||||
id: hir::HirId,
|
||||
name: String,
|
||||
callback: &F,
|
||||
) -> Vec<Item>
|
||||
where F: Fn(& dyn Fn(DefId) -> Def, String) -> Vec<Item> {
|
||||
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)
|
||||
}
|
@ -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;
|
||||
@ -3777,40 +3775,13 @@ pub struct Impl {
|
||||
pub blanket_impl: Option<Type>,
|
||||
}
|
||||
|
||||
pub fn get_auto_traits_with_hir_id(
|
||||
cx: &DocContext<'_>,
|
||||
id: hir::HirId,
|
||||
name: String
|
||||
) -> Vec<Item> {
|
||||
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<Item> {
|
||||
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<Item> {
|
||||
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<Item> {
|
||||
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<Item = Item> {
|
||||
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<Vec<Item>> for doctree::Impl {
|
||||
@ -4462,125 +4433,8 @@ pub fn path_to_def(tcx: TyCtxt<'_, '_, '_>, path: &[&str]) -> Option<DefId> {
|
||||
}
|
||||
}
|
||||
|
||||
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<String>;
|
||||
type Region = ();
|
||||
type Type = ();
|
||||
type DynExistential = ();
|
||||
|
||||
fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn print_region(
|
||||
self,
|
||||
_region: ty::Region<'_>,
|
||||
) -> Result<Self::Region, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_type(
|
||||
self,
|
||||
_ty: Ty<'tcx>,
|
||||
) -> Result<Self::Type, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_dyn_existential(
|
||||
self,
|
||||
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
|
||||
) -> Result<Self::DynExistential, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path_crate(
|
||||
self,
|
||||
cnum: CrateNum,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
|
||||
}
|
||||
fn path_qualified(
|
||||
self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
// 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<Self::Path, Self::Error>,
|
||||
_disambiguated_data: &DisambiguatedDefPathData,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
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!("<impl {} for {}>", trait_ref, self_ty)
|
||||
}
|
||||
None => format!("<impl {}>", self_ty),
|
||||
});
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
fn path_append(
|
||||
self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
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<Self::Path, Self::Error>,
|
||||
_args: &[Kind<'tcx>],
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
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>),
|
||||
@ -4599,21 +4453,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<GenericBound> for SimpleBound {
|
||||
fn from(bound: GenericBound) -> Self {
|
||||
match bound.clone() {
|
||||
|
@ -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<DefId>,
|
||||
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
|
||||
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
|
||||
/// Maps (type_id, trait_id) -> auto trait impl
|
||||
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>,
|
||||
/// 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<FxHashSet<(Ty<'tcx>, DefId)>>,
|
||||
pub all_traits: Vec<DefId>,
|
||||
}
|
||||
|
||||
@ -173,98 +170,6 @@ impl<'tcx> DocContext<'tcx> {
|
||||
self.tcx.hir().as_local_hir_id(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_real_ty<F>(&self,
|
||||
def_id: DefId,
|
||||
def_ctor: &F,
|
||||
real_name: &Option<Ident>,
|
||||
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 {
|
||||
|
@ -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<Item> = 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<Item> {
|
||||
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,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has foo/struct.S.html '//h3[@id="impl-Into"]//code' 'impl<T, U> Into for T'
|
||||
// @has foo/struct.S.html '//h3[@id="impl-Into%3CU%3E"]//code' 'impl<T, U> Into<U> for T'
|
||||
pub struct S2 {}
|
||||
mod m {
|
||||
pub struct S {}
|
||||
|
@ -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};
|
||||
|
@ -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>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
|
||||
|
||||
pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};
|
||||
|
Loading…
x
Reference in New Issue
Block a user