Check predicates from blanket trait impls while testing if they apply

This commit is contained in:
Wim Looman 2020-11-02 22:19:36 +01:00
parent 4051473c8b
commit 0e2af5cc63
2 changed files with 47 additions and 7 deletions

View File

@ -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
}

View File

@ -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<()> {}