normalize trait-ref in context of impl

The `specializes()` function was trying to normalize the impl trait in
an empty environment. This could lead to inexplicable failures.
This commit is contained in:
Niko Matsakis 2016-11-02 11:50:16 -04:00
parent 797e0420e3
commit d9bc86032d

View file

@ -148,6 +148,8 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl1_def_id: DefId,
impl2_def_id: DefId) -> bool {
debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
if let Some(r) = tcx.specializes_cache.borrow().check(impl1_def_id, impl2_def_id) {
return r;
}
@ -177,21 +179,22 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
let mut penv = tcx.construct_parameter_environment(DUMMY_SP,
impl1_def_id,
region::DUMMY_CODE_EXTENT);
let penv = tcx.construct_parameter_environment(DUMMY_SP,
impl1_def_id,
region::DUMMY_CODE_EXTENT);
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
.unwrap()
.subst(tcx, &penv.free_substs);
let result = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|mut infcx| {
// Create a infcx, taking the predicates of impl1 as assumptions:
let result = tcx.infer_ctxt(None, Some(penv), Reveal::ExactMatch).enter(|mut infcx| {
// Normalize the trait reference, adding any obligations
// that arise into the impl1 assumptions.
let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = {
let selcx = &mut SelectionContext::new(&infcx);
traits::normalize(selcx, ObligationCause::dummy(), &impl1_trait_ref)
};
penv.caller_bounds.extend(normalization_obligations.into_iter().map(|o| {
infcx.parameter_environment.caller_bounds.extend(normalization_obligations.into_iter().map(|o| {
match tcx.lift_to_global(&o.predicate) {
Some(predicate) => predicate,
None => {
@ -200,9 +203,6 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}));
// Install the parameter environment, taking the predicates of impl1 as assumptions:
infcx.parameter_environment = penv;
// Attempt to prove that impl2 applies, given all of the above.
fulfill_implication(&infcx, impl1_trait_ref, impl2_def_id).is_ok()
});