Skip to content

Commit 5dbaafd

Browse files
committedApr 2, 2024·
Auto merge of #123340 - fmease:rustdoc-simplify-auto-trait-impl-synth, r=GuillaumeGomez
rustdoc: heavily simplify the synthesis of auto trait impls `gd --numstat HEAD~2 HEAD src/librustdoc/clean/auto_trait.rs` **+315 -705** 🟩🟥🟥🟥⬛ --- As outlined in issue #113015, there are currently 3[^1] large separate routines that “clean” `rustc_middle::ty` data types related to generics & predicates to rustdoc data types. Every single one has their own kinds of bugs. While I've patched a lot of bugs in each of the routines in the past, it's about time to unify them. This PR is only the first in a series. It completely **yanks** the custom “bounds cleaning” of mod `auto_trait` and reuses the routines found in mod `simplify`. As alluded to, `simplify` is also flawed but it's still more complete than `auto_trait`'s routines. [See also my review comment over at `tests/rustdoc/synthetic_auto/bounds.rs`](#123340 (comment)). This is preparatory work for rewriting “bounds cleaning” from scratch in follow-up PRs in order to finally [fix] #113015. Apart from that, I've eliminated all potential sources of *instability* in the rendered output. See also #119597. I'm pretty sure this fixes #119597. This PR does not attempt to fix [any other issues related to synthetic auto trait impls](https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AA-synthetic-impls%20label%3AA-auto-traits). However, it's definitely meant to be a *stepping stone* by making `auto_trait` more contributor-friendly. --- * Replace `FxHash{Map,Set}` with `FxIndex{Map,Set}` to guarantee a stable iteration order * Or as a perf opt, `UnordSet` (a thin wrapper around `FxHashSet`) in cases where we never iterate over the set. * Yes, we do make use of `swap_remove` but that shouldn't matter since all the callers are deterministic. It does make the output less “predictable” but it's still better than before. Ofc, I rely on `rustc_infer` being deterministic. I hope that holds. * Utilizing `clean::simplify` over the custom “bounds cleaning” routines wipes out the last reference to `collect_referenced_late_bound_regions` in rustdoc (`simplify` uses `bound_vars`) which was a source of instability / unpredictability (cc #116388) * Remove the types `RegionTarget` and `RegionDeps` from `librustdoc`. They were duplicates of the identical types found in `rustc`. Just import them from `rustc`. For some reason, they were duplicated when splitting `auto_trait` in two in #49711. * Get rid of the useless “type namespace” `AutoTraitFinder` in `librustdoc` * The struct only held a `DocContext`, it was over-engineered * Turn the associated functions into free ones * Eliminates rightward drift; increases legibility * `rustc` also contains a useless `AutoTraitFinder` struct but I plan on removing that in a follow-up PR * Rename a bunch of methods to be way more descriptive * Eliminate `use super::*;` * Lead to `clean/mod.rs` accumulating a lot of unnecessary imports * Made `auto_traits` less modular * Eliminate a custom `TypeFolder`: We can just use the rustc helper `fold_regions` which does that for us I plan on adding extensive documentation to `librustdoc`'s `auto_trait` in follow-up PRs. I don't want to do that in this PR because further refactoring & bug fix PRs may alter the overall structure of `librustdoc`'s & `rustc`'s `auto_trait` modules to a great degree. I'm slowly digging into the dark details of `rustc`'s `auto_trait` module again and once I have the full picture I will be able to provide proper docs. --- While this PR does indeed touch `rustc`'s `auto_trait` — mostly tiny refactorings — I argue this PR doesn't need any compiler reviewers next to rustdoc ones since that module falls under the purview of rustdoc — it used to be part of `librustdoc` after all (#49711). Sorry for not having split this into more commits. If you'd like me to I can try to split it into more atomic commits retroactively. However, I don't know if that would actually make reviewing easier. I think the best way to review this might just be to place the master version of `auto_trait` on the left of your screen and the patched one on the right, not joking. r? `@GuillaumeGomez` [^1]: Or even 4 depending on the way you're counting.
2 parents 0e682e9 + 069e7f2 commit 5dbaafd

File tree

11 files changed

+452
-849
lines changed

11 files changed

+452
-849
lines changed
 

‎compiler/rustc_trait_selection/src/traits/auto_trait.rs

+22-40
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use super::*;
66
use crate::errors::UnableToConstructConstantValue;
77
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
88
use crate::traits::project::ProjectAndUnifyResult;
9+
10+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
11+
use rustc_data_structures::unord::UnordSet;
912
use rustc_infer::infer::DefineOpaqueTypes;
1013
use rustc_middle::mir::interpret::ErrorHandled;
1114
use rustc_middle::ty::{Region, RegionVid};
1215

13-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
14-
15-
use std::collections::hash_map::Entry;
1616
use std::collections::VecDeque;
1717
use std::iter;
1818

@@ -25,8 +25,8 @@ pub enum RegionTarget<'tcx> {
2525

2626
#[derive(Default, Debug, Clone)]
2727
pub struct RegionDeps<'tcx> {
28-
larger: FxIndexSet<RegionTarget<'tcx>>,
29-
smaller: FxIndexSet<RegionTarget<'tcx>>,
28+
pub larger: FxIndexSet<RegionTarget<'tcx>>,
29+
pub smaller: FxIndexSet<RegionTarget<'tcx>>,
3030
}
3131

3232
pub enum AutoTraitResult<A> {
@@ -35,17 +35,10 @@ pub enum AutoTraitResult<A> {
3535
NegativeImpl,
3636
}
3737

38-
#[allow(dead_code)]
39-
impl<A> AutoTraitResult<A> {
40-
fn is_auto(&self) -> bool {
41-
matches!(self, AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl)
42-
}
43-
}
44-
4538
pub struct AutoTraitInfo<'cx> {
4639
pub full_user_env: ty::ParamEnv<'cx>,
4740
pub region_data: RegionConstraintData<'cx>,
48-
pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
41+
pub vid_to_region: FxIndexMap<ty::RegionVid, ty::Region<'cx>>,
4942
}
5043

5144
pub struct AutoTraitFinder<'tcx> {
@@ -88,19 +81,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
8881

8982
let infcx = tcx.infer_ctxt().build();
9083
let mut selcx = SelectionContext::new(&infcx);
91-
for polarity in [true, false] {
84+
for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] {
9285
let result = selcx.select(&Obligation::new(
9386
tcx,
9487
ObligationCause::dummy(),
9588
orig_env,
96-
ty::TraitPredicate {
97-
trait_ref,
98-
polarity: if polarity {
99-
ty::PredicatePolarity::Positive
100-
} else {
101-
ty::PredicatePolarity::Negative
102-
},
103-
},
89+
ty::TraitPredicate { trait_ref, polarity },
10490
));
10591
if let Ok(Some(ImplSource::UserDefined(_))) = result {
10692
debug!(
@@ -114,7 +100,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
114100
}
115101

116102
let infcx = tcx.infer_ctxt().build();
117-
let mut fresh_preds = FxHashSet::default();
103+
let mut fresh_preds = FxIndexSet::default();
118104

119105
// Due to the way projections are handled by SelectionContext, we need to run
120106
// evaluate_predicates twice: once on the original param env, and once on the result of
@@ -239,7 +225,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
239225
ty: Ty<'tcx>,
240226
param_env: ty::ParamEnv<'tcx>,
241227
user_env: ty::ParamEnv<'tcx>,
242-
fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
228+
fresh_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
243229
) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> {
244230
let tcx = infcx.tcx;
245231

@@ -252,7 +238,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
252238

253239
let mut select = SelectionContext::new(infcx);
254240

255-
let mut already_visited = FxHashSet::default();
241+
let mut already_visited = UnordSet::new();
256242
let mut predicates = VecDeque::new();
257243
predicates.push_back(ty::Binder::dummy(ty::TraitPredicate {
258244
trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]),
@@ -473,9 +459,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
473459
fn map_vid_to_region<'cx>(
474460
&self,
475461
regions: &RegionConstraintData<'cx>,
476-
) -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
477-
let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default();
478-
let mut finished_map = FxHashMap::default();
462+
) -> FxIndexMap<ty::RegionVid, ty::Region<'cx>> {
463+
let mut vid_map = FxIndexMap::<RegionTarget<'cx>, RegionDeps<'cx>>::default();
464+
let mut finished_map = FxIndexMap::default();
479465

480466
for (constraint, _) in &regions.constraints {
481467
match constraint {
@@ -513,25 +499,22 @@ impl<'tcx> AutoTraitFinder<'tcx> {
513499
}
514500

515501
while !vid_map.is_empty() {
516-
#[allow(rustc::potential_query_instability)]
517-
let target = *vid_map.keys().next().expect("Keys somehow empty");
518-
let deps = vid_map.remove(&target).expect("Entry somehow missing");
502+
let target = *vid_map.keys().next().unwrap();
503+
let deps = vid_map.swap_remove(&target).unwrap();
519504

520505
for smaller in deps.smaller.iter() {
521506
for larger in deps.larger.iter() {
522507
match (smaller, larger) {
523508
(&RegionTarget::Region(_), &RegionTarget::Region(_)) => {
524-
if let Entry::Occupied(v) = vid_map.entry(*smaller) {
509+
if let IndexEntry::Occupied(v) = vid_map.entry(*smaller) {
525510
let smaller_deps = v.into_mut();
526511
smaller_deps.larger.insert(*larger);
527-
// FIXME(#120456) - is `swap_remove` correct?
528512
smaller_deps.larger.swap_remove(&target);
529513
}
530514

531-
if let Entry::Occupied(v) = vid_map.entry(*larger) {
515+
if let IndexEntry::Occupied(v) = vid_map.entry(*larger) {
532516
let larger_deps = v.into_mut();
533517
larger_deps.smaller.insert(*smaller);
534-
// FIXME(#120456) - is `swap_remove` correct?
535518
larger_deps.smaller.swap_remove(&target);
536519
}
537520
}
@@ -542,24 +525,23 @@ impl<'tcx> AutoTraitFinder<'tcx> {
542525
// Do nothing; we don't care about regions that are smaller than vids.
543526
}
544527
(&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
545-
if let Entry::Occupied(v) = vid_map.entry(*smaller) {
528+
if let IndexEntry::Occupied(v) = vid_map.entry(*smaller) {
546529
let smaller_deps = v.into_mut();
547530
smaller_deps.larger.insert(*larger);
548-
// FIXME(#120456) - is `swap_remove` correct?
549531
smaller_deps.larger.swap_remove(&target);
550532
}
551533

552-
if let Entry::Occupied(v) = vid_map.entry(*larger) {
534+
if let IndexEntry::Occupied(v) = vid_map.entry(*larger) {
553535
let larger_deps = v.into_mut();
554536
larger_deps.smaller.insert(*smaller);
555-
// FIXME(#120456) - is `swap_remove` correct?
556537
larger_deps.smaller.swap_remove(&target);
557538
}
558539
}
559540
}
560541
}
561542
}
562543
}
544+
563545
finished_map
564546
}
565547

@@ -588,7 +570,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
588570
ty: Ty<'_>,
589571
nested: impl Iterator<Item = PredicateObligation<'tcx>>,
590572
computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
591-
fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
573+
fresh_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
592574
predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
593575
selcx: &mut SelectionContext<'_, 'tcx>,
594576
) -> bool {

‎src/librustdoc/clean/auto_trait.rs

+319-705
Large diffs are not rendered by default.

‎src/librustdoc/clean/mod.rs

+35-74
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
2121
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
2222
use rustc_hir::PredicateOrigin;
2323
use rustc_hir_analysis::lower_ty;
24-
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
2524
use rustc_middle::metadata::Reexport;
2625
use rustc_middle::middle::resolve_bound_vars as rbv;
27-
use rustc_middle::ty::fold::TypeFolder;
2826
use rustc_middle::ty::GenericArgsRef;
2927
use rustc_middle::ty::TypeVisitableExt;
3028
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt};
@@ -35,9 +33,7 @@ use rustc_span::{self, ExpnKind};
3533
use rustc_trait_selection::traits::wf::object_region_bounds;
3634

3735
use std::borrow::Cow;
38-
use std::collections::hash_map::Entry;
3936
use std::collections::BTreeMap;
40-
use std::hash::Hash;
4137
use std::mem;
4238
use thin_vec::ThinVec;
4339

@@ -502,14 +498,17 @@ fn projection_to_path_segment<'tcx>(
502498

503499
fn clean_generic_param_def<'tcx>(
504500
def: &ty::GenericParamDef,
501+
defaults: ParamDefaults,
505502
cx: &mut DocContext<'tcx>,
506503
) -> GenericParamDef {
507504
let (name, kind) = match def.kind {
508505
ty::GenericParamDefKind::Lifetime => {
509506
(def.name, GenericParamDefKind::Lifetime { outlives: ThinVec::new() })
510507
}
511508
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
512-
let default = if has_default {
509+
let default = if let ParamDefaults::Yes = defaults
510+
&& has_default
511+
{
513512
Some(clean_middle_ty(
514513
ty::Binder::dummy(cx.tcx.type_of(def.def_id).instantiate_identity()),
515514
cx,
@@ -542,11 +541,14 @@ fn clean_generic_param_def<'tcx>(
542541
Some(def.def_id),
543542
None,
544543
)),
545-
default: match has_default {
546-
true => Some(Box::new(
544+
default: if let ParamDefaults::Yes = defaults
545+
&& has_default
546+
{
547+
Some(Box::new(
547548
cx.tcx.const_param_default(def.def_id).instantiate_identity().to_string(),
548-
)),
549-
false => None,
549+
))
550+
} else {
551+
None
550552
},
551553
is_host_effect,
552554
},
@@ -556,6 +558,12 @@ fn clean_generic_param_def<'tcx>(
556558
GenericParamDef { name, def_id: def.def_id, kind }
557559
}
558560

561+
/// Whether to clean generic parameter defaults or not.
562+
enum ParamDefaults {
563+
Yes,
564+
No,
565+
}
566+
559567
fn clean_generic_param<'tcx>(
560568
cx: &mut DocContext<'tcx>,
561569
generics: Option<&hir::Generics<'tcx>>,
@@ -759,34 +767,30 @@ fn clean_ty_generics<'tcx>(
759767
gens: &ty::Generics,
760768
preds: ty::GenericPredicates<'tcx>,
761769
) -> Generics {
762-
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
763-
// since `Clean for ty::Predicate` would consume them.
770+
// Don't populate `cx.impl_trait_bounds` before cleaning where clauses,
771+
// since `clean_predicate` would consume them.
764772
let mut impl_trait = BTreeMap::<u32, Vec<GenericBound>>::default();
765773

766-
// Bounds in the type_params and lifetimes fields are repeated in the
767-
// predicates field (see rustc_hir_analysis::collect::ty_generics), so remove
768-
// them.
769-
let stripped_params = gens
774+
let params: ThinVec<_> = gens
770775
.params
771776
.iter()
772-
.filter_map(|param| match param.kind {
773-
ty::GenericParamDefKind::Lifetime if param.is_anonymous_lifetime() => None,
774-
ty::GenericParamDefKind::Lifetime => Some(clean_generic_param_def(param, cx)),
777+
.filter(|param| match param.kind {
778+
ty::GenericParamDefKind::Lifetime => !param.is_anonymous_lifetime(),
775779
ty::GenericParamDefKind::Type { synthetic, .. } => {
776780
if param.name == kw::SelfUpper {
777-
assert_eq!(param.index, 0);
778-
return None;
781+
debug_assert_eq!(param.index, 0);
782+
return false;
779783
}
780784
if synthetic {
781785
impl_trait.insert(param.index, vec![]);
782-
return None;
786+
return false;
783787
}
784-
Some(clean_generic_param_def(param, cx))
788+
true
785789
}
786-
ty::GenericParamDefKind::Const { is_host_effect: true, .. } => None,
787-
ty::GenericParamDefKind::Const { .. } => Some(clean_generic_param_def(param, cx)),
790+
ty::GenericParamDefKind::Const { is_host_effect, .. } => !is_host_effect,
788791
})
789-
.collect::<ThinVec<GenericParamDef>>();
792+
.map(|param| clean_generic_param_def(param, ParamDefaults::Yes, cx))
793+
.collect();
790794

791795
// param index -> [(trait DefId, associated type name & generics, term)]
792796
let mut impl_trait_proj =
@@ -882,56 +886,13 @@ fn clean_ty_generics<'tcx>(
882886

883887
// Now that `cx.impl_trait_bounds` is populated, we can process
884888
// remaining predicates which could contain `impl Trait`.
885-
let mut where_predicates =
886-
where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>();
887-
888-
// In the surface language, all type parameters except `Self` have an
889-
// implicit `Sized` bound unless removed with `?Sized`.
890-
// However, in the list of where-predicates below, `Sized` appears like a
891-
// normal bound: It's either present (the type is sized) or
892-
// absent (the type might be unsized) but never *maybe* (i.e. `?Sized`).
893-
//
894-
// This is unsuitable for rendering.
895-
// Thus, as a first step remove all `Sized` bounds that should be implicit.
896-
//
897-
// Note that associated types also have an implicit `Sized` bound but we
898-
// don't actually know the set of associated types right here so that's
899-
// handled when cleaning associated types.
900-
let mut sized_params = FxHashSet::default();
901-
where_predicates.retain(|pred| {
902-
if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred
903-
&& *g != kw::SelfUpper
904-
&& bounds.iter().any(|b| b.is_sized_bound(cx))
905-
{
906-
sized_params.insert(*g);
907-
false
908-
} else {
909-
true
910-
}
911-
});
912-
913-
// As a final step, go through the type parameters again and insert a
914-
// `?Sized` bound for each one we didn't find to be `Sized`.
915-
for tp in &stripped_params {
916-
if let types::GenericParamDefKind::Type { .. } = tp.kind
917-
&& !sized_params.contains(&tp.name)
918-
{
919-
where_predicates.push(WherePredicate::BoundPredicate {
920-
ty: Type::Generic(tp.name),
921-
bounds: vec![GenericBound::maybe_sized(cx)],
922-
bound_params: Vec::new(),
923-
})
924-
}
925-
}
926-
927-
// It would be nice to collect all of the bounds on a type and recombine
928-
// them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
929-
// and instead see `where T: Foo + Bar + Sized + 'a`
889+
let where_predicates =
890+
where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect();
930891

931-
Generics {
932-
params: stripped_params,
933-
where_predicates: simplify::where_clauses(cx, where_predicates),
934-
}
892+
let mut generics = Generics { params, where_predicates };
893+
simplify::sized_bounds(cx, &mut generics);
894+
generics.where_predicates = simplify::where_clauses(cx, generics.where_predicates);
895+
generics
935896
}
936897

937898
fn clean_ty_alias_inner_type<'tcx>(

‎src/librustdoc/clean/simplify.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//! bounds by special casing scenarios such as these. Fun!
1313
1414
use rustc_data_structures::fx::FxIndexMap;
15+
use rustc_data_structures::unord::UnordSet;
1516
use rustc_hir::def_id::DefId;
1617
use rustc_middle::ty;
1718
use thin_vec::ThinVec;
@@ -21,7 +22,7 @@ use crate::clean::GenericArgs as PP;
2122
use crate::clean::WherePredicate as WP;
2223
use crate::core::DocContext;
2324

24-
pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP> {
25+
pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec<WP>) -> ThinVec<WP> {
2526
// First, partition the where clause into its separate components.
2627
//
2728
// We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to
@@ -128,6 +129,48 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId)
128129
.any(|did| trait_is_same_or_supertrait(cx, did, trait_))
129130
}
130131

132+
pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generics) {
133+
let mut sized_params = UnordSet::new();
134+
135+
// In the surface language, all type parameters except `Self` have an
136+
// implicit `Sized` bound unless removed with `?Sized`.
137+
// However, in the list of where-predicates below, `Sized` appears like a
138+
// normal bound: It's either present (the type is sized) or
139+
// absent (the type might be unsized) but never *maybe* (i.e. `?Sized`).
140+
//
141+
// This is unsuitable for rendering.
142+
// Thus, as a first step remove all `Sized` bounds that should be implicit.
143+
//
144+
// Note that associated types also have an implicit `Sized` bound but we
145+
// don't actually know the set of associated types right here so that
146+
// should be handled when cleaning associated types.
147+
generics.where_predicates.retain(|pred| {
148+
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred
149+
&& *param != rustc_span::symbol::kw::SelfUpper
150+
&& bounds.iter().any(|b| b.is_sized_bound(cx))
151+
{
152+
sized_params.insert(*param);
153+
false
154+
} else {
155+
true
156+
}
157+
});
158+
159+
// As a final step, go through the type parameters again and insert a
160+
// `?Sized` bound for each one we didn't find to be `Sized`.
161+
for param in &generics.params {
162+
if let clean::GenericParamDefKind::Type { .. } = param.kind
163+
&& !sized_params.contains(&param.name)
164+
{
165+
generics.where_predicates.push(WP::BoundPredicate {
166+
ty: clean::Type::Generic(param.name),
167+
bounds: vec![clean::GenericBound::maybe_sized(cx)],
168+
bound_params: Vec::new(),
169+
})
170+
}
171+
}
172+
}
173+
131174
/// Move bounds that are (likely) directly attached to generic parameters from the where-clause to
132175
/// the respective parameter.
133176
///

‎src/librustdoc/clean/types.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1277,13 +1277,6 @@ impl GenericBound {
12771277
false
12781278
}
12791279

1280-
pub(crate) fn get_poly_trait(&self) -> Option<PolyTrait> {
1281-
if let GenericBound::TraitBound(ref p, _) = *self {
1282-
return Some(p.clone());
1283-
}
1284-
None
1285-
}
1286-
12871280
pub(crate) fn get_trait_path(&self) -> Option<Path> {
12881281
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
12891282
Some(trait_.clone())

‎src/librustdoc/clean/utils.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::clean::auto_trait::AutoTraitFinder;
1+
use crate::clean::auto_trait::synthesize_auto_trait_impls;
22
use crate::clean::blanket_impl::BlanketImplFinder;
33
use crate::clean::render_macro_matchers::render_macro_matcher;
44
use crate::clean::{
@@ -251,15 +251,6 @@ pub(super) fn clean_middle_path<'tcx>(
251251
}
252252
}
253253

254-
/// Remove the generic arguments from a path.
255-
pub(crate) fn strip_path_generics(mut path: Path) -> Path {
256-
for ps in path.segments.iter_mut() {
257-
ps.args = GenericArgs::AngleBracketed { args: Default::default(), bindings: ThinVec::new() }
258-
}
259-
260-
path
261-
}
262-
263254
pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
264255
let segments = match *p {
265256
hir::QPath::Resolved(_, path) => &path.segments,
@@ -486,15 +477,16 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
486477
}
487478
}
488479

480+
// FIXME(fmease): Update the `get_*` terminology to the `synthesize_` one.
489481
pub(crate) fn get_auto_trait_and_blanket_impls(
490482
cx: &mut DocContext<'_>,
491483
item_def_id: DefId,
492484
) -> impl Iterator<Item = Item> {
493485
let auto_impls = cx
494486
.sess()
495487
.prof
496-
.generic_activity("get_auto_trait_impls")
497-
.run(|| AutoTraitFinder::new(cx).get_auto_trait_impls(item_def_id));
488+
.generic_activity("synthesize_auto_trait_impls")
489+
.run(|| synthesize_auto_trait_impls(cx, item_def_id));
498490
let blanket_impls = cx
499491
.sess()
500492
.prof
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
pub struct Outer<T>(Inner<T>);
2+
pub struct Inner<T>(T);
3+
4+
// @has bounds/struct.Outer.html
5+
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
6+
// "impl<T> Unpin for Outer<T>where \
7+
// T: for<'any> Trait<A = (), B<'any> = (), X = ()>,"
8+
9+
impl<T> std::marker::Unpin for Inner<T>
10+
where
11+
T: for<'any> Trait<A = (), B<'any> = (), X = ()>,
12+
{}
13+
14+
pub trait Trait: SuperTrait {
15+
type A;
16+
type B<'a>;
17+
}
18+
19+
pub trait SuperTrait {
20+
type X;
21+
}

‎tests/rustdoc/synthetic_auto/complex.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ mod foo {
2121

2222
// @has complex/struct.NotOuter.html
2323
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
24-
// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \
25-
// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
24+
// "impl<'a, T, K> Send for Outer<'a, T, K>where 'a: 'static, T: MyTrait<'a>, \
25+
// K: for<'b> Fn((&'b bool, &'a u8)) -> &'b i8 + ?Sized, <T as MyTrait<'a>>::MyItem: Copy,"
2626

2727
pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};
2828

‎tests/rustdoc/synthetic_auto/lifetimes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ where
1010

1111
// @has lifetimes/struct.Foo.html
1212
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
13-
// "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
13+
// "impl<'c, K> Send for Foo<'c, K>where 'c: 'static, K: for<'b> Fn(&'b bool) -> &'c u8,"
1414
//
1515
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
1616
// "impl<'c, K> Sync for Foo<'c, K>where K: Sync"

‎tests/rustdoc/synthetic_auto/no-redundancy.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// FIXME(fmease, #119216): Reenable this test!
2-
//@ ignore-test
3-
41
pub struct Inner<T> {
52
field: T,
63
}
@@ -13,7 +10,7 @@ where
1310

1411
// @has no_redundancy/struct.Outer.html
1512
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
16-
// "impl<T> Send for Outer<T>where T: Send + Copy"
13+
// "impl<T> Send for Outer<T>where T: Copy + Send"
1714
pub struct Outer<T> {
1815
inner_field: Inner<T>,
1916
}

‎tests/rustdoc/synthetic_auto/project.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ where
2424

2525
// @has project/struct.Foo.html
2626
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
27-
// "impl<'c, K> Send for Foo<'c, K>where K: MyTrait<MyItem = bool>, 'c: 'static"
27+
// "impl<'c, K> Send for Foo<'c, K>where 'c: 'static, K: MyTrait<MyItem = bool>,"
2828
//
2929
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
30-
// "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
31-
// 'c: 'static,"
30+
// "impl<'c, K> Sync for Foo<'c, K>where 'c: 'static, K: MyTrait, \
31+
// <K as MyTrait>::MyItem: OtherTrait,"
3232
pub struct Foo<'c, K: 'c> {
3333
inner_field: Inner<'c, K>,
3434
}

0 commit comments

Comments
 (0)
Please sign in to comment.