Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 91d3b72

Browse files
committed
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.
1 parent 4c6385f commit 91d3b72

File tree

11 files changed

+208
-306
lines changed

11 files changed

+208
-306
lines changed

src/librustdoc/clean/auto_trait.rs

Lines changed: 86 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
118118
span: Span::dummy(),
119119
unsafety: hir::Unsafety::Normal,
120120
generics: new_generics,
121-
trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path()),
121+
trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()),
122122
for_: ty.clean(self.cx),
123123
items: Vec::new(),
124124
negative_polarity,
@@ -353,48 +353,35 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
353353
if let Some(data) = ty_to_fn.get(&ty) {
354354
let (poly_trait, output) =
355355
(data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new));
356-
let new_ty = match poly_trait.trait_ {
357-
Type::ResolvedPath { ref path, ref did } => {
358-
let mut new_path = path.clone();
359-
let last_segment =
360-
new_path.segments.pop().expect("segments were empty");
361-
362-
let (old_input, old_output) = match last_segment.args {
363-
GenericArgs::AngleBracketed { args, .. } => {
364-
let types = args
365-
.iter()
366-
.filter_map(|arg| match arg {
367-
GenericArg::Type(ty) => Some(ty.clone()),
368-
_ => None,
369-
})
370-
.collect();
371-
(types, None)
372-
}
373-
GenericArgs::Parenthesized { inputs, output, .. } => {
374-
(inputs, output)
375-
}
376-
};
356+
let mut new_path = poly_trait.trait_.clone();
357+
let last_segment = new_path.segments.pop().expect("segments were empty");
358+
359+
let (old_input, old_output) = match last_segment.args {
360+
GenericArgs::AngleBracketed { args, .. } => {
361+
let types = args
362+
.iter()
363+
.filter_map(|arg| match arg {
364+
GenericArg::Type(ty) => Some(ty.clone()),
365+
_ => None,
366+
})
367+
.collect();
368+
(types, None)
369+
}
370+
GenericArgs::Parenthesized { inputs, output } => (inputs, output),
371+
};
377372

378-
if old_output.is_some() && old_output != output {
379-
panic!(
380-
"Output mismatch for {:?} {:?} {:?}",
381-
ty, old_output, data.1
382-
);
383-
}
373+
if old_output.is_some() && old_output != output {
374+
panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1);
375+
}
384376

385-
let new_params =
386-
GenericArgs::Parenthesized { inputs: old_input, output };
377+
let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
387378

388-
new_path
389-
.segments
390-
.push(PathSegment { name: last_segment.name, args: new_params });
379+
new_path
380+
.segments
381+
.push(PathSegment { name: last_segment.name, args: new_params });
391382

392-
Type::ResolvedPath { path: new_path, did: *did }
393-
}
394-
_ => panic!("Unexpected data: {:?}, {:?}", ty, data),
395-
};
396383
bounds.insert(GenericBound::TraitBound(
397-
PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params },
384+
PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params },
398385
hir::TraitBoundModifier::None,
399386
));
400387
}
@@ -476,7 +463,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
476463
let mut has_sized = FxHashSet::default();
477464
let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
478465
let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
479-
let mut ty_to_traits: FxHashMap<Type, FxHashSet<Type>> = Default::default();
466+
let mut ty_to_traits: FxHashMap<Type, FxHashSet<Path>> = Default::default();
480467

481468
let mut ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)> = Default::default();
482469

@@ -511,11 +498,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
511498
if b.is_sized_bound(self.cx) {
512499
has_sized.insert(ty.clone());
513500
} else if !b
514-
.get_trait_type()
515-
.and_then(|t| {
501+
.get_trait_path()
502+
.and_then(|trait_| {
516503
ty_to_traits
517504
.get(&ty)
518-
.map(|bounds| bounds.contains(&strip_type(t.clone())))
505+
.map(|bounds| bounds.contains(&strip_path(trait_.clone())))
519506
})
520507
.unwrap_or(false)
521508
{
@@ -532,7 +519,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
532519
// that we don't end up with duplicate bounds (e.g., for<'b, 'b>)
533520
for_generics.extend(p.generic_params.clone());
534521
p.generic_params = for_generics.into_iter().collect();
535-
self.is_fn_ty(&p.trait_)
522+
self.is_fn_trait(&p.trait_)
536523
}
537524
_ => false,
538525
};
@@ -558,78 +545,59 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
558545
match lhs {
559546
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
560547
let ty = &*self_type;
561-
match **trait_ {
562-
Type::ResolvedPath { path: ref trait_path, ref did } => {
563-
let mut new_trait_path = trait_path.clone();
564-
565-
if self.is_fn_ty(trait_) && left_name == sym::Output {
566-
ty_to_fn
567-
.entry(*ty.clone())
568-
.and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
569-
.or_insert((None, Some(rhs)));
570-
continue;
571-
}
572-
573-
let args = &mut new_trait_path
574-
.segments
575-
.last_mut()
576-
.expect("segments were empty")
577-
.args;
578-
579-
match args {
580-
// Convert something like '<T as Iterator::Item> = u8'
581-
// to 'T: Iterator<Item=u8>'
582-
GenericArgs::AngleBracketed {
583-
ref mut bindings, ..
584-
} => {
585-
bindings.push(TypeBinding {
586-
name: left_name,
587-
kind: TypeBindingKind::Equality { ty: rhs },
588-
});
589-
}
590-
GenericArgs::Parenthesized { .. } => {
591-
existing_predicates.push(WherePredicate::EqPredicate {
592-
lhs: lhs.clone(),
593-
rhs,
594-
});
595-
continue; // If something other than a Fn ends up
596-
// with parenthesis, leave it alone
597-
}
598-
}
599-
600-
let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
601-
602-
bounds.insert(GenericBound::TraitBound(
603-
PolyTrait {
604-
trait_: Type::ResolvedPath {
605-
path: new_trait_path,
606-
did: *did,
607-
},
608-
generic_params: Vec::new(),
609-
},
610-
hir::TraitBoundModifier::None,
611-
));
612-
613-
// Remove any existing 'plain' bound (e.g., 'T: Iterator`) so
614-
// that we don't see a
615-
// duplicate bound like `T: Iterator + Iterator<Item=u8>`
616-
// on the docs page.
617-
bounds.remove(&GenericBound::TraitBound(
618-
PolyTrait {
619-
trait_: *trait_.clone(),
620-
generic_params: Vec::new(),
621-
},
622-
hir::TraitBoundModifier::None,
623-
));
624-
// Avoid creating any new duplicate bounds later in the outer
625-
// loop
626-
ty_to_traits
627-
.entry(*ty.clone())
628-
.or_default()
629-
.insert(*trait_.clone());
548+
let mut new_trait = *trait_.clone();
549+
550+
if self.is_fn_trait(trait_) && left_name == sym::Output {
551+
ty_to_fn
552+
.entry(*ty.clone())
553+
.and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
554+
.or_insert((None, Some(rhs)));
555+
continue;
556+
}
557+
558+
let args = &mut new_trait
559+
.segments
560+
.last_mut()
561+
.expect("segments were empty")
562+
.args;
563+
564+
match args {
565+
// Convert something like '<T as Iterator::Item> = u8'
566+
// to 'T: Iterator<Item=u8>'
567+
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
568+
bindings.push(TypeBinding {
569+
name: left_name,
570+
kind: TypeBindingKind::Equality { ty: rhs },
571+
});
572+
}
573+
GenericArgs::Parenthesized { .. } => {
574+
existing_predicates.push(WherePredicate::EqPredicate {
575+
lhs: lhs.clone(),
576+
rhs,
577+
});
578+
continue; // If something other than a Fn ends up
579+
// with parenthesis, leave it alone
630580
}
631-
_ => panic!("Unexpected trait {:?} for {:?}", trait_, item_def_id),
632581
}
582+
583+
let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
584+
585+
bounds.insert(GenericBound::TraitBound(
586+
PolyTrait { trait_: new_trait, generic_params: Vec::new() },
587+
hir::TraitBoundModifier::None,
588+
));
589+
590+
// Remove any existing 'plain' bound (e.g., 'T: Iterator`) so
591+
// that we don't see a
592+
// duplicate bound like `T: Iterator + Iterator<Item=u8>`
593+
// on the docs page.
594+
bounds.remove(&GenericBound::TraitBound(
595+
PolyTrait { trait_: *trait_.clone(), generic_params: Vec::new() },
596+
hir::TraitBoundModifier::None,
597+
));
598+
// Avoid creating any new duplicate bounds later in the outer
599+
// loop
600+
ty_to_traits.entry(*ty.clone()).or_default().insert(*trait_.clone());
633601
}
634602
_ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
635603
}
@@ -721,16 +689,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
721689
vec.sort_by_cached_key(|x| format!("{:?}", x))
722690
}
723691

724-
fn is_fn_ty(&self, ty: &Type) -> bool {
692+
fn is_fn_trait(&self, path: &Path) -> bool {
725693
let tcx = self.cx.tcx;
726-
match ty {
727-
&Type::ResolvedPath { did, .. } => {
728-
did == tcx.require_lang_item(LangItem::Fn, None)
729-
|| did == tcx.require_lang_item(LangItem::FnMut, None)
730-
|| did == tcx.require_lang_item(LangItem::FnOnce, None)
731-
}
732-
_ => false,
733-
}
694+
let did = path.res.def_id();
695+
did == tcx.require_lang_item(LangItem::Fn, None)
696+
|| did == tcx.require_lang_item(LangItem::FnMut, None)
697+
|| did == tcx.require_lang_item(LangItem::FnOnce, None)
734698
}
735699
}
736700

src/librustdoc/clean/blanket_impl.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
114114
.clean(self.cx),
115115
// FIXME(eddyb) compute both `trait_` and `for_` from
116116
// the post-inference `trait_ref`, as it's more accurate.
117-
trait_: Some(
118-
trait_ref.clean(self.cx).get_trait_type().unwrap().expect_path(),
119-
),
117+
trait_: Some(trait_ref.clean(self.cx).get_trait_path().unwrap()),
120118
for_: ty.clean(self.cx),
121119
items: self
122120
.cx

src/librustdoc/clean/inline.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,20 @@ crate fn build_impl(
455455
}
456456

457457
// Return if the trait itself or any types of the generic parameters are doc(hidden).
458-
let mut stack: Vec<&Type> = trait_.iter().collect();
459-
stack.push(&for_);
458+
let mut stack: Vec<&Type> = vec![&for_];
459+
460+
if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) {
461+
if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
462+
return;
463+
}
464+
}
465+
if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
466+
stack.extend(generics);
467+
}
468+
460469
while let Some(ty) = stack.pop() {
461470
if let Some(did) = ty.def_id() {
462-
if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
471+
if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) {
463472
return;
464473
}
465474
}
@@ -468,8 +477,8 @@ crate fn build_impl(
468477
}
469478
}
470479

471-
if let Some(trait_did) = trait_.def_id() {
472-
record_extern_trait(cx, trait_did);
480+
if let Some(did) = trait_.as_ref().map(|t| t.res.def_id()) {
481+
record_extern_trait(cx, did);
473482
}
474483

475484
let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
@@ -483,7 +492,7 @@ crate fn build_impl(
483492
span: clean::types::rustc_span(did, cx.tcx),
484493
unsafety: hir::Unsafety::Normal,
485494
generics,
486-
trait_: trait_.map(|t| t.expect_path()),
495+
trait_,
487496
for_,
488497
items: trait_items,
489498
negative_polarity: polarity.clean(cx),
@@ -620,30 +629,23 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
620629
ref mut bounds,
621630
..
622631
} if *s == kw::SelfUpper => {
623-
bounds.retain(|bound| match *bound {
624-
clean::GenericBound::TraitBound(
625-
clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. },
626-
_,
627-
) => did != trait_did,
632+
bounds.retain(|bound| match bound {
633+
clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
634+
trait_.res.def_id() != trait_did
635+
}
628636
_ => true,
629637
});
630638
}
631639
_ => {}
632640
}
633641
}
634642

635-
g.where_predicates.retain(|pred| match *pred {
643+
g.where_predicates.retain(|pred| match pred {
636644
clean::WherePredicate::BoundPredicate {
637-
ty:
638-
clean::QPath {
639-
self_type: box clean::Generic(ref s),
640-
trait_: box clean::ResolvedPath { did, .. },
641-
name: ref _name,
642-
..
643-
},
644-
ref bounds,
645+
ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. },
646+
bounds,
645647
..
646-
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
648+
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.res.def_id() == trait_did),
647649
_ => true,
648650
});
649651
g

0 commit comments

Comments
 (0)