about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2023-07-22 12:20:17 +0200
committerLeón Orell Valerian Liehr <me@fmease.dev>2023-07-22 12:20:17 +0200
commit5924043b868e31623f50a86d6eb41d10ac8e5173 (patch)
treea67126e4b32479d1e0952c205b352ebcb1adc219
parentc3c5a5c5f7a0cf9acdfe60440a1e1fa68a1c1278 (diff)
downloadrust-5924043b868e31623f50a86d6eb41d10ac8e5173.tar.gz
rust-5924043b868e31623f50a86d6eb41d10ac8e5173.zip
rustdoc: handle cross-crate RPITITs correctly
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs9
-rw-r--r--src/librustdoc/clean/blanket_impl.rs3
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/html/render/mod.rs4
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs35
-rw-r--r--tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs35
7 files changed, 84 insertions, 8 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index b5b00b7b640..4347c0de4c2 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2081,9 +2081,9 @@ rustc_queries! {
         }
     }
 
-    query is_impossible_method(key: (DefId, DefId)) -> bool {
+    query is_impossible_associated_item(key: (DefId, DefId)) -> bool {
         desc { |tcx|
-            "checking if `{}` is impossible to call within `{}`",
+            "checking if `{}` is impossible to reference within `{}`",
             tcx.def_path_str(key.1),
             tcx.def_path_str(key.0),
         }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 1c145999184..6bab87e5de5 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -474,11 +474,14 @@ fn subst_and_check_impossible_predicates<'tcx>(
     result
 }
 
-/// Checks whether a trait's method is impossible to call on a given impl.
+/// Checks whether a trait's associated item is impossible to reference on a given impl.
 ///
 /// This only considers predicates that reference the impl's generics, and not
 /// those that reference the method's generics.
-fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool {
+fn is_impossible_associated_item(
+    tcx: TyCtxt<'_>,
+    (impl_def_id, trait_item_def_id): (DefId, DefId),
+) -> bool {
     struct ReferencesOnlyParentGenerics<'tcx> {
         tcx: TyCtxt<'tcx>,
         generics: &'tcx ty::Generics,
@@ -556,7 +559,7 @@ pub fn provide(providers: &mut Providers) {
         specializes: specialize::specializes,
         subst_and_check_impossible_predicates,
         check_tys_might_be_eq: misc::check_tys_might_be_eq,
-        is_impossible_method,
+        is_impossible_associated_item,
         ..*providers
     };
 }
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index f5e02940c82..9d744237b57 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -121,7 +121,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .tcx
                             .associated_items(impl_def_id)
                             .in_definition_order()
-                            .map(|x| clean_middle_assoc_item(x, cx))
+                            .filter(|item| !item.is_impl_trait_in_trait())
+                            .map(|item| clean_middle_assoc_item(item, cx))
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index cfd9875e1c8..89eaf561e6a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -216,6 +216,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
         .tcx
         .associated_items(did)
         .in_definition_order()
+        .filter(|item| !item.is_impl_trait_in_trait())
         .map(|item| clean_middle_assoc_item(item, cx))
         .collect();
 
@@ -459,6 +460,7 @@ pub(crate) fn build_impl(
         None => (
             tcx.associated_items(did)
                 .in_definition_order()
+                .filter(|item| !item.is_impl_trait_in_trait())
                 .filter(|item| {
                     // If this is a trait impl, filter out associated items whose corresponding item
                     // in the associated trait is marked `doc(hidden)`.
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4d029407afa..2fcf61d0049 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1678,11 +1678,11 @@ fn render_impl(
         rendering_params: ImplRenderingParameters,
     ) {
         for trait_item in &t.items {
-            // Skip over any default trait items that are impossible to call
+            // Skip over any default trait items that are impossible to reference
             // (e.g. if it has a `Self: Sized` bound on an unsized type).
             if let Some(impl_def_id) = parent.item_id.as_def_id()
                 && let Some(trait_item_def_id) = trait_item.item_id.as_def_id()
-                && cx.tcx().is_impossible_method((impl_def_id, trait_item_def_id))
+                && cx.tcx().is_impossible_associated_item((impl_def_id, trait_item_def_id))
             {
                 continue;
             }
diff --git a/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs
new file mode 100644
index 00000000000..c72f011152d
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs
@@ -0,0 +1,35 @@
+#![feature(return_position_impl_trait_in_trait)]
+
+pub trait Trait {
+    fn create() -> impl Iterator<Item = u64> {
+        std::iter::empty()
+    }
+}
+
+pub struct Basic;
+pub struct Intermediate;
+pub struct Advanced;
+
+impl Trait for Basic {
+    // method provided by the trait
+}
+
+impl Trait for Intermediate {
+    fn create() -> std::ops::Range<u64> { // concrete return type
+        0..1
+    }
+}
+
+impl Trait for Advanced {
+    fn create() -> impl Iterator<Item = u64> { // opaque return type
+        std::iter::repeat(0)
+    }
+}
+
+// Regression test for issue #113929:
+
+pub trait Def {
+    fn def<T>() -> impl Default {}
+}
+
+impl Def for () {}
diff --git a/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs
new file mode 100644
index 00000000000..8e9ef902015
--- /dev/null
+++ b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs
@@ -0,0 +1,35 @@
+#![crate_name = "user"]
+// aux-crate:rpitit=ret-pos-impl-trait-in-trait.rs
+// edition:2021
+
+// Test that we can correctly render cross-crate RPITITs.
+// In particular, check that we don't render the internal associated type generated by
+// their desugaring. We count the number of associated items and ensure that it is exactly one.
+// This is more robust than checking for the absence of the associated type.
+
+// @has user/trait.Trait.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator<Item = u64>'
+// The class "method" is used for all three kinds of associated items at the time of writing.
+// @count - '//*[@id="main-content"]//section[@class="method"]' 1
+pub use rpitit::Trait;
+
+// @has user/struct.Basic.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator<Item = u64>'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Basic;
+
+// @has user/struct.Intermediate.html
+// @has - '//*[@id="method.create"]' 'fn create() -> Range<u64>'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Intermediate;
+
+// @has user/struct.Advanced.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator<Item = u64>'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Advanced;
+
+// Regression test for issue #113929:
+
+// @has user/trait.Def.html
+// @has - '//*[@id="method.def"]' 'fn def<T>() -> impl Default'
+pub use rpitit::Def;