From 0e2af5cc63065db84ffee23532ec572e644e4cf4 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Mon, 2 Nov 2020 22:19:36 +0100 Subject: [PATCH] Check predicates from blanket trait impls while testing if they apply --- src/librustdoc/clean/blanket_impl.rs | 30 +++++++++++++++++++++------- src/test/rustdoc/issue-78673.rs | 24 ++++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 src/test/rustdoc/issue-78673.rs diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index de5a9a615557c..7030fd9b7f23b 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 0000000000000..d09141c320473 --- /dev/null +++ b/src/test/rustdoc/issue-78673.rs @@ -0,0 +1,24 @@ +#![crate_name = "issue_78673"] + +pub trait Something {} + +pub trait AnAmazingTrait {} + +impl 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); + +impl Something for AnotherStruct {} +impl AnAmazingTrait for AnotherStruct<()> {}