Change:
showed me program which fails to compile. Here is a reduced version: This yields: However, if you change the type of to , it builds. Seems like there is a missing constraint somewhere in the region inference graph.
I tagged this as associated items as my best guess is that the constraint that would to affect is somehow getting lost.
I think the problem is actually variance, as guessed initially, or perhaps a question of what the subtyping rules for associated types ought to be. Let's consider a simple trait : The normal variance inference will conclude that is contravariant w/r/t , because only appears in a contravariant position in the method signature for . Now imagine I have and , where . What can we say about the relationship between and , if any? My first thought was that since (since is contravariant), we could say that . But that doesn't seem to make any sense -- after all, this contravariance result is based purely on method signatures, and has no relation to the associated type definitions. And anyway we can easily concoct some examples where that relationship doesn't hold: Now if and , where , then . So we'd expect that if my initial rules were correct, then -- and hence . But in fact , since fn types are covariant in their return type and . So in this case . But clearly we also can't conclude that in general either. After all, we can easily build another example where the relationship is the opposite: So it seems like the only thing we can conclude is that iff . In other words, a projection type is invariant with respect to its trait reference. This seems awfully strong but it's not clear to me how to make a weaker rule, at least not without some kind of declaration in the trait somehow relating the variance of to the trait inputs.
Yes, I think your examples have hit it on the head: In general one cannot draw any conclusion about the relationship between and without adding constraints (in the trait definition itself) on (1.) what the implementing type chooses for the associated item and/or (2.) the variance of that associated type with respect to the trait inputs and/or the type. And we do not currently have anyway to express such constraints in the language, AFAICT.
I'll try to get a fix up for this today, but in the meantime you CAN workaround it by adding a method like this to the trait:
I already implemented the fix but I'm a bit stymied on how to write nice unit tests without support for style where clauses. I may just go off on a yak shave and implement those, which I've been meaning to do for other reasons.
Fix enqueued ().
Thanks! I'll use the workaround for now.

Discussion:
Err(ty::terr_projection_name_mismatched( expected_found(self, a.item_name, b.item_name))) } else { <del> let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref)); </del> <ins> // Note that the trait refs for the projection must be // *equal*. This is because there is no inherent // relationship between `<T as Foo>::Bar` and `<U as // Foo>::Bar` that we can derive based on how `T` relates // to `U`. Issue #21726 contains further discussion and // in-depth examples. let trait_ref = try!(self.equate().trait_refs(&*a.trait_ref, &*b.trait_ref)); </ins> Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name }) } }

trait_def.generics.types.as_slice(), trait_def.generics.regions.as_slice(), trait_ref.substs, <del> variance); </del> <ins> self.invariant); </ins> } ty::ty_trait(ref data) => {

<ins> // Copyright 2015 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. #![allow(unused_variables)] trait Trait<'a> { type Type; fn method(&'a self) { } } fn method1<'a,'b,T>(x: &'a T, y: &'b T) where T : for<'z> Trait<'z>, 'a : 'b { // Note that &'static T <: &'a T. let a: <T as Trait<'a>>::Type = loop { }; let b: <T as Trait<'b>>::Type = loop { }; let _: <T as Trait<'a>>::Type = a; } fn method2<'a,'b,T>(x: &'a T, y: &'b T) where T : for<'z> Trait<'z>, 'a : 'b { // Note that &'static T <: &'a T. let a: <T as Trait<'a>>::Type = loop { }; let b: <T as Trait<'b>>::Type = loop { }; let _: <T as Trait<'b>>::Type = a; //~ ERROR mismatched types } fn method3<'a,'b,T>(x: &'a T, y: &'b T) where T : for<'z> Trait<'z>, 'a : 'b { // Note that &'static T <: &'a T. let a: <T as Trait<'a>>::Type = loop { }; let b: <T as Trait<'b>>::Type = loop { }; let _: <T as Trait<'a>>::Type = b; //~ ERROR mismatched types } fn method4<'a,'b,T>(x: &'a T, y: &'b T) where T : for<'z> Trait<'z>, 'a : 'b { // Note that &'static T <: &'a T. let a: <T as Trait<'a>>::Type = loop { }; let b: <T as Trait<'b>>::Type = loop { }; let _: <T as Trait<'b>>::Type = b; } fn main() { } </ins>

<ins> // Copyright 2015 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. // Test that the variance computation considers types/regions that // appear in projections to be invariant. trait Trait<'a> { type Type; fn method(&'a self) { } } #[rustc_variance] struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[];[]], regions=[[-];[];[]]) field: (T, &'a ()) } #[rustc_variance] struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[];[]], regions=[[o];[];[]]) field: <T as Trait<'a>>::Type } fn main() { } </ins>

<ins> // Copyright 2015 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. // Regression test for #21726: an issue arose around the rules for // subtyping of projection types that resulted in an unconstrained // region, yielding region inference failures. fn main() { } fn foo<'a>(s: &'a str) { let b: B<()> = B::new(s, ()); b.get_short(); } trait IntoRef<'a> { type T: Clone; fn into_ref(self, &'a str) -> Self::T; } impl<'a> IntoRef<'a> for () { type T = &'a str; fn into_ref(self, s: &'a str) -> &'a str { s } } struct B<'a, P: IntoRef<'a>>(P::T); impl<'a, P: IntoRef<'a>> B<'a, P> { fn new(s: &'a str, i: P) -> B<'a, P> { B(i.into_ref(s)) } fn get_short(&self) -> P::T { self.0.clone() } } </ins>