From 64ee0f74eb4d724e87601fea4bd6b18377289fa2 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 15 Jun 2023 21:14:40 +0200 Subject: [PATCH 1/2] remove unused field since DrainFilter no longer continues draining when it's dropped the panic tracking is no longer needed. --- library/alloc/src/vec/extract_if.rs | 8 -------- library/alloc/src/vec/mod.rs | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index e8e6bd56d21ba..118cfdb36b9c2 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -37,12 +37,6 @@ pub struct ExtractIf< pub(super) old_len: usize, /// The filter test predicate. pub(super) pred: F, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `ExtractIf`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - pub(super) panic_flag: bool, } impl ExtractIf<'_, T, F, A> @@ -69,9 +63,7 @@ where while self.idx < self.old_len { let i = self.idx; let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - self.panic_flag = true; let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; // Update the index *after* the predicate is called. If the index // is updated prior and the predicate panics, the element at this // index would be leaked. diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 289bbc7d2effd..259c659c7ebb0 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2948,7 +2948,7 @@ impl Vec { self.set_len(0); } - ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } + ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter } } } From c643bedf7c90940005da021ba80b6c4e6dcbdaa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 22 Jun 2023 10:42:02 +0200 Subject: [PATCH 2/2] rustdoc: render gen params & where-clauses of cross-crate assoc tys in impl blocks --- src/librustdoc/clean/mod.rs | 88 ++++++++++--------- .../inline_cross/assoc_item_trait_bounds.rs | 12 +++ .../auxiliary/assoc_item_trait_bounds.rs | 17 ++++ 3 files changed, 74 insertions(+), 43 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f86c32158e0b3..3dd3a6a8394f3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1360,21 +1360,53 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } + let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; if let ty::TraitContainer = assoc_item.container { let bounds = tcx .explicit_item_bounds(assoc_item.def_id) .subst_identity_iter_copied() .map(|(c, s)| (c.as_predicate(), s)); - let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; - let predicates = - tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); - let mut generics = clean_ty_generics( - cx, - tcx.generics_of(assoc_item.def_id), - ty::GenericPredicates { parent: None, predicates }, - ); - // Filter out the bounds that are (likely?) directly attached to the associated type, - // as opposed to being located in the where clause. + predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); + } + let mut generics = clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + ty::GenericPredicates { parent: None, predicates }, + ); + // Move bounds that are (likely) directly attached to the parameters of the + // (generic) associated type from the where clause to the respective parameter. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. + let mut where_predicates = ThinVec::new(); + for mut pred in generics.where_predicates { + if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.append(bounds); + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.extend(bounds.drain(..).map(|bound| match bound { + GenericBound::Outlives(lifetime) => lifetime, + _ => unreachable!(), + })); + } else { + where_predicates.push(pred); + } + } + generics.where_predicates = where_predicates; + + if let ty::TraitContainer = assoc_item.container { + // Move bounds that are (likely) directly attached to the associated type + // from the where-clause to the associated type. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. let mut bounds: Vec = Vec::new(); generics.where_predicates.retain_mut(|pred| match *pred { WherePredicate::BoundPredicate { @@ -1431,33 +1463,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } None => bounds.push(GenericBound::maybe_sized(cx)), } - // Move bounds that are (likely) directly attached to the parameters of the - // (generic) associated type from the where clause to the respective parameter. - // There is no guarantee that this is what the user actually wrote but we have - // no way of knowing. - let mut where_predicates = ThinVec::new(); - for mut pred in generics.where_predicates { - if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) - { - param_bounds.append(bounds); - } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { - param_bounds.extend(bounds.drain(..).map(|bound| match bound { - GenericBound::Outlives(lifetime) => lifetime, - _ => unreachable!(), - })); - } else { - where_predicates.push(pred); - } - } - generics.where_predicates = where_predicates; if tcx.defaultness(assoc_item.def_id).has_value() { AssocTypeItem( @@ -1469,7 +1474,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( None, ), generics, - // FIXME: should we obtain the Type from HIR and pass it on here? item_type: None, }), bounds, @@ -1478,7 +1482,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( TyAssocTypeItem(generics, bounds) } } else { - // FIXME: when could this happen? Associated items in inherent impls? AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( @@ -1487,12 +1490,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( Some(assoc_item.def_id), None, ), - generics: Generics { - params: ThinVec::new(), - where_predicates: ThinVec::new(), - }, + generics, item_type: None, }), + // Associated types inside trait or inherent impls are not allowed to have + // item bounds. Thus we don't attempt to move any bounds there. Vec::new(), ) } diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs index db2491b87b4d6..74ceb697af693 100644 --- a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs +++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -42,3 +42,15 @@ pub use aux::Main; // @has main/trait.Aid.html // @has - '//*[@id="associatedtype.Result"]' "type Result<'inter: 'src>" pub use aux::Aid; + +// Below, ensure that we correctly display generic parameters and where-clauses on +// associated types inside trait *impls*. More particularly, check that we don't render +// any bounds (here `Self::Alias: ...`) as item bounds unlike all the trait test cases above. + +// @has main/struct.Implementor.html +// @has - '//*[@id="associatedtype.Alias"]' \ +// "type Alias = T \ +// where \ +// String: From, \ +// ::Alias: From<::Alias>" +pub use aux::Implementor; diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs index 6644c8e414789..551e97a2fa9ac 100644 --- a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs +++ b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs @@ -44,3 +44,20 @@ pub trait Helper { pub trait Aid<'src> { type Result<'inter: 'src>; } + +pub trait Implementee { + type Alias + where + String: From; +} + +pub struct Implementor; + +impl Implementee for Implementor { + type Alias = T + where + String: From, + // We will check that this bound doesn't get turned into an item bound since + // associated types in impls are not allowed to have any. + Self::Alias: From>; +}