about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/clean/blanket_impl.rs30
-rw-r--r--src/test/rustdoc/issue-78673.rs24
2 files changed, 47 insertions, 7 deletions
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index de5a9a61555..7030fd9b7f2 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -62,14 +62,30 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
                             param_env, trait_ref, ty
                         );
-                        match infcx.evaluate_obligation(&traits::Obligation::new(
-                            cause,
-                            param_env,
-                            trait_ref.without_const().to_predicate(infcx.tcx),
-                        )) {
-                            Ok(eval_result) => eval_result.may_apply(),
-                            Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no
+                        let predicates = self
+                            .cx
+                            .tcx
+                            .predicates_of(impl_def_id)
+                            .instantiate(self.cx.tcx, impl_substs)
+                            .predicates
+                            .into_iter()
+                            .chain(Some(trait_ref.without_const().to_predicate(infcx.tcx)));
+                        for predicate in predicates {
+                            debug!("testing predicate {:?}", predicate);
+                            let obligation = traits::Obligation::new(
+                                traits::ObligationCause::dummy(),
+                                param_env,
+                                predicate,
+                            );
+                            match infcx.evaluate_obligation(&obligation) {
+                                Ok(eval_result) if eval_result.may_apply() => {}
+                                Err(traits::OverflowError) => {}
+                                _ => {
+                                    return false;
+                                }
+                            }
                         }
+                        true
                     } else {
                         false
                     }
diff --git a/src/test/rustdoc/issue-78673.rs b/src/test/rustdoc/issue-78673.rs
new file mode 100644
index 00000000000..d09141c3204
--- /dev/null
+++ b/src/test/rustdoc/issue-78673.rs
@@ -0,0 +1,24 @@
+#![crate_name = "issue_78673"]
+
+pub trait Something {}
+
+pub trait AnAmazingTrait {}
+
+impl<T: Something> AnAmazingTrait for T {}
+
+// @has 'issue_78673/struct.MyStruct.html'
+// @has  - '//*[@class="impl"]' 'AnAmazingTrait for MyStruct'
+// @!has - '//*[@class="impl"]' 'AnAmazingTrait for T'
+pub struct MyStruct;
+
+impl AnAmazingTrait for MyStruct {}
+
+// generic structs may have _both_ specific and blanket impls that apply
+
+// @has 'issue_78673/struct.AnotherStruct.html'
+// @has - '//*[@class="impl"]' 'AnAmazingTrait for AnotherStruct<()>'
+// @has - '//*[@class="impl"]' 'AnAmazingTrait for T'
+pub struct AnotherStruct<T>(T);
+
+impl<T: Something> Something for AnotherStruct<T> {}
+impl AnAmazingTrait for AnotherStruct<()> {}