diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index e286855c285..8b29ef9b880 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -263,7 +263,13 @@ pub trait Combine<'tcx> : Sized { Err(ty::terr_projection_name_mismatched( expected_found(self, a.item_name, b.item_name))) } else { - let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref)); + // Note that the trait refs for the projection must be + // *equal*. This is because there is no inherent + // relationship between `::Bar` and `::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)); Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name }) } } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index dd42c667956..6c5950e4df5 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -793,7 +793,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { trait_def.generics.types.as_slice(), trait_def.generics.regions.as_slice(), trait_ref.substs, - variance); + self.invariant); } ty::ty_trait(ref data) => { diff --git a/src/test/compile-fail/associated-types-subtyping-1.rs b/src/test/compile-fail/associated-types-subtyping-1.rs new file mode 100644 index 00000000000..f9106ba3960 --- /dev/null +++ b/src/test/compile-fail/associated-types-subtyping-1.rs @@ -0,0 +1,55 @@ +// 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 or the MIT license +// , 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: >::Type = loop { }; + let b: >::Type = loop { }; + let _: >::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: >::Type = loop { }; + let b: >::Type = loop { }; + let _: >::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: >::Type = loop { }; + let b: >::Type = loop { }; + let _: >::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: >::Type = loop { }; + let b: >::Type = loop { }; + let _: >::Type = b; +} + +fn main() { } diff --git a/src/test/compile-fail/variance-associated-types.rs b/src/test/compile-fail/variance-associated-types.rs new file mode 100644 index 00000000000..ecb2287769b --- /dev/null +++ b/src/test/compile-fail/variance-associated-types.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , 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: >::Type +} + +fn main() { } diff --git a/src/test/run-pass/issue-21726.rs b/src/test/run-pass/issue-21726.rs new file mode 100644 index 00000000000..09d1a3bca69 --- /dev/null +++ b/src/test/run-pass/issue-21726.rs @@ -0,0 +1,44 @@ +// 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 or the MIT license +// , 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() + } +}