about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-12 10:08:45 +0000
committerbors <bors@rust-lang.org>2023-06-12 10:08:45 +0000
commitcb882fa998571e8a7ec1c06bb5d9dd9bc3423629 (patch)
tree134c65ef9c18965844b6e367357b41ad572f5d1f /src
parentfd0a3313f7a64cb16533030e49a271db449368c3 (diff)
parentb93ca0146af3a8adeee286d3d4dbd561e534a8bf (diff)
downloadrust-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.rs90
-rw-r--r--src/librustdoc/html/render/print_item.rs48
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) {