1
Fork 0

New tests --- projection outlives relation

This commit is contained in:
Niko Matsakis 2015-08-07 13:25:23 -04:00
parent d159977502
commit 788a802dad
15 changed files with 405 additions and 23 deletions

View file

@ -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() {
}

View file

@ -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() {}

View file

@ -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() { }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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() { }

View file

@ -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() { }

View file

@ -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() { }

View file

@ -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() {
}

View file

@ -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>() { }

View file

@ -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

View file

@ -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

View file

@ -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