Change:
First reported in cc - let's discuss this when you are back from vacation (unless can come up with a solution?)
Associated types variant, which bypasses some fixes based only on supertraits:
Chalk's strategy will solve this, but I guess that shouldn't be extremely difficult to fix even with the current strategy. The first impl is valid: since indeed implies that . The second however, is not: the impl declaration should be able to prove that holds (ok because of the first impl), but also that is well-formed, i.e. that holds. Same thing in the second example, this impl declaration: should prove that (ok) and that is well-formed, i.e. . The latter is not being proved currently.
triage: P-high -- has pending fix

Discussion:
-> Vec<traits::PredicateObligation<'tcx>> { let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; <del> wf.compute_trait_ref(trait_ref); </del> <ins> wf.compute_trait_ref(trait_ref, Elaborate::All); </ins> wf.normalize() }

// (*) ok to skip binders, because wf code is prepared for it match *predicate { ty::Predicate::Trait(ref t) => { <del> wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*) </del> <ins> wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*) </ins> } ty::Predicate::Equate(ref t) => { wf.compute(t.skip_binder().0);

out: Vec<traits::PredicateObligation<'tcx>>, } <ins> /// Controls whether we "elaborate" supertraits and so forth on the WF /// predicates. This is a kind of hack to address #43784. The /// underlying problem in that issue was a trait structure like: /// /// ``` /// trait Foo: Copy { } /// trait Bar: Foo { } /// impl<T: Bar> Foo for T { } /// impl<T> Bar for T { } /// ``` /// /// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but /// we decide that this is true because `T: Bar` is in the /// where-clauses (and we can elaborate that to include `T: /// Copy`). This wouldn't be a problem, except that when we check the /// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo` /// impl. And so nowhere did we check that `T: Copy` holds! /// /// To resolve this, we elaborate the WF requirements that must be /// proven when checking impls. This means that (e.g.) the `impl Bar /// for T` will be forced to prove not only that `T: Foo` but also `T: /// Copy` (which it won't be able to do, because there is no `Copy` /// impl for `T`). #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum Elaborate { All, None, } </ins> impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> { traits::ObligationCause::new(self.span, self.body_id, code)

/// Pushes the obligations required for `trait_ref` to be WF into /// `self.out`. <del> fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { </del> <ins> fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { </ins> let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); <del> self.out.extend(obligations); </del> let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; <ins> if let Elaborate::All = elaborate { let predicates = obligations.iter() .map(|obligation| obligation.predicate.clone()) .collect(); let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); let implied_obligations = implied_obligations.map(|pred| { traits::Obligation::new(cause.clone(), param_env, pred) }); self.out.extend(implied_obligations); } self.out.extend(obligations); </ins> self.out.extend( trait_ref.substs.types() .filter(|ty| !ty.has_escaping_regions())

// WF and (b) the trait-ref holds.  (It may also be // normalizable and be WF that way.) let trait_ref = data.trait_ref(self.infcx.tcx); <del> self.compute_trait_ref(&trait_ref); </del> <ins> self.compute_trait_ref(&trait_ref, Elaborate::None); </ins> if !data.has_escaping_regions() { let predicate = trait_ref.to_predicate();

<ins> // Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. pub trait Partial<X: ?Sized>: Copy { } pub trait Complete { type Assoc: Partial<Self>; } impl<T> Partial<T> for T::Assoc where T: Complete { } impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied type Assoc = T; } </ins>

<ins> // Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. pub trait Partial: Copy { } pub trait Complete: Partial { } impl<T> Partial for T where T: Complete {} impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied </ins>