提交 91d3b720 编写于 作者: N Noah Lev

Use `Path` instead of `Type` in `PolyTrait`

The change to `impl Clean<Path> for hir::TraitRef<'_>` was necessary to
fix a test failure for `src/test/rustdoc/trait-alias-mention.rs`.
Here's why:

The old code path was through `impl Clean<Type> for hir::TraitRef<'_>`,
which called `resolve_type`, which in turn called `register_res`. Now,
because `PolyTrait` uses a `Path` instead of a `Type`, the impl of
`Clean<Path>` was being run, which did not call `register_res`, causing
the trait alias to not be recorded in the `external_paths` cache.
上级 4c6385ff
...@@ -118,7 +118,7 @@ fn generate_for_trait( ...@@ -118,7 +118,7 @@ fn generate_for_trait(
span: Span::dummy(), span: Span::dummy(),
unsafety: hir::Unsafety::Normal, unsafety: hir::Unsafety::Normal,
generics: new_generics, generics: new_generics,
trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path()), trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()),
for_: ty.clean(self.cx), for_: ty.clean(self.cx),
items: Vec::new(), items: Vec::new(),
negative_polarity, negative_polarity,
...@@ -353,11 +353,8 @@ fn make_final_bounds( ...@@ -353,11 +353,8 @@ fn make_final_bounds(
if let Some(data) = ty_to_fn.get(&ty) { if let Some(data) = ty_to_fn.get(&ty) {
let (poly_trait, output) = let (poly_trait, output) =
(data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new)); (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new));
let new_ty = match poly_trait.trait_ { let mut new_path = poly_trait.trait_.clone();
Type::ResolvedPath { ref path, ref did } => { let last_segment = new_path.segments.pop().expect("segments were empty");
let mut new_path = path.clone();
let last_segment =
new_path.segments.pop().expect("segments were empty");
let (old_input, old_output) = match last_segment.args { let (old_input, old_output) = match last_segment.args {
GenericArgs::AngleBracketed { args, .. } => { GenericArgs::AngleBracketed { args, .. } => {
...@@ -370,31 +367,21 @@ fn make_final_bounds( ...@@ -370,31 +367,21 @@ fn make_final_bounds(
.collect(); .collect();
(types, None) (types, None)
} }
GenericArgs::Parenthesized { inputs, output, .. } => { GenericArgs::Parenthesized { inputs, output } => (inputs, output),
(inputs, output)
}
}; };
if old_output.is_some() && old_output != output { if old_output.is_some() && old_output != output {
panic!( panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1);
"Output mismatch for {:?} {:?} {:?}",
ty, old_output, data.1
);
} }
let new_params = let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
GenericArgs::Parenthesized { inputs: old_input, output };
new_path new_path
.segments .segments
.push(PathSegment { name: last_segment.name, args: new_params }); .push(PathSegment { name: last_segment.name, args: new_params });
Type::ResolvedPath { path: new_path, did: *did }
}
_ => panic!("Unexpected data: {:?}, {:?}", ty, data),
};
bounds.insert(GenericBound::TraitBound( bounds.insert(GenericBound::TraitBound(
PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params }, PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params },
hir::TraitBoundModifier::None, hir::TraitBoundModifier::None,
)); ));
} }
...@@ -476,7 +463,7 @@ fn param_env_to_generics( ...@@ -476,7 +463,7 @@ fn param_env_to_generics(
let mut has_sized = FxHashSet::default(); let mut has_sized = FxHashSet::default();
let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
let mut ty_to_traits: FxHashMap<Type, FxHashSet<Type>> = Default::default(); let mut ty_to_traits: FxHashMap<Type, FxHashSet<Path>> = Default::default();
let mut ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)> = Default::default(); let mut ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)> = Default::default();
...@@ -511,11 +498,11 @@ fn param_env_to_generics( ...@@ -511,11 +498,11 @@ fn param_env_to_generics(
if b.is_sized_bound(self.cx) { if b.is_sized_bound(self.cx) {
has_sized.insert(ty.clone()); has_sized.insert(ty.clone());
} else if !b } else if !b
.get_trait_type() .get_trait_path()
.and_then(|t| { .and_then(|trait_| {
ty_to_traits ty_to_traits
.get(&ty) .get(&ty)
.map(|bounds| bounds.contains(&strip_type(t.clone()))) .map(|bounds| bounds.contains(&strip_path(trait_.clone())))
}) })
.unwrap_or(false) .unwrap_or(false)
{ {
...@@ -532,7 +519,7 @@ fn param_env_to_generics( ...@@ -532,7 +519,7 @@ fn param_env_to_generics(
// that we don't end up with duplicate bounds (e.g., for<'b, 'b>) // that we don't end up with duplicate bounds (e.g., for<'b, 'b>)
for_generics.extend(p.generic_params.clone()); for_generics.extend(p.generic_params.clone());
p.generic_params = for_generics.into_iter().collect(); p.generic_params = for_generics.into_iter().collect();
self.is_fn_ty(&p.trait_) self.is_fn_trait(&p.trait_)
} }
_ => false, _ => false,
}; };
...@@ -558,11 +545,9 @@ fn param_env_to_generics( ...@@ -558,11 +545,9 @@ fn param_env_to_generics(
match lhs { match lhs {
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => { Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
let ty = &*self_type; let ty = &*self_type;
match **trait_ { let mut new_trait = *trait_.clone();
Type::ResolvedPath { path: ref trait_path, ref did } => {
let mut new_trait_path = trait_path.clone();
if self.is_fn_ty(trait_) && left_name == sym::Output { if self.is_fn_trait(trait_) && left_name == sym::Output {
ty_to_fn ty_to_fn
.entry(*ty.clone()) .entry(*ty.clone())
.and_modify(|e| *e = (e.0.clone(), Some(rhs.clone()))) .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
...@@ -570,7 +555,7 @@ fn param_env_to_generics( ...@@ -570,7 +555,7 @@ fn param_env_to_generics(
continue; continue;
} }
let args = &mut new_trait_path let args = &mut new_trait
.segments .segments
.last_mut() .last_mut()
.expect("segments were empty") .expect("segments were empty")
...@@ -579,9 +564,7 @@ fn param_env_to_generics( ...@@ -579,9 +564,7 @@ fn param_env_to_generics(
match args { match args {
// Convert something like '<T as Iterator::Item> = u8' // Convert something like '<T as Iterator::Item> = u8'
// to 'T: Iterator<Item=u8>' // to 'T: Iterator<Item=u8>'
GenericArgs::AngleBracketed { GenericArgs::AngleBracketed { ref mut bindings, .. } => {
ref mut bindings, ..
} => {
bindings.push(TypeBinding { bindings.push(TypeBinding {
name: left_name, name: left_name,
kind: TypeBindingKind::Equality { ty: rhs }, kind: TypeBindingKind::Equality { ty: rhs },
...@@ -600,13 +583,7 @@ fn param_env_to_generics( ...@@ -600,13 +583,7 @@ fn param_env_to_generics(
let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
bounds.insert(GenericBound::TraitBound( bounds.insert(GenericBound::TraitBound(
PolyTrait { PolyTrait { trait_: new_trait, generic_params: Vec::new() },
trait_: Type::ResolvedPath {
path: new_trait_path,
did: *did,
},
generic_params: Vec::new(),
},
hir::TraitBoundModifier::None, hir::TraitBoundModifier::None,
)); ));
...@@ -615,21 +592,12 @@ fn param_env_to_generics( ...@@ -615,21 +592,12 @@ fn param_env_to_generics(
// duplicate bound like `T: Iterator + Iterator<Item=u8>` // duplicate bound like `T: Iterator + Iterator<Item=u8>`
// on the docs page. // on the docs page.
bounds.remove(&GenericBound::TraitBound( bounds.remove(&GenericBound::TraitBound(
PolyTrait { PolyTrait { trait_: *trait_.clone(), generic_params: Vec::new() },
trait_: *trait_.clone(),
generic_params: Vec::new(),
},
hir::TraitBoundModifier::None, hir::TraitBoundModifier::None,
)); ));
// Avoid creating any new duplicate bounds later in the outer // Avoid creating any new duplicate bounds later in the outer
// loop // loop
ty_to_traits ty_to_traits.entry(*ty.clone()).or_default().insert(*trait_.clone());
.entry(*ty.clone())
.or_default()
.insert(*trait_.clone());
}
_ => panic!("Unexpected trait {:?} for {:?}", trait_, item_def_id),
}
} }
_ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id), _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
} }
...@@ -721,17 +689,13 @@ fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) { ...@@ -721,17 +689,13 @@ fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) {
vec.sort_by_cached_key(|x| format!("{:?}", x)) vec.sort_by_cached_key(|x| format!("{:?}", x))
} }
fn is_fn_ty(&self, ty: &Type) -> bool { fn is_fn_trait(&self, path: &Path) -> bool {
let tcx = self.cx.tcx; let tcx = self.cx.tcx;
match ty { let did = path.res.def_id();
&Type::ResolvedPath { did, .. } => {
did == tcx.require_lang_item(LangItem::Fn, None) did == tcx.require_lang_item(LangItem::Fn, None)
|| did == tcx.require_lang_item(LangItem::FnMut, None) || did == tcx.require_lang_item(LangItem::FnMut, None)
|| did == tcx.require_lang_item(LangItem::FnOnce, None) || did == tcx.require_lang_item(LangItem::FnOnce, None)
} }
_ => false,
}
}
} }
fn region_name(region: Region<'_>) -> Option<Symbol> { fn region_name(region: Region<'_>) -> Option<Symbol> {
......
...@@ -114,9 +114,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { ...@@ -114,9 +114,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
.clean(self.cx), .clean(self.cx),
// FIXME(eddyb) compute both `trait_` and `for_` from // FIXME(eddyb) compute both `trait_` and `for_` from
// the post-inference `trait_ref`, as it's more accurate. // the post-inference `trait_ref`, as it's more accurate.
trait_: Some( trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()),
trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path(),
),
for_: ty.clean(self.cx), for_: ty.clean(self.cx),
items: self items: self
.cx .cx
......
...@@ -455,11 +455,20 @@ fn merge_attrs( ...@@ -455,11 +455,20 @@ fn merge_attrs(
} }
// Return if the trait itself or any types of the generic parameters are doc(hidden). // Return if the trait itself or any types of the generic parameters are doc(hidden).
let mut stack: Vec<&Type> = trait_.iter().collect(); let mut stack: Vec<&Type> = vec![&for_];
stack.push(&for_);
if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) {
if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
return;
}
}
if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
stack.extend(generics);
}
while let Some(ty) = stack.pop() { while let Some(ty) = stack.pop() {
if let Some(did) = ty.def_id() { if let Some(did) = ty.def_id() {
if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
return; return;
} }
} }
...@@ -468,8 +477,8 @@ fn merge_attrs( ...@@ -468,8 +477,8 @@ fn merge_attrs(
} }
} }
if let Some(trait_did) = trait_.def_id() { if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) {
record_extern_trait(cx, trait_did); record_extern_trait(cx, did);
} }
let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
...@@ -483,7 +492,7 @@ fn merge_attrs( ...@@ -483,7 +492,7 @@ fn merge_attrs(
span: clean::types::rustc_span(did, cx.tcx), span: clean::types::rustc_span(did, cx.tcx),
unsafety: hir::Unsafety::Normal, unsafety: hir::Unsafety::Normal,
generics, generics,
trait_: trait_.map(|t| t.expect_path()), trait_,
for_, for_,
items: trait_items, items: trait_items,
negative_polarity: polarity.clean(cx), negative_polarity: polarity.clean(cx),
...@@ -620,11 +629,10 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: ...@@ -620,11 +629,10 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
ref mut bounds, ref mut bounds,
.. ..
} if *s == kw::SelfUpper => { } if *s == kw::SelfUpper => {
bounds.retain(|bound| match *bound { bounds.retain(|bound| match bound {
clean::GenericBound::TraitBound( clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. }, trait_.res.def_id() != trait_did
_, }
) => did != trait_did,
_ => true, _ => true,
}); });
} }
...@@ -632,18 +640,12 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: ...@@ -632,18 +640,12 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
} }
} }
g.where_predicates.retain(|pred| match *pred { g.where_predicates.retain(|pred| match pred {
clean::WherePredicate::BoundPredicate { clean::WherePredicate::BoundPredicate {
ty: ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. },
clean::QPath { bounds,
self_type: box clean::Generic(ref s),
trait_: box clean::ResolvedPath { did, .. },
name: ref _name,
..
},
ref bounds,
.. ..
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did), } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.res.def_id() == trait_did),
_ => true, _ => true,
}); });
g g
......
...@@ -152,8 +152,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { ...@@ -152,8 +152,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
} }
} }
impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) { impl Clean<Path> for (ty::TraitRef<'_>, &[TypeBinding]) {
fn clean(&self, cx: &mut DocContext<'_>) -> Type { fn clean(&self, cx: &mut DocContext<'_>) -> Path {
let (trait_ref, bounds) = *self; let (trait_ref, bounds) = *self;
let kind = cx.tcx.def_kind(trait_ref.def_id).into(); let kind = cx.tcx.def_kind(trait_ref.def_id).into();
if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
...@@ -168,7 +168,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type { ...@@ -168,7 +168,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
ResolvedPath { path, did: trait_ref.def_id } path
} }
} }
...@@ -905,7 +905,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type { ...@@ -905,7 +905,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
impl Clean<Path> for hir::TraitRef<'_> { impl Clean<Path> for hir::TraitRef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Path { fn clean(&self, cx: &mut DocContext<'_>) -> Path {
self.path.clean(cx) let path = self.path.clean(cx);
register_res(cx, path.res);
path
} }
} }
...@@ -1111,9 +1113,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item { ...@@ -1111,9 +1113,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
if *name != my_name { if *name != my_name {
return None; return None;
} }
match **trait_ { if trait_.res.def_id() != self.container.id() {
ResolvedPath { did, .. } if did == self.container.id() => {} return None;
_ => return None,
} }
match **self_type { match **self_type {
Generic(ref s) if *s == kw::SelfUpper => {} Generic(ref s) if *s == kw::SelfUpper => {}
...@@ -1286,11 +1287,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { ...@@ -1286,11 +1287,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
res: Res::Def(DefKind::Trait, trait_def), res: Res::Def(DefKind::Trait, trait_def),
segments: trait_segments.clean(cx), segments: trait_segments.clean(cx),
}; };
register_res(cx, trait_path.res);
Type::QPath { Type::QPath {
name: p.segments.last().expect("segments were empty").ident.name, name: p.segments.last().expect("segments were empty").ident.name,
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)), self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
self_type: box qself.clean(cx), self_type: box qself.clean(cx),
trait_: box resolve_type(cx, trait_path), trait_: box trait_path,
} }
} }
hir::QPath::TypeRelative(ref qself, ref segment) => { hir::QPath::TypeRelative(ref qself, ref segment) => {
...@@ -1302,11 +1304,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { ...@@ -1302,11 +1304,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
_ => bug!("clean: expected associated type, found `{:?}`", ty), _ => bug!("clean: expected associated type, found `{:?}`", ty),
}; };
let trait_path = hir::Path { span, res, segments: &[] }.clean(cx); let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
register_res(cx, trait_path.res);
Type::QPath { Type::QPath {
name: segment.ident.name, name: segment.ident.name,
self_def_id: res.opt_def_id(), self_def_id: res.opt_def_id(),
self_type: box qself.clean(cx), self_type: box qself.clean(cx),
trait_: box resolve_type(cx, trait_path), trait_: box trait_path,
} }
} }
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
...@@ -1475,10 +1478,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type { ...@@ -1475,10 +1478,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
let empty = cx.tcx.intern_substs(&[]); let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, did, false, vec![], empty); let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait); inline::record_extern_fqn(cx, did, ItemType::Trait);
let bound = PolyTrait { let bound = PolyTrait { trait_: path, generic_params: Vec::new() };
trait_: ResolvedPath { path, did },
generic_params: Vec::new(),
};
bounds.push(bound); bounds.push(bound);
} }
...@@ -1491,10 +1491,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type { ...@@ -1491,10 +1491,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
} }
let path = external_path(cx, did, false, bindings, substs); let path = external_path(cx, did, false, bindings, substs);
bounds.insert( bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() });
0,
PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() },
);
DynTrait(bounds, lifetime) DynTrait(bounds, lifetime)
} }
......
...@@ -99,17 +99,13 @@ ...@@ -99,17 +99,13 @@
clean::GenericBound::TraitBound(ref mut tr, _) => tr, clean::GenericBound::TraitBound(ref mut tr, _) => tr,
clean::GenericBound::Outlives(..) => return false, clean::GenericBound::Outlives(..) => return false,
}; };
let (did, path) = match trait_ref.trait_ {
clean::ResolvedPath { did, ref mut path, .. } => (did, path),
_ => return false,
};
// If this QPath's trait `trait_did` is the same as, or a supertrait // If this QPath's trait `trait_did` is the same as, or a supertrait
// of, the bound's trait `did` then we can keep going, otherwise // of, the bound's trait `did` then we can keep going, otherwise
// this is just a plain old equality bound. // this is just a plain old equality bound.
if !trait_is_same_or_supertrait(cx, did, trait_did) { if !trait_is_same_or_supertrait(cx, trait_ref.trait_.res.def_id(), trait_did) {
return false; return false;
} }
let last = path.segments.last_mut().expect("segments were empty"); let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
match last.args { match last.args {
PP::AngleBracketed { ref mut bindings, .. } => { PP::AngleBracketed { ref mut bindings, .. } => {
bindings.push(clean::TypeBinding { bindings.push(clean::TypeBinding {
......
...@@ -1114,7 +1114,7 @@ impl GenericBound { ...@@ -1114,7 +1114,7 @@ impl GenericBound {
let path = external_path(cx, did, false, vec![], empty); let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait); inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound( GenericBound::TraitBound(
PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() }, PolyTrait { trait_: path, generic_params: Vec::new() },
hir::TraitBoundModifier::Maybe, hir::TraitBoundModifier::Maybe,
) )
} }
...@@ -1136,7 +1136,7 @@ impl GenericBound { ...@@ -1136,7 +1136,7 @@ impl GenericBound {
None None
} }
crate fn get_trait_type(&self) -> Option<Type> { crate fn get_trait_path(&self) -> Option<Path> {
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
Some(trait_.clone()) Some(trait_.clone())
} else { } else {
...@@ -1368,7 +1368,7 @@ fn def_id_full(&self, cache: &Cache) -> Option<DefId> { ...@@ -1368,7 +1368,7 @@ fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
/// A trait reference, which may have higher ranked lifetimes. /// A trait reference, which may have higher ranked lifetimes.
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
crate struct PolyTrait { crate struct PolyTrait {
crate trait_: Type, crate trait_: Path,
crate generic_params: Vec<GenericParamDef>, crate generic_params: Vec<GenericParamDef>,
} }
...@@ -1408,7 +1408,8 @@ fn def_id_full(&self, cache: &Cache) -> Option<DefId> { ...@@ -1408,7 +1408,8 @@ fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
name: Symbol, name: Symbol,
self_type: Box<Type>, self_type: Box<Type>,
self_def_id: Option<DefId>, self_def_id: Option<DefId>,
trait_: Box<Type>, // FIXME: remove this `Box`; it's unnecessary
trait_: Box<Path>,
}, },
// `_` // `_`
...@@ -1473,15 +1474,6 @@ impl Type { ...@@ -1473,15 +1474,6 @@ impl Type {
} }
} }
// FIXME: temporary
#[track_caller]
crate fn expect_path(self) -> Path {
match self {
ResolvedPath { path, .. } => path,
_ => panic!("not a ResolvedPath: {:?}", self),
}
}
crate fn is_self_type(&self) -> bool { crate fn is_self_type(&self) -> bool {
match *self { match *self {
Generic(name) => name == kw::SelfUpper, Generic(name) => name == kw::SelfUpper,
...@@ -1496,19 +1488,6 @@ impl Type { ...@@ -1496,19 +1488,6 @@ impl Type {
} }
} }
crate fn bindings(&self) -> Option<&[TypeBinding]> {
match *self {
ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| {
if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
Some(&**bindings)
} else {
None
}
}),
_ => None,
}
}
crate fn is_full_generic(&self) -> bool { crate fn is_full_generic(&self) -> bool {
matches!(self, Type::Generic(_)) matches!(self, Type::Generic(_))
} }
...@@ -1522,17 +1501,13 @@ impl Type { ...@@ -1522,17 +1501,13 @@ impl Type {
QPath { self_type, trait_, name, .. } => (self_type, trait_, name), QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
_ => return None, _ => return None,
}; };
let trait_did = match **trait_ { Some((&self_, trait_.res.def_id(), *name))
ResolvedPath { did, .. } => did,
_ => return None,
};
Some((&self_, trait_did, *name))
} }
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> { fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
let t: PrimitiveType = match *self { let t: PrimitiveType = match *self {
ResolvedPath { did, .. } => return Some(did), ResolvedPath { did, .. } => return Some(did),
DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache), DynTrait(ref bounds, _) => return Some(bounds[0].trait_.res.def_id()),
Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
...@@ -2006,6 +1981,16 @@ impl Path { ...@@ -2006,6 +1981,16 @@ impl Path {
} }
}) })
} }
crate fn bindings(&self) -> Option<&[TypeBinding]> {
self.segments.last().and_then(|seg| {
if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
Some(&**bindings)
} else {
None
}
})
}
} }
// FIXME: this is temporary // FIXME: this is temporary
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::blanket_impl::BlanketImplFinder;
use crate::clean::{ use crate::clean::{
inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
ItemKind, Lifetime, Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type,
TypeBinding, Visibility, TypeBinding, Visibility,
}; };
use crate::core::DocContext; use crate::core::DocContext;
...@@ -156,39 +156,7 @@ pub(super) fn external_path( ...@@ -156,39 +156,7 @@ pub(super) fn external_path(
} }
} }
crate fn strip_type(ty: Type) -> Type { crate fn strip_path(path: Path) -> Path {
match ty {
Type::ResolvedPath { path, did } => Type::ResolvedPath { path: strip_path(&path), did },
Type::DynTrait(mut bounds, lt) => {
let first = bounds.remove(0);
let stripped_trait = strip_type(first.trait_);
bounds.insert(
0,
PolyTrait { trait_: stripped_trait, generic_params: first.generic_params },
);
Type::DynTrait(bounds, lt)
}
Type::Tuple(inner_tys) => {
Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
}
Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
Type::BorrowedRef { lifetime, mutability, type_ } => {
Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
}
Type::QPath { name, self_type, trait_, self_def_id } => Type::QPath {
name,
self_def_id,
self_type: Box::new(strip_type(*self_type)),
trait_: Box::new(strip_type(*trait_)),
},
_ => ty,
}
}
crate fn strip_path(path: &Path) -> Path {
let segments = path let segments = path
.segments .segments
.iter() .iter()
......
...@@ -18,9 +18,7 @@ ...@@ -18,9 +18,7 @@
use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::clean::{ use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, ItemId, PrimitiveType};
self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType,
};
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::escape::Escape; use crate::html::escape::Escape;
use crate::html::render::cache::ExternalLocation; use crate::html::render::cache::ExternalLocation;
...@@ -914,15 +912,10 @@ fn fmt_type<'cx>( ...@@ -914,15 +912,10 @@ fn fmt_type<'cx>(
} }
} }
clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => { clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => {
let should_show_cast = match *trait_ { let should_show_cast = !trait_.segments.is_empty()
box clean::ResolvedPath { ref path, .. } => {
!path.segments.is_empty()
&& self_def_id && self_def_id
.zip(trait_.def_id()) .zip(Some(trait_.res.def_id()))
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_) .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_);
}
_ => true,
};
if f.alternate() { if f.alternate() {
if should_show_cast { if should_show_cast {
write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
...@@ -936,7 +929,6 @@ fn fmt_type<'cx>( ...@@ -936,7 +929,6 @@ fn fmt_type<'cx>(
write!(f, "{}::", self_type.print(cx))? write!(f, "{}::", self_type.print(cx))?
} }
}; };
match *trait_ {
// It's pretty unsightly to look at `<A as B>::C` in output, and // It's pretty unsightly to look at `<A as B>::C` in output, and
// we've got hyperlinking on our side, so try to avoid longer // we've got hyperlinking on our side, so try to avoid longer
// notation as much as possible by making `C` a hyperlink to trait // notation as much as possible by making `C` a hyperlink to trait
...@@ -947,8 +939,7 @@ fn fmt_type<'cx>( ...@@ -947,8 +939,7 @@ fn fmt_type<'cx>(
// the ugliness comes from inlining across crates where // the ugliness comes from inlining across crates where
// everything comes in as a fully resolved QPath (hard to // everything comes in as a fully resolved QPath (hard to
// look at). // look at).
box clean::ResolvedPath { did, .. } => { match href(trait_.res.def_id(), cx) {
match href(did, cx) {
Ok((ref url, _, ref path)) if !f.alternate() => { Ok((ref url, _, ref path)) if !f.alternate() => {
write!( write!(
f, f,
...@@ -964,9 +955,6 @@ fn fmt_type<'cx>( ...@@ -964,9 +955,6 @@ fn fmt_type<'cx>(
} }
Ok(()) Ok(())
} }
_ => write!(f, "{}", name),
}
}
} }
} }
......
...@@ -226,16 +226,13 @@ fn get_index_type(clean_type: &clean::Type) -> RenderType { ...@@ -226,16 +226,13 @@ fn get_index_type(clean_type: &clean::Type) -> RenderType {
fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> { fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> {
match *clean_type { match *clean_type {
clean::ResolvedPath { ref path, .. } => { clean::ResolvedPath { ref path, .. } => {
let segments = &path.segments; let path_segment = path.segments.last().unwrap();
let path_segment = segments.iter().last().unwrap_or_else(|| {
panic!(
"get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path",
clean_type, accept_generic
)
});
Some(path_segment.name) Some(path_segment.name)
} }
clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic), clean::DynTrait(ref bounds, _) => {
let path = &bounds[0].trait_;
Some(path.segments.last().unwrap().name)
}
clean::Generic(s) if accept_generic => Some(s), clean::Generic(s) if accept_generic => Some(s),
clean::Primitive(ref p) => Some(p.as_sym()), clean::Primitive(ref p) => Some(p.as_sym()),
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic),
...@@ -324,7 +321,8 @@ fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> u ...@@ -324,7 +321,8 @@ fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> u
} }
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
for bound in bound.get_bounds().unwrap_or(&[]) { for bound in bound.get_bounds().unwrap_or(&[]) {
if let Some(ty) = bound.get_trait_type() { if let Some(path) = bound.get_trait_path() {
let ty = Type::ResolvedPath { did: path.res.def_id(), path };
let adds = get_real_types(generics, &ty, tcx, recurse + 1, res); let adds = get_real_types(generics, &ty, tcx, recurse + 1, res);
nb_added += adds; nb_added += adds;
if adds == 0 && !ty.is_full_generic() { if adds == 0 && !ty.is_full_generic() {
......
...@@ -2370,6 +2370,15 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> { ...@@ -2370,6 +2370,15 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
let mut visited = FxHashSet::default(); let mut visited = FxHashSet::default();
let mut work = VecDeque::new(); let mut work = VecDeque::new();
let mut process_path = |did: DefId| {
let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone());
let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
if let Some(path) = fqp {
out.push(path.join("::"));
}
};
work.push_back(first_ty); work.push_back(first_ty);
while let Some(ty) = work.pop_front() { while let Some(ty) = work.pop_front() {
...@@ -2378,14 +2387,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> { ...@@ -2378,14 +2387,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
} }
match ty { match ty {
clean::Type::ResolvedPath { did, .. } => { clean::Type::ResolvedPath { did, .. } => process_path(did),
let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone());
let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
if let Some(path) = fqp {
out.push(path.join("::"));
}
}
clean::Type::Tuple(tys) => { clean::Type::Tuple(tys) => {
work.extend(tys.into_iter()); work.extend(tys.into_iter());
} }
...@@ -2403,7 +2405,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> { ...@@ -2403,7 +2405,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
} }
clean::Type::QPath { self_type, trait_, .. } => { clean::Type::QPath { self_type, trait_, .. } => {
work.push_back(*self_type); work.push_back(*self_type);
work.push_back(*trait_); process_path(trait_.res.def_id());
} }
_ => {} _ => {}
} }
......
...@@ -363,8 +363,11 @@ fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self { ...@@ -363,8 +363,11 @@ fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
use clean::GenericBound::*; use clean::GenericBound::*;
match bound { match bound {
TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ =
clean::ResolvedPath { did: trait_.res.def_id(), path: trait_ }.into_tcx(tcx);
GenericBound::TraitBound { GenericBound::TraitBound {
trait_: trait_.into_tcx(tcx), trait_,
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
modifier: from_trait_bound_modifier(modifier), modifier: from_trait_bound_modifier(modifier),
} }
...@@ -394,15 +397,12 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { ...@@ -394,15 +397,12 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
param_names: Vec::new(), param_names: Vec::new(),
}, },
DynTrait(mut bounds, lt) => { DynTrait(mut bounds, lt) => {
let (path, id) = match bounds.remove(0).trait_ { let first_trait = bounds.remove(0).trait_;
ResolvedPath { path, did, .. } => (path, did),
_ => unreachable!(),
};
Type::ResolvedPath { Type::ResolvedPath {
name: path.whole_name(), name: first_trait.whole_name(),
id: from_item_id(id.into()), id: from_item_id(first_trait.res.def_id().into()),
args: path args: first_trait
.segments .segments
.last() .last()
.map(|args| Box::new(args.clone().args.into_tcx(tcx))), .map(|args| Box::new(args.clone().args.into_tcx(tcx))),
...@@ -434,11 +434,15 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { ...@@ -434,11 +434,15 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
mutable: mutability == ast::Mutability::Mut, mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_tcx(tcx)), type_: Box::new((*type_).into_tcx(tcx)),
}, },
QPath { name, self_type, trait_, .. } => Type::QualifiedPath { QPath { name, self_type, trait_, .. } => {
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ = ResolvedPath { did: trait_.res.def_id(), path: *trait_ }.into_tcx(tcx);
Type::QualifiedPath {
name: name.to_string(), name: name.to_string(),
self_type: Box::new((*self_type).into_tcx(tcx)), self_type: Box::new((*self_type).into_tcx(tcx)),
trait_: Box::new((*trait_).into_tcx(tcx)), trait_: Box::new(trait_),
}, }
}
} }
} }
} }
...@@ -507,7 +511,7 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { ...@@ -507,7 +511,7 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
blanket_impl, blanket_impl,
span: _span, span: _span,
} = impl_; } = impl_;
// FIXME: should `trait_` be a Path in JSON? // FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ = trait_.map(|path| { let trait_ = trait_.map(|path| {
let did = path.res.def_id(); let did = path.res.def_id();
clean::ResolvedPath { path, did }.into_tcx(tcx) clean::ResolvedPath { path, did }.into_tcx(tcx)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册