Skip to content

Commit 788a802

Browse files
committed
New tests --- projection outlives relation
1 parent d159977 commit 788a802

15 files changed

+405
-23
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Regression test for issue #24622. The older associated types code
12+
// was erroneously assuming that all projections outlived the current
13+
// fn body, causing this (invalid) code to be accepted.
14+
15+
pub trait Foo<'a> {
16+
type Bar;
17+
}
18+
19+
impl<'a, T:'a> Foo<'a> for T {
20+
type Bar = &'a T;
21+
}
22+
23+
fn denormalise<'a, T>(t: &'a T) -> <T as Foo<'a>>::Bar {
24+
t
25+
}
26+
27+
pub fn free_and_use<T: for<'a> Foo<'a>,
28+
F: for<'a> FnOnce(<T as Foo<'a>>::Bar)>(x: T, f: F) {
29+
let y;
30+
'body: loop { // lifetime annotations added for clarity
31+
's: loop { y = denormalise(&x); break }
32+
drop(x); //~ ERROR cannot move out of `x` because it is borrowed
33+
return f(y);
34+
}
35+
}
36+
37+
pub fn main() {
38+
}

src/test/compile-fail/regions-close-associated-type-into-object.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,12 @@ fn meh1<'a, T: Iter>(v: &'a T) -> Box<X+'a>
7272
where T::Item : Clone
7373
{
7474
// This case is kind of interesting. It's the same as `ok3` but
75-
// without the explicit declaration. In principle, it seems like
76-
// we ought to be able to infer that `T::Item : 'a` because we
77-
// invoked `v.as_self()` which yielded a value of type `&'a
78-
// T::Item`. But we're not that smart at present.
75+
// without the explicit declaration. This is valid because `T: 'a
76+
// => T::Item: 'a`, and the former we can deduce from our argument
77+
// of type `&'a T`.
7978

8079
let item = Clone::clone(v.as_item());
81-
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live
80+
Box::new(item)
8281
}
8382

8483
fn main() {}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Illustrates the "projection gap": in this test, even though we know
12+
// that `T::Foo: 'x`, that does not tell us that `T: 'x`, because
13+
// there might be other ways for the caller of `func` to show that
14+
// `T::Foo: 'x` holds (e.g., where-clause).
15+
16+
trait Trait1<'x> {
17+
type Foo;
18+
}
19+
20+
// calling this fn should trigger a check that the type argument
21+
// supplied is well-formed.
22+
fn wf<T>() { }
23+
24+
fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
25+
{
26+
wf::<&'x T>();
27+
//~^ ERROR the parameter type `T` may not live long enough
28+
}
29+
30+
fn caller2<'x, T:Trait1<'x>>(t: &'x T)
31+
{
32+
wf::<&'x T::Foo>(); // OK
33+
}
34+
35+
fn caller3<'x, T:Trait1<'x>>(t: &'x T::Foo)
36+
{
37+
wf::<&'x T::Foo>(); // OK
38+
}
39+
40+
fn main() { }
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Along with the other tests in this series, illustrates the
12+
// "projection gap": in this test, we know that `T: 'x`, and that is
13+
// enough to conclude that `T::Foo: 'x`.
14+
15+
#![feature(rustc_attrs)]
16+
#![allow(dead_code)]
17+
#![allow(unused_variables)]
18+
19+
trait Trait1<'x> {
20+
type Foo;
21+
}
22+
23+
// calling this fn should trigger a check that the type argument
24+
// supplied is well-formed.
25+
fn wf<T>() { }
26+
27+
fn func<'x, T:Trait1<'x>>(t: &'x T)
28+
{
29+
wf::<&'x T::Foo>();
30+
}
31+
32+
#[rustc_error]
33+
fn main() { } //~ ERROR compilation successful
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Along with the other tests in this series, illustrates the
12+
// "projection gap": in this test, we know that `T::Foo: 'x`, and that
13+
// is (naturally) enough to conclude that `T::Foo: 'x`.
14+
15+
#![feature(rustc_attrs)]
16+
#![allow(dead_code)]
17+
#![allow(unused_variables)]
18+
19+
trait Trait1<'x> {
20+
type Foo;
21+
}
22+
23+
// calling this fn should trigger a check that the type argument
24+
// supplied is well-formed.
25+
fn wf<T>() { }
26+
27+
fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
28+
{
29+
wf::<&'x T::Foo>();
30+
}
31+
32+
#[rustc_error]
33+
fn main() { } //~ ERROR compilation successful
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Along with the other tests in this series, illustrates the
12+
// "projection gap": in this test, we know that `T: 'x`, and that
13+
// is (naturally) enough to conclude that `T: 'x`.
14+
15+
#![feature(rustc_attrs)]
16+
#![allow(dead_code)]
17+
#![allow(unused_variables)]
18+
19+
trait Trait1<'x> {
20+
type Foo;
21+
}
22+
23+
// calling this fn should trigger a check that the type argument
24+
// supplied is well-formed.
25+
fn wf<T>() { }
26+
27+
fn func<'x, T:Trait1<'x>>(t: &'x T)
28+
{
29+
wf::<&'x T>();
30+
}
31+
32+
#[rustc_error]
33+
fn main() { } //~ ERROR compilation successful
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// The "projection gap" is particularly "fun" around higher-ranked
12+
// projections. This is because the current code is hard-coded to say
13+
// that a projection that contains escaping regions, like `<T as
14+
// Trait2<'y, 'z>>::Foo` where `'z` is bound, can only be found to
15+
// outlive a region if all components that appear free (`'y`, where)
16+
// outlive that region. However, we DON'T add those components to the
17+
// implied bounds set, but rather we treat projections with escaping
18+
// regions as opaque entities, just like projections without escaping
19+
// regions.
20+
21+
trait Trait1<T> { }
22+
23+
trait Trait2<'a, 'b> {
24+
type Foo;
25+
}
26+
27+
fn wf<T>() { }
28+
29+
// As a side-effect of the conservative process above, this argument
30+
// is not automatically considered well-formed, since for it to be WF,
31+
// we would need to know that `'y: 'x`, but we do not infer that.
32+
fn callee<'x, 'y, T>(
33+
t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
34+
{
35+
wf::<&'x &'y i32>();
36+
//~^ ERROR reference has a longer lifetime than the data it references
37+
}
38+
39+
fn main() { }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
12+
// arguments (like `'a`) outlive `'b`.
13+
//
14+
// Rule OutlivesNominalType from RFC 1214.
15+
16+
#![feature(rustc_attrs)]
17+
#![allow(dead_code)]
18+
19+
mod variant_enum_region {
20+
enum Foo<'a> {
21+
V { x: &'a i32 }
22+
}
23+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
24+
f: &'a Foo<'b>
25+
}
26+
}
27+
28+
mod rev_variant_enum_region {
29+
enum Foo<'a> {
30+
V { x: fn(&'a i32) }
31+
}
32+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
33+
f: &'a Foo<'b>
34+
}
35+
}
36+
37+
mod variant_enum_type {
38+
enum Foo<T> {
39+
V { x: T }
40+
}
41+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
42+
f: &'a Foo<&'b i32>
43+
}
44+
}
45+
46+
mod rev_variant_enum_type {
47+
enum Foo<T> {
48+
V { x: fn(T) }
49+
}
50+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
51+
f: &'a Foo<&'b i32>
52+
}
53+
}
54+
55+
#[rustc_error]
56+
fn main() { }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its
12+
// arguments (like `'a`) outlive `'b`.
13+
//
14+
// Rule OutlivesNominalType from RFC 1214.
15+
16+
#![feature(rustc_attrs)]
17+
#![allow(dead_code)]
18+
19+
mod variant_struct_region {
20+
struct Foo<'a> {
21+
x: &'a i32,
22+
}
23+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
24+
f: &'a Foo<'b>
25+
}
26+
}
27+
28+
mod rev_variant_struct_region {
29+
struct Foo<'a> {
30+
x: fn(&'a i32),
31+
}
32+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
33+
f: &'a Foo<'b>
34+
}
35+
}
36+
37+
mod variant_struct_type {
38+
struct Foo<T> {
39+
x: T
40+
}
41+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
42+
f: &'a Foo<&'b i32>
43+
}
44+
}
45+
46+
mod rev_variant_struct_type {
47+
struct Foo<T> {
48+
x: fn(T)
49+
}
50+
struct Bar<'a,'b> { //~ ERROR reference has a longer lifetime
51+
f: &'a Foo<&'b i32>
52+
}
53+
}
54+
55+
#[rustc_error]
56+
fn main() { }

src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs renamed to src/test/compile-fail/regions-outlives-projection-container-hrtb.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ pub struct WithHrAssoc<T>
3737
}
3838

3939
fn with_assoc<'a,'b>() {
40-
// We get no error here because the where clause has a higher-ranked assoc type,
41-
// which could not be projected from.
40+
// We get an error because beacuse 'b:'a does not hold:
4241

4342
let _: &'a WithHrAssoc<TheType<'b>> = loop { };
43+
//~^ ERROR reference has a longer lifetime
4444
}
4545

4646
///////////////////////////////////////////////////////////////////////////
@@ -57,12 +57,13 @@ pub struct WithHrAssocSub<T>
5757
}
5858

5959
fn with_assoc_sub<'a,'b>() {
60-
// Same here, because although the where clause is not HR, it
61-
// extends a trait in a HR way.
60+
// The error here is just because `'b:'a` must hold for the type
61+
// below to be well-formed, it is not related to the HR relation.
6262

6363
let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
64+
//~^ ERROR reference has a longer lifetime
6465
}
6566

6667
#[rustc_error]
67-
fn main() { //~ ERROR compilation successful
68+
fn main() {
6869
}

0 commit comments

Comments
 (0)