about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-11-13 23:12:01 +0000
committerbors <bors@rust-lang.org>2020-11-13 23:12:01 +0000
commitb63d05a908ab667f37ea9fb66f4fab9dd89fce76 (patch)
tree039eb8b20cc9cedfd963650ebfca7077f85ace49 /src
parent74f7e32f43b5fb0f83896d124566d8242eb786b1 (diff)
parent0e2af5cc63065db84ffee23532ec572e644e4cf4 (diff)
downloadrust-b63d05a908ab667f37ea9fb66f4fab9dd89fce76.tar.gz
rust-b63d05a908ab667f37ea9fb66f4fab9dd89fce76.zip
Auto merge of #78683 - Nemo157:issue-78673, r=lcnr
Check predicates from blanket trait impls while testing if they apply

fixes #78673
Diffstat (limited to 'src')
-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<()> {}