span: Span::dummy(),
unsafety: hir::Unsafety::Normal,
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),
items: Vec::new(),
negative_polarity,
if let Some(data) = ty_to_fn.get(&ty) {
let (poly_trait, output) =
(data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new));
- let new_ty = match poly_trait.trait_ {
- Type::ResolvedPath { ref path, ref did } => {
- 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 {
- GenericArgs::AngleBracketed { args, .. } => {
- let types = args
- .iter()
- .filter_map(|arg| match arg {
- GenericArg::Type(ty) => Some(ty.clone()),
- _ => None,
- })
- .collect();
- (types, None)
- }
- GenericArgs::Parenthesized { inputs, output, .. } => {
- (inputs, output)
- }
- };
+ let mut new_path = poly_trait.trait_.clone();
+ let last_segment = new_path.segments.pop().expect("segments were empty");
+
+ let (old_input, old_output) = match last_segment.args {
+ GenericArgs::AngleBracketed { args, .. } => {
+ let types = args
+ .iter()
+ .filter_map(|arg| match arg {
+ GenericArg::Type(ty) => Some(ty.clone()),
+ _ => None,
+ })
+ .collect();
+ (types, None)
+ }
+ GenericArgs::Parenthesized { inputs, output } => (inputs, output),
+ };
- if old_output.is_some() && old_output != output {
- panic!(
- "Output mismatch for {:?} {:?} {:?}",
- ty, old_output, data.1
- );
- }
+ if old_output.is_some() && old_output != output {
+ panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1);
+ }
- let new_params =
- GenericArgs::Parenthesized { inputs: old_input, output };
+ let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
- new_path
- .segments
- .push(PathSegment { name: last_segment.name, args: new_params });
+ new_path
+ .segments
+ .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(
- PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params },
+ PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params },
hir::TraitBoundModifier::None,
));
}
let mut has_sized = FxHashSet::default();
let mut ty_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();
if b.is_sized_bound(self.cx) {
has_sized.insert(ty.clone());
} else if !b
- .get_trait_type()
- .and_then(|t| {
+ .get_trait_path()
+ .and_then(|trait_| {
ty_to_traits
.get(&ty)
- .map(|bounds| bounds.contains(&strip_type(t.clone())))
+ .map(|bounds| bounds.contains(&strip_path(trait_.clone())))
})
.unwrap_or(false)
{
// that we don't end up with duplicate bounds (e.g., for<'b, 'b>)
for_generics.extend(p.generic_params.clone());
p.generic_params = for_generics.into_iter().collect();
- self.is_fn_ty(&p.trait_)
+ self.is_fn_trait(&p.trait_)
}
_ => false,
};
match lhs {
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
let ty = &*self_type;
- match **trait_ {
- 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 {
- ty_to_fn
- .entry(*ty.clone())
- .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
- .or_insert((None, Some(rhs)));
- continue;
- }
-
- let args = &mut new_trait_path
- .segments
- .last_mut()
- .expect("segments were empty")
- .args;
-
- match args {
- // Convert something like '<T as Iterator::Item> = u8'
- // to 'T: Iterator<Item=u8>'
- GenericArgs::AngleBracketed {
- ref mut bindings, ..
- } => {
- bindings.push(TypeBinding {
- name: left_name,
- kind: TypeBindingKind::Equality { ty: rhs },
- });
- }
- GenericArgs::Parenthesized { .. } => {
- existing_predicates.push(WherePredicate::EqPredicate {
- lhs: lhs.clone(),
- rhs,
- });
- continue; // If something other than a Fn ends up
- // with parenthesis, leave it alone
- }
- }
-
- let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
-
- bounds.insert(GenericBound::TraitBound(
- PolyTrait {
- trait_: Type::ResolvedPath {
- path: new_trait_path,
- did: *did,
- },
- generic_params: Vec::new(),
- },
- hir::TraitBoundModifier::None,
- ));
-
- // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so
- // that we don't see a
- // duplicate bound like `T: Iterator + Iterator<Item=u8>`
- // on the docs page.
- bounds.remove(&GenericBound::TraitBound(
- PolyTrait {
- trait_: *trait_.clone(),
- generic_params: Vec::new(),
- },
- hir::TraitBoundModifier::None,
- ));
- // Avoid creating any new duplicate bounds later in the outer
- // loop
- ty_to_traits
- .entry(*ty.clone())
- .or_default()
- .insert(*trait_.clone());
+ let mut new_trait = *trait_.clone();
+
+ if self.is_fn_trait(trait_) && left_name == sym::Output {
+ ty_to_fn
+ .entry(*ty.clone())
+ .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
+ .or_insert((None, Some(rhs)));
+ continue;
+ }
+
+ let args = &mut new_trait
+ .segments
+ .last_mut()
+ .expect("segments were empty")
+ .args;
+
+ match args {
+ // Convert something like '<T as Iterator::Item> = u8'
+ // to 'T: Iterator<Item=u8>'
+ GenericArgs::AngleBracketed { ref mut bindings, .. } => {
+ bindings.push(TypeBinding {
+ name: left_name,
+ kind: TypeBindingKind::Equality { ty: rhs },
+ });
+ }
+ GenericArgs::Parenthesized { .. } => {
+ existing_predicates.push(WherePredicate::EqPredicate {
+ lhs: lhs.clone(),
+ rhs,
+ });
+ continue; // If something other than a Fn ends up
+ // with parenthesis, leave it alone
}
- _ => panic!("Unexpected trait {:?} for {:?}", trait_, item_def_id),
}
+
+ let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
+
+ bounds.insert(GenericBound::TraitBound(
+ PolyTrait { trait_: new_trait, generic_params: Vec::new() },
+ hir::TraitBoundModifier::None,
+ ));
+
+ // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so
+ // that we don't see a
+ // duplicate bound like `T: Iterator + Iterator<Item=u8>`
+ // on the docs page.
+ bounds.remove(&GenericBound::TraitBound(
+ PolyTrait { trait_: *trait_.clone(), generic_params: Vec::new() },
+ hir::TraitBoundModifier::None,
+ ));
+ // Avoid creating any new duplicate bounds later in the outer
+ // loop
+ ty_to_traits.entry(*ty.clone()).or_default().insert(*trait_.clone());
}
_ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
}
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;
- match ty {
- &Type::ResolvedPath { did, .. } => {
- did == tcx.require_lang_item(LangItem::Fn, None)
- || did == tcx.require_lang_item(LangItem::FnMut, None)
- || did == tcx.require_lang_item(LangItem::FnOnce, None)
- }
- _ => false,
- }
+ let did = path.res.def_id();
+ did == tcx.require_lang_item(LangItem::Fn, None)
+ || did == tcx.require_lang_item(LangItem::FnMut, None)
+ || did == tcx.require_lang_item(LangItem::FnOnce, None)
}
}
.clean(self.cx),
// 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().expect_path(),
- ),
+ trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()),
for_: ty.clean(self.cx),
items: self
.cx
}
// Return if the trait itself or any types of the generic parameters are doc(hidden).
- let mut stack: Vec<&Type> = trait_.iter().collect();
- stack.push(&for_);
+ let mut stack: Vec<&Type> = vec![&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() {
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;
}
}
}
}
- if let Some(trait_did) = trait_.def_id() {
- record_extern_trait(cx, trait_did);
+ if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) {
+ record_extern_trait(cx, did);
}
let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
span: clean::types::rustc_span(did, cx.tcx),
unsafety: hir::Unsafety::Normal,
generics,
- trait_: trait_.map(|t| t.expect_path()),
+ trait_,
for_,
items: trait_items,
negative_polarity: polarity.clean(cx),
ref mut bounds,
..
} if *s == kw::SelfUpper => {
- bounds.retain(|bound| match *bound {
- clean::GenericBound::TraitBound(
- clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. },
- _,
- ) => did != trait_did,
+ bounds.retain(|bound| match bound {
+ clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
+ trait_.res.def_id() != trait_did
+ }
_ => true,
});
}
}
}
- g.where_predicates.retain(|pred| match *pred {
+ g.where_predicates.retain(|pred| match pred {
clean::WherePredicate::BoundPredicate {
- ty:
- clean::QPath {
- self_type: box clean::Generic(ref s),
- trait_: box clean::ResolvedPath { did, .. },
- name: ref _name,
- ..
- },
- ref bounds,
+ ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. },
+ bounds,
..
- } => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
+ } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.res.def_id() == trait_did),
_ => true,
});
g
}
}
-impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
- fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl Clean<Path> for (ty::TraitRef<'_>, &[TypeBinding]) {
+ fn clean(&self, cx: &mut DocContext<'_>) -> Path {
let (trait_ref, bounds) = *self;
let kind = cx.tcx.def_kind(trait_ref.def_id).into();
if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
- ResolvedPath { path, did: trait_ref.def_id }
+ path
}
}
impl Clean<Path> for hir::TraitRef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Path {
- self.path.clean(cx)
+ let path = self.path.clean(cx);
+ register_res(cx, path.res);
+ path
}
}
if *name != my_name {
return None;
}
- match **trait_ {
- ResolvedPath { did, .. } if did == self.container.id() => {}
- _ => return None,
+ if trait_.res.def_id() != self.container.id() {
+ return None;
}
match **self_type {
Generic(ref s) if *s == kw::SelfUpper => {}
res: Res::Def(DefKind::Trait, trait_def),
segments: trait_segments.clean(cx),
};
+ register_res(cx, trait_path.res);
Type::QPath {
name: p.segments.last().expect("segments were empty").ident.name,
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
self_type: box qself.clean(cx),
- trait_: box resolve_type(cx, trait_path),
+ trait_: box trait_path,
}
}
hir::QPath::TypeRelative(ref qself, ref segment) => {
_ => bug!("clean: expected associated type, found `{:?}`", ty),
};
let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
+ register_res(cx, trait_path.res);
Type::QPath {
name: segment.ident.name,
self_def_id: res.opt_def_id(),
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"),
let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
- let bound = PolyTrait {
- trait_: ResolvedPath { path, did },
- generic_params: Vec::new(),
- };
+ let bound = PolyTrait { trait_: path, generic_params: Vec::new() };
bounds.push(bound);
}
}
let path = external_path(cx, did, false, bindings, substs);
- bounds.insert(
- 0,
- PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() },
- );
+ bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() });
DynTrait(bounds, lifetime)
}
clean::GenericBound::TraitBound(ref mut tr, _) => tr,
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
// of, the bound's trait `did` then we can keep going, otherwise
// 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;
}
- 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 {
PP::AngleBracketed { ref mut bindings, .. } => {
bindings.push(clean::TypeBinding {
let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(
- PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() },
+ PolyTrait { trait_: path, generic_params: Vec::new() },
hir::TraitBoundModifier::Maybe,
)
}
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 {
Some(trait_.clone())
} else {
/// A trait reference, which may have higher ranked lifetimes.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
crate struct PolyTrait {
- crate trait_: Type,
+ crate trait_: Path,
crate generic_params: Vec<GenericParamDef>,
}
name: Symbol,
self_type: Box<Type>,
self_def_id: Option<DefId>,
- trait_: Box<Type>,
+ // FIXME: remove this `Box`; it's unnecessary
+ trait_: Box<Path>,
},
// `_`
}
}
- // 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 {
match *self {
Generic(name) => name == kw::SelfUpper,
}
}
- 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 {
matches!(self, Type::Generic(_))
}
QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
_ => return None,
};
- let trait_did = match **trait_ {
- ResolvedPath { did, .. } => did,
- _ => return None,
- };
- Some((&self_, trait_did, *name))
+ Some((&self_, trait_.res.def_id(), *name))
}
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
let t: PrimitiveType = match *self {
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()),
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
}
})
}
+
+ 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
use crate::clean::blanket_impl::BlanketImplFinder;
use crate::clean::{
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,
};
use crate::core::DocContext;
}
}
-crate fn strip_type(ty: Type) -> Type {
- 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 {
+crate fn strip_path(path: Path) -> Path {
let segments = path
.segments
.iter()
use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_target::spec::abi::Abi;
-use crate::clean::{
- self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType,
-};
+use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, ItemId, PrimitiveType};
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
use crate::html::render::cache::ExternalLocation;
}
}
clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => {
- let should_show_cast = match *trait_ {
- box clean::ResolvedPath { ref path, .. } => {
- !path.segments.is_empty()
- && self_def_id
- .zip(trait_.def_id())
- .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
- }
- _ => true,
- };
+ let should_show_cast = !trait_.segments.is_empty()
+ && self_def_id
+ .zip(Some(trait_.res.def_id()))
+ .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_);
if f.alternate() {
if should_show_cast {
write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
write!(f, "{}::", self_type.print(cx))?
}
};
- match *trait_ {
- // 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
- // notation as much as possible by making `C` a hyperlink to trait
- // `B` to disambiguate.
- //
- // FIXME: this is still a lossy conversion and there should probably
- // be a better way of representing this in general? Most of
- // the ugliness comes from inlining across crates where
- // everything comes in as a fully resolved QPath (hard to
- // look at).
- box clean::ResolvedPath { did, .. } => {
- match href(did, cx) {
- Ok((ref url, _, ref path)) if !f.alternate() => {
- write!(
- f,
- "<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
+ // 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
+ // notation as much as possible by making `C` a hyperlink to trait
+ // `B` to disambiguate.
+ //
+ // FIXME: this is still a lossy conversion and there should probably
+ // be a better way of representing this in general? Most of
+ // the ugliness comes from inlining across crates where
+ // everything comes in as a fully resolved QPath (hard to
+ // look at).
+ match href(trait_.res.def_id(), cx) {
+ Ok((ref url, _, ref path)) if !f.alternate() => {
+ write!(
+ f,
+ "<a class=\"type\" href=\"{url}#{shortty}.{name}\" \
title=\"type {path}::{name}\">{name}</a>",
- url = url,
- shortty = ItemType::AssocType,
- name = name,
- path = path.join("::")
- )?;
- }
- _ => write!(f, "{}", name)?,
- }
- Ok(())
+ url = url,
+ shortty = ItemType::AssocType,
+ name = name,
+ path = path.join("::")
+ )?;
}
- _ => write!(f, "{}", name),
+ _ => write!(f, "{}", name)?,
}
+ Ok(())
}
}
}
fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<Symbol> {
match *clean_type {
clean::ResolvedPath { ref path, .. } => {
- let segments = &path.segments;
- 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
- )
- });
+ let path_segment = path.segments.last().unwrap();
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::Primitive(ref p) => Some(p.as_sym()),
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic),
}
if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
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);
nb_added += adds;
if adds == 0 && !ty.is_full_generic() {
let mut visited = FxHashSet::default();
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);
while let Some(ty) = work.pop_front() {
}
match ty {
- clean::Type::ResolvedPath { 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::ResolvedPath { did, .. } => process_path(did),
clean::Type::Tuple(tys) => {
work.extend(tys.into_iter());
}
}
clean::Type::QPath { self_type, trait_, .. } => {
work.push_back(*self_type);
- work.push_back(*trait_);
+ process_path(trait_.res.def_id());
}
_ => {}
}
use clean::GenericBound::*;
match bound {
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 {
- trait_: trait_.into_tcx(tcx),
+ trait_,
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
modifier: from_trait_bound_modifier(modifier),
}
param_names: Vec::new(),
},
DynTrait(mut bounds, lt) => {
- let (path, id) = match bounds.remove(0).trait_ {
- ResolvedPath { path, did, .. } => (path, did),
- _ => unreachable!(),
- };
+ let first_trait = bounds.remove(0).trait_;
Type::ResolvedPath {
- name: path.whole_name(),
- id: from_item_id(id.into()),
- args: path
+ name: first_trait.whole_name(),
+ id: from_item_id(first_trait.res.def_id().into()),
+ args: first_trait
.segments
.last()
.map(|args| Box::new(args.clone().args.into_tcx(tcx))),
mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_tcx(tcx)),
},
- QPath { name, self_type, trait_, .. } => Type::QualifiedPath {
- name: name.to_string(),
- self_type: Box::new((*self_type).into_tcx(tcx)),
- trait_: Box::new((*trait_).into_tcx(tcx)),
- },
+ 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(),
+ self_type: Box::new((*self_type).into_tcx(tcx)),
+ trait_: Box::new(trait_),
+ }
+ }
}
}
}
blanket_impl,
span: _span,
} = 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 did = path.res.def_id();
clean::ResolvedPath { path, did }.into_tcx(tcx)