diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-08-07 13:25:23 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-08-12 17:58:22 -0400 |
| commit | 788a802dad3f273b74150b732d24d37a695d29f6 (patch) | |
| tree | af418f292ef4e3fe2c3317543c4b2e49486772c9 | |
| parent | d15997750211421cc1367faba574b3d9b2dc2432 (diff) | |
| download | rust-788a802dad3f273b74150b732d24d37a695d29f6.tar.gz rust-788a802dad3f273b74150b732d24d37a695d29f6.zip | |
New tests --- projection outlives relation
15 files changed, 405 insertions, 23 deletions
diff --git a/src/test/compile-fail/associated-types-outlives.rs b/src/test/compile-fail/associated-types-outlives.rs new file mode 100644 index 00000000000..f070ab6799c --- /dev/null +++ b/src/test/compile-fail/associated-types-outlives.rs @@ -0,0 +1,38 @@ +// 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 issue #24622. The older associated types code +// was erroneously assuming that all projections outlived the current +// fn body, causing this (invalid) code to be accepted. + +pub trait Foo<'a> { + type Bar; +} + +impl<'a, T:'a> Foo<'a> for T { + type Bar = &'a T; +} + +fn denormalise<'a, T>(t: &'a T) -> <T as Foo<'a>>::Bar { + t +} + +pub fn free_and_use<T: for<'a> Foo<'a>, + F: for<'a> FnOnce(<T as Foo<'a>>::Bar)>(x: T, f: F) { + let y; + 'body: loop { // lifetime annotations added for clarity + 's: loop { y = denormalise(&x); break } + drop(x); //~ ERROR cannot move out of `x` because it is borrowed + return f(y); + } +} + +pub fn main() { +} diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs index fdc97ecaf21..61897aac187 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -72,13 +72,12 @@ fn meh1<'a, T: Iter>(v: &'a T) -> Box<X+'a> where T::Item : Clone { // This case is kind of interesting. It's the same as `ok3` but - // without the explicit declaration. In principle, it seems like - // we ought to be able to infer that `T::Item : 'a` because we - // invoked `v.as_self()` which yielded a value of type `&'a - // T::Item`. But we're not that smart at present. + // without the explicit declaration. This is valid because `T: 'a + // => T::Item: 'a`, and the former we can deduce from our argument + // of type `&'a T`. let item = Clone::clone(v.as_item()); - Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live + Box::new(item) } fn main() {} diff --git a/src/test/compile-fail/regions-implied-bounds-projection-gap-1.rs b/src/test/compile-fail/regions-implied-bounds-projection-gap-1.rs new file mode 100644 index 00000000000..65594ab8f2e --- /dev/null +++ b/src/test/compile-fail/regions-implied-bounds-projection-gap-1.rs @@ -0,0 +1,40 @@ +// Copyright 2012 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. + +// Illustrates the "projection gap": in this test, even though we know +// that `T::Foo: 'x`, that does not tell us that `T: 'x`, because +// there might be other ways for the caller of `func` to show that +// `T::Foo: 'x` holds (e.g., where-clause). + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf<T>() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) +{ + wf::<&'x T>(); + //~^ ERROR the parameter type `T` may not live long enough +} + +fn caller2<'x, T:Trait1<'x>>(t: &'x T) +{ + wf::<&'x T::Foo>(); // OK +} + +fn caller3<'x, T:Trait1<'x>>(t: &'x T::Foo) +{ + wf::<&'x T::Foo>(); // OK +} + +fn main() { } diff --git a/src/test/compile-fail/regions-implied-bounds-projection-gap-2.rs b/src/test/compile-fail/regions-implied-bounds-projection-gap-2.rs new file mode 100644 index 00000000000..b3037a1e187 --- /dev/null +++ b/src/test/compile-fail/regions-implied-bounds-projection-gap-2.rs @@ -0,0 +1,33 @@ +// Copyright 2012 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. + +// Along with the other tests in this series, illustrates the +// "projection gap": in this test, we know that `T: 'x`, and that is +// enough to conclude that `T::Foo: 'x`. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf<T>() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T) +{ + wf::<&'x T::Foo>(); +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/regions-implied-bounds-projection-gap-3.rs b/src/test/compile-fail/regions-implied-bounds-projection-gap-3.rs new file mode 100644 index 00000000000..a2e6de21376 --- /dev/null +++ b/src/test/compile-fail/regions-implied-bounds-projection-gap-3.rs @@ -0,0 +1,33 @@ +// Copyright 2012 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. + +// Along with the other tests in this series, illustrates the +// "projection gap": in this test, we know that `T::Foo: 'x`, and that +// is (naturally) enough to conclude that `T::Foo: 'x`. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf<T>() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) +{ + wf::<&'x T::Foo>(); +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/regions-implied-bounds-projection-gap-4.rs b/src/test/compile-fail/regions-implied-bounds-projection-gap-4.rs new file mode 100644 index 00000000000..b8582f8c26b --- /dev/null +++ b/src/test/compile-fail/regions-implied-bounds-projection-gap-4.rs @@ -0,0 +1,33 @@ +// Copyright 2012 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. + +// Along with the other tests in this series, illustrates the +// "projection gap": in this test, we know that `T: 'x`, and that +// is (naturally) enough to conclude that `T: 'x`. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf<T>() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T) +{ + wf::<&'x T>(); +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/compile-fail/regions-implied-bounds-projection-gap-hr-1.rs new file mode 100644 index 00000000000..47985f931dd --- /dev/null +++ b/src/test/compile-fail/regions-implied-bounds-projection-gap-hr-1.rs @@ -0,0 +1,39 @@ +// Copyright 2012 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. + +// The "projection gap" is particularly "fun" around higher-ranked +// projections. This is because the current code is hard-coded to say +// that a projection that contains escaping regions, like `<T as +// Trait2<'y, 'z>>::Foo` where `'z` is bound, can only be found to +// outlive a region if all components that appear free (`'y`, where) +// outlive that region. However, we DON'T add those components to the +// implied bounds set, but rather we treat projections with escaping +// regions as opaque entities, just like projections without escaping +// regions. + +trait Trait1<T> { } + +trait Trait2<'a, 'b> { + type Foo; +} + +fn wf<T>() { } + +// As a side-effect of the conservative process above, this argument +// is not automatically considered well-formed, since for it to be WF, +// we would need to know that `'y: 'x`, but we do not infer that. +fn callee<'x, 'y, T>( + t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >) +{ + wf::<&'x &'y i32>(); + //~^ ERROR reference has a longer lifetime than the data it references +} + +fn main() { } diff --git a/src/test/compile-fail/regions-outlives-nominal-type-enum.rs b/src/test/compile-fail/regions-outlives-nominal-type-enum.rs new file mode 100644 index 00000000000..6fb409326f1 --- /dev/null +++ b/src/test/compile-fail/regions-outlives-nominal-type-enum.rs @@ -0,0 +1,56 @@ +// Copyright 2014 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 a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_enum_region { + enum Foo<'a> { + V { x: &'a i32 } + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<'b> + } +} + +mod rev_variant_enum_region { + enum Foo<'a> { + V { x: fn(&'a i32) } + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<'b> + } +} + +mod variant_enum_type { + enum Foo<T> { + V { x: T } + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<&'b i32> + } +} + +mod rev_variant_enum_type { + enum Foo<T> { + V { x: fn(T) } + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<&'b i32> + } +} + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/regions-outlives-nominal-type-struct.rs b/src/test/compile-fail/regions-outlives-nominal-type-struct.rs new file mode 100644 index 00000000000..fb3fdddae88 --- /dev/null +++ b/src/test/compile-fail/regions-outlives-nominal-type-struct.rs @@ -0,0 +1,56 @@ +// Copyright 2014 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 a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_struct_region { + struct Foo<'a> { + x: &'a i32, + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<'b> + } +} + +mod rev_variant_struct_region { + struct Foo<'a> { + x: fn(&'a i32), + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<'b> + } +} + +mod variant_struct_type { + struct Foo<T> { + x: T + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<&'b i32> + } +} + +mod rev_variant_struct_type { + struct Foo<T> { + x: fn(T) + } + struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime + f: &'a Foo<&'b i32> + } +} + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs b/src/test/compile-fail/regions-outlives-projection-container-hrtb.rs index 0d3d2e296be..b8c4a7f8a8c 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs +++ b/src/test/compile-fail/regions-outlives-projection-container-hrtb.rs @@ -37,10 +37,10 @@ pub struct WithHrAssoc<T> } fn with_assoc<'a,'b>() { - // We get no error here because the where clause has a higher-ranked assoc type, - // which could not be projected from. + // We get an error because beacuse 'b:'a does not hold: let _: &'a WithHrAssoc<TheType<'b>> = loop { }; + //~^ ERROR reference has a longer lifetime } /////////////////////////////////////////////////////////////////////////// @@ -57,12 +57,13 @@ pub struct WithHrAssocSub<T> } fn with_assoc_sub<'a,'b>() { - // Same here, because although the where clause is not HR, it - // extends a trait in a HR way. + // The error here is just because `'b:'a` must hold for the type + // below to be well-formed, it is not related to the HR relation. let _: &'a WithHrAssocSub<TheType<'b>> = loop { }; + //~^ ERROR reference has a longer lifetime } #[rustc_error] -fn main() { //~ ERROR compilation successful +fn main() { } diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs b/src/test/compile-fail/regions-outlives-projection-container-wc.rs index 2ceaea98d27..2ceaea98d27 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs +++ b/src/test/compile-fail/regions-outlives-projection-container-wc.rs diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container.rs b/src/test/compile-fail/regions-outlives-projection-container.rs index e3e57ff1711..6f5ebf2d1ce 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container.rs +++ b/src/test/compile-fail/regions-outlives-projection-container.rs @@ -59,11 +59,10 @@ fn with_assoc1<'a,'b>() where 'b : 'a { } fn without_assoc<'a,'b>() { - // Here there are no associated types and the `'b` appearing in - // `TheType<'b>` is purely covariant, so there is no requirement - // that `'b:'a` holds. + // Here there are no associated types but there is a requirement + // that `'b:'a` holds because the `'b` appears in `TheType<'b>`. - let _: &'a WithoutAssoc<TheType<'b>> = loop { }; + let _: &'a WithoutAssoc<TheType<'b>> = loop { }; //~ ERROR reference has a longer lifetime } fn call_with_assoc<'a,'b>() { @@ -72,13 +71,13 @@ fn call_with_assoc<'a,'b>() { // no data. call::<&'a WithAssoc<TheType<'b>>>(); - //~^ ERROR cannot infer + //~^ ERROR reference has a longer lifetime } fn call_without_assoc<'a,'b>() { // As `without_assoc`, but in a distinct scenario. - call::<&'a WithoutAssoc<TheType<'b>>>(); + call::<&'a WithoutAssoc<TheType<'b>>>(); //~ ERROR reference has a longer lifetime } fn call<T>() { } diff --git a/src/test/compile-fail/regions-outlives-projection-trait-def.rs b/src/test/compile-fail/regions-outlives-projection-trait-def.rs new file mode 100644 index 00000000000..04682a77297 --- /dev/null +++ b/src/test/compile-fail/regions-outlives-projection-trait-def.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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 `<F as Foo<'a>>::Type: 'b`, where `trait Foo<'a> { Type: +// 'a; }`, does not require that `F: 'b`. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait SomeTrait<'a> { + type Type: 'a; +} + +impl<'a: 'c, 'c, T> SomeTrait<'a> for &'c T where T: SomeTrait<'a> { + type Type = <T as SomeTrait<'a>>::Type; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~ + // | + // Note that this type must outlive 'a, due to the trait + // definition. If we fall back to OutlivesProjectionComponents + // here, then we would require that `T:'a`, which is too strong. +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/regions-outlives-scalar.rs b/src/test/compile-fail/regions-outlives-scalar.rs new file mode 100644 index 00000000000..94f7a350cf7 --- /dev/null +++ b/src/test/compile-fail/regions-outlives-scalar.rs @@ -0,0 +1,23 @@ +// Copyright 2014 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 scalar values outlive all regions. +// Rule OutlivesScalar from RFC 1214. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +struct Foo<'a> { + x: &'a i32, + y: &'static i32 +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/traits-issue-23003-overflow.rs b/src/test/compile-fail/traits-issue-23003-overflow.rs index ea41775f310..80d2884ee60 100644 --- a/src/test/compile-fail/traits-issue-23003-overflow.rs +++ b/src/test/compile-fail/traits-issue-23003-overflow.rs @@ -9,10 +9,11 @@ // except according to those terms. // A variant of traits-issue-23003 in which an infinite series of -// types are required. This currently creates an overflow. This test -// is included to ensure that some controlled failure, at least, -// results -- but it might be that we should adjust the rules somewhat -// to make this legal. -nmatsakis +// types are required. This test now just compiles fine, since the +// relevant rules that triggered the overflow were removed. + +#![feature(rustc_attrs)] +#![allow(dead_code)] use std::marker::PhantomData; @@ -32,7 +33,7 @@ impl<B> Async for Complete<B> { type Cancel = Receipt<Complete<Option<B>>>; } -fn foo(r: Receipt<Complete<()>>) { } -//~^ ERROR overflow +fn foo(_: Receipt<Complete<()>>) { } -fn main() { } +#[rustc_error] +fn main() { } //~ ERROR compilation successful |
