diff options
| author | bors <bors@rust-lang.org> | 2023-06-12 10:08:45 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-06-12 10:08:45 +0000 |
| commit | cb882fa998571e8a7ec1c06bb5d9dd9bc3423629 (patch) | |
| tree | 134c65ef9c18965844b6e367357b41ad572f5d1f /src | |
| parent | fd0a3313f7a64cb16533030e49a271db449368c3 (diff) | |
| parent | b93ca0146af3a8adeee286d3d4dbd561e534a8bf (diff) | |
| download | rust-cb882fa998571e8a7ec1c06bb5d9dd9bc3423629.tar.gz rust-cb882fa998571e8a7ec1c06bb5d9dd9bc3423629.zip | |
Auto merge of #112543 - GuillaumeGomez:revert-112429, r=lcnr
[rustdoc] Fix infinite loop when retrieving impls for type alias Fixes #112515. Reverts #112429. r? `@lcnr`
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustdoc/html/render/mod.rs | 90 | ||||
| -rw-r--r-- | src/librustdoc/html/render/print_item.rs | 48 |
2 files changed, 28 insertions, 110 deletions
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index baffee0964d..f205ff15ec3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -53,15 +53,12 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::Mutability; -use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::middle::stability; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_span::{ symbol::{sym, Symbol}, BytePos, FileName, RealFileName, }; -use rustc_trait_selection::traits::ObligationCtxt; use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Serialize, Serializer}; @@ -1115,47 +1112,15 @@ fn render_assoc_items<'a, 'cx: 'a>( containing_item: &'a clean::Item, it: DefId, what: AssocItemRender<'a>, - aliased_type: Option<DefId>, ) -> impl fmt::Display + 'a + Captures<'cx> { let mut derefs = DefIdSet::default(); derefs.insert(it); display_fn(move |f| { - render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs, aliased_type); + render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs); Ok(()) }) } -/// Check whether `impl_def_id` may apply to *some instantiation* of `item_def_id`. -fn is_valid_impl_for(tcx: TyCtxt<'_>, item_def_id: DefId, impl_def_id: DefId) -> bool { - let infcx = tcx.infer_ctxt().intercrate(true).build(); - let ocx = ObligationCtxt::new(&infcx); - let param_env = ParamEnv::empty(); - - let alias_substs = infcx.fresh_substs_for_item(rustc_span::DUMMY_SP, item_def_id); - let alias_ty = tcx.type_of(item_def_id).subst(tcx, alias_substs); - let alias_bounds = tcx.predicates_of(item_def_id).instantiate(tcx, alias_substs); - - let impl_substs = infcx.fresh_substs_for_item(rustc_span::DUMMY_SP, impl_def_id); - let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs); - let impl_bounds = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs); - - if ocx.eq(&ObligationCause::dummy(), param_env, impl_self_ty, alias_ty).is_err() { - return false; - } - ocx.register_obligations( - alias_bounds - .iter() - .chain(impl_bounds) - .map(|(p, _)| Obligation::new(tcx, ObligationCause::dummy(), param_env, p)), - ); - - let errors = ocx.select_where_possible(); - errors.is_empty() -} - -// If `aliased_type` is `Some`, it means `it` is a type alias and `aliased_type` is the "actual" -// type aliased behind `it`. It is used to check whether or not the implementation of the aliased -// type can be displayed on the alias doc page. fn render_assoc_items_inner( mut w: &mut dyn fmt::Write, cx: &mut Context<'_>, @@ -1163,28 +1128,12 @@ fn render_assoc_items_inner( it: DefId, what: AssocItemRender<'_>, derefs: &mut DefIdSet, - aliased_type: Option<DefId>, ) { info!("Documenting associated items of {:?}", containing_item.name); let shared = Rc::clone(&cx.shared); let cache = &shared.cache; - let empty = Vec::new(); - let v = match cache.impls.get(&it) { - Some(v) => v, - None => &empty, - }; - let v2 = match aliased_type { - Some(aliased_type) => cache.impls.get(&aliased_type).unwrap_or(&empty), - None => &empty, - }; - if v.is_empty() && v2.is_empty() { - return; - } - let mut saw_impls = FxHashSet::default(); - let (non_trait, traits): (Vec<_>, _) = - v.iter().chain(v2).partition(|i| i.inner_impl().trait_.is_none()); - let tcx = cx.tcx(); - let is_alias = aliased_type.is_some(); + let Some(v) = cache.impls.get(&it) else { return }; + let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { let mut tmp_buf = Buffer::html(); let (render_mode, id, class_html) = match what { @@ -1216,12 +1165,6 @@ fn render_assoc_items_inner( }; let mut impls_buf = Buffer::html(); for i in &non_trait { - if !saw_impls.insert(i.def_id()) { - continue; - } - if is_alias && !is_valid_impl_for(tcx, it, i.def_id()) { - continue; - } render_impl( &mut impls_buf, cx, @@ -1250,14 +1193,9 @@ fn render_assoc_items_inner( if !traits.is_empty() { let deref_impl = traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait()); - if let Some(impl_) = deref_impl && - (!is_alias || is_valid_impl_for(tcx, it, impl_.def_id())) - { + if let Some(impl_) = deref_impl { let has_deref_mut = - traits.iter().any(|t| { - t.trait_did() == cx.tcx().lang_items().deref_mut_trait() && - (!is_alias || is_valid_impl_for(tcx, it, t.def_id())) - }); + traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait()); render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs); } @@ -1267,14 +1205,10 @@ fn render_assoc_items_inner( return; } - let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = traits - .into_iter() - .filter(|t| saw_impls.insert(t.def_id())) - .partition(|t| t.inner_impl().kind.is_auto()); - let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete - .into_iter() - .filter(|t| !is_alias || is_valid_impl_for(tcx, it, t.def_id())) - .partition(|t| t.inner_impl().kind.is_blanket()); + let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = + traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); + let (blanket_impl, concrete): (Vec<&Impl>, _) = + concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl); } @@ -1313,10 +1247,10 @@ fn render_deref_methods( return; } } - render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs, None); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } else if let Some(prim) = target.primitive_type() { if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs, None); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 02cfad6b346..383e3c17088 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -129,7 +129,7 @@ macro_rules! item_template_methods { display_fn(move |f| { let (item, mut cx) = self.item_and_mut_cx(); let def_id = item.item_id.expect_def_id(); - let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All, None); + let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All); write!(f, "{v}") }) } @@ -953,11 +953,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } // If there are methods directly on this trait object, render them here. - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)); let cloned_shared = Rc::clone(&cx.shared); let cache = &cloned_shared.cache; @@ -1189,12 +1185,8 @@ fn item_trait_alias( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ) - .unwrap(); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) + .unwrap(); } fn item_opaque_ty( @@ -1222,12 +1214,8 @@ fn item_opaque_ty( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ) - .unwrap(); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) + .unwrap(); } fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { @@ -1251,11 +1239,11 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let def_id = it.item_id.expect_def_id(); - write!( - w, - "{}", - render_assoc_items(cx, it, def_id, AssocItemRender::All, t.type_.def_id(&cx.cache())) - ); + // Render any items associated directly to this alias, as otherwise they + // won't be visible anywhere in the docs. It would be nice to also show + // associated items from the aliased type (see discussion in #32077), but + // we need #14072 to make sense of the generics. + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } @@ -1494,7 +1482,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!(w, "</div>"); } let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All, None)); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } @@ -1537,7 +1525,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite let def_id = it.item_id.expect_def_id(); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All, None)).unwrap(); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)).unwrap(); } else { // We handle the "reference" primitive type on its own because we only want to list // implementations on generic types. @@ -1642,7 +1630,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } } let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All, None)); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } @@ -1677,12 +1665,8 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean:: }); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ) - .unwrap(); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) + .unwrap(); } fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { |
