diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f63e7b09947..2b62e513ab2 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1555,7 +1555,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, NodeItem(item) => { match item.node { ItemStatic(ref t, _, _) | ItemConst(ref t, _) => { - ccx.icx(&()).to_ty(&ExplicitRscope, &t) + ccx.icx(&()).to_ty(&ElidableRscope::new(ty::ReStatic), &t) } ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl, diff --git a/src/test/compile-fail/regions-in-consts.rs b/src/test/compile-fail/regions-in-consts.rs deleted file mode 100644 index 8d0829a4cff..00000000000 --- a/src/test/compile-fail/regions-in-consts.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -static c_y: &isize = &22; //~ ERROR missing lifetime specifier -static c_z: &'static isize = &22; - -fn main() { -} diff --git a/src/test/compile-fail/rfc1623.rs b/src/test/compile-fail/rfc1623.rs new file mode 100644 index 00000000000..1d8fc7fe111 --- /dev/null +++ b/src/test/compile-fail/rfc1623.rs @@ -0,0 +1,101 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { + a +} + +// the boundaries of elision +static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = &(non_elidable as fn(&u8, &u8) -> &u8); +//~^ ERROR missing lifetime specifier [E0106] + +struct SomeStruct<'x, 'y, 'z: 'x> { + foo: &'x Foo<'z>, + bar: &'x Bar<'z>, + f: &'y for<'a, 'b: 'a> Fn(&'a Foo<'b>) -> &'a Bar<'b>, +} + +fn id(t: T) -> T { + t +} + +static SOME_STRUCT: &SomeStruct = SomeStruct { + foo: &Foo { bools: &[false, true] }, + bar: &Bar { bools: &[true, true] }, + f: &id, +}; + +// very simple test for a 'static static with default lifetime +static STATIC_STR: &'static str = "&'static str"; +const CONST_STR: &'static str = "&'static str"; + +// this should be the same as without default: +static EXPLICIT_STATIC_STR: &'static str = "&'static str"; +const EXPLICIT_CONST_STR: &'static str = "&'static str"; + +// a function that elides to an unbound lifetime for both in- and output +fn id_u8_slice(arg: &[u8]) -> &[u8] { + arg +} + +// one with a function, argument elided +static STATIC_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); +const CONST_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); + +// this should be the same as without elision +static STATIC_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); +const CONST_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); + +// another function that elides, each to a different unbound lifetime +fn multi_args(a: &u8, b: &u8, c: &u8) {} + +static STATIC_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); +const CONST_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); + +struct Foo<'a> { + bools: &'a [bool], +} + +static STATIC_FOO: Foo<'static> = Foo { bools: &[true, false] }; +const CONST_FOO: Foo<'static> = Foo { bools: &[true, false] }; + +type Bar<'a> = Foo<'a>; + +static STATIC_BAR: Bar<'static> = Bar { bools: &[true, false] }; +const CONST_BAR: Bar<'static> = Bar { bools: &[true, false] }; + +type Baz<'a> = fn(&'a [u8]) -> Option; + +fn baz(e: &[u8]) -> Option { + e.first().map(|x| *x) +} + +static STATIC_BAZ: &'static Baz<'static> = &(baz as Baz); +const CONST_BAZ: &'static Baz<'static> = &(baz as Baz); + +static BYTES: &'static [u8] = &[1, 2, 3]; + +fn main() { + let x = &[1u8, 2, 3]; + let y = x; + + // this works, so lifetime < `'static` is valid + assert_eq!(Some(1), STATIC_BAZ(y)); + assert_eq!(Some(1), CONST_BAZ(y)); + + let y = &[1u8, 2, 3]; + + STATIC_BAZ(BYTES); // BYTES has static lifetime + CONST_BAZ(y); // interestingly this does not get reported +} diff --git a/src/test/compile-fail/rfc1623.rs.bk b/src/test/compile-fail/rfc1623.rs.bk new file mode 100644 index 00000000000..abdcc02de76 --- /dev/null +++ b/src/test/compile-fail/rfc1623.rs.bk @@ -0,0 +1,98 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { a } + +// the boundaries of elision +static NON_ELIDABLE_FN : &fn(&u8, &u8) -> &u8 = +//~^ ERROR: missing lifetime specifier + &(non_elidable as fn(&u8, &u8) -> &u8); + +struct SomeStruct<'x, 'y, 'z: 'x> { + foo: &'x Foo<'z>, + bar: &'x Bar<'z>, + f: &'y for<'a, 'b: 'a> Fn(&'a Foo<'b>) -> &'a Bar<'b>, +} + +fn id(t: T) -> T { t } + +static SOME_STRUCT : &SomeStruct = SomeStruct { + foo: &Foo { bools: &[false, true] }, + bar: &Bar { bools: &[true, true] }, + f: &id, +}; + +// very simple test for a 'static static with default lifetime +static STATIC_STR : &'static str = "&'static str"; +const CONST_STR : &'static str = "&'static str"; + +// this should be the same as without default: +static EXPLICIT_STATIC_STR : &'static str = "&'static str"; +const EXPLICIT_CONST_STR : &'static str = "&'static str"; + +// a function that elides to an unbound lifetime for both in- and output +fn id_u8_slice(arg: &[u8]) -> &[u8] { arg } + +// one with a function, argument elided +static STATIC_SIMPLE_FN : &'static fn(&[u8]) -> &[u8] = + &(id_u8_slice as fn(&[u8]) -> &[u8]); +const CONST_SIMPLE_FN : &'static fn(&[u8]) -> &[u8] = + &(id_u8_slice as fn(&[u8]) -> &[u8]); + +// this should be the same as without elision +static STATIC_NON_ELIDED_fN : &'static for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); +const CONST_NON_ELIDED_fN : &'static for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); + +// another function that elides, each to a different unbound lifetime +fn multi_args(a: &u8, b: &u8, c: &u8) { } + +static STATIC_MULTI_FN : &'static fn(&u8, &u8, &u8) = + &(multi_args as fn(&u8, &u8, &u8)); +const CONST_MULTI_FN : &'static fn(&u8, &u8, &u8) = + &(multi_args as fn(&u8, &u8, &u8)); + +struct Foo<'a> { + bools: &'a [bool] +} + +static STATIC_FOO : Foo<'static> = Foo { bools: &[true, false] }; +const CONST_FOO : Foo<'static> = Foo { bools: &[true, false] }; + +type Bar<'a> = Foo<'a>; + +static STATIC_BAR : Bar<'static> = Bar { bools: &[true, false] }; +const CONST_BAR : Bar<'static> = Bar { bools: &[true, false] }; + +type Baz<'a> = fn(&'a [u8]) -> Option; + +fn baz(e: &[u8]) -> Option { e.first().map(|x| *x) } + +static STATIC_BAZ : &'static Baz<'static> = &(baz as Baz); +const CONST_BAZ : &'static Baz<'static> = &(baz as Baz); + +static BYTES : &'static [u8] = &[1, 2, 3]; + +fn main() { + let x = &[1u8, 2, 3]; + let y = x; + + //this works, so lifetime < `'static` is valid + assert_eq!(Some(1), STATIC_BAZ(y)); + assert_eq!(Some(1), CONST_BAZ(y)); + + let y = &[1u8, 2, 3]; + //^~ ERROR: borrowed values does not live long enough + STATIC_BAZ(BYTES); // BYTES has static lifetime + CONST_BAZ(y); // This forces static lifetime, which y has not +} diff --git a/src/test/run-pass/rfc1623.rs b/src/test/run-pass/rfc1623.rs new file mode 100644 index 00000000000..17453933c8a --- /dev/null +++ b/src/test/run-pass/rfc1623.rs @@ -0,0 +1,81 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +// very simple test for a 'static static with default lifetime +static STATIC_STR: &str = "&'static str"; +const CONST_STR: &str = "&'static str"; + +// this should be the same as without default: +static EXPLICIT_STATIC_STR: &'static str = "&'static str"; +const EXPLICIT_CONST_STR: &'static str = "&'static str"; + +// a function that elides to an unbound lifetime for both in- and output +fn id_u8_slice(arg: &[u8]) -> &[u8] { + arg +} + +// one with a function, argument elided +static STATIC_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); +const CONST_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); + +// this should be the same as without elision +static STATIC_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); +const CONST_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); + +// another function that elides, each to a different unbound lifetime +fn multi_args(a: &u8, b: &u8, c: &u8) {} + +static STATIC_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); +const CONST_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); + +struct Foo<'a> { + bools: &'a [bool], +} + +static STATIC_FOO: Foo = Foo { bools: &[true, false] }; +const CONST_FOO: Foo = Foo { bools: &[true, false] }; + +type Bar<'a> = Foo<'a>; + +static STATIC_BAR: Bar = Bar { bools: &[true, false] }; +const CONST_BAR: Bar = Bar { bools: &[true, false] }; + +type Baz<'a> = fn(&'a [u8]) -> Option; + +fn baz(e: &[u8]) -> Option { + e.first().map(|x| *x) +} + +static STATIC_BAZ: &Baz = &(baz as Baz); +const CONST_BAZ: &Baz = &(baz as Baz); + +static BYTES: &[u8] = &[1, 2, 3]; + +fn main() { + // make sure that the lifetime is actually elided (and not defaulted) + let x = &[1u8, 2, 3]; + STATIC_SIMPLE_FN(x); + CONST_SIMPLE_FN(x); + + STATIC_BAZ(BYTES); // neees static lifetime + CONST_BAZ(BYTES); + + // make sure this works with different lifetimes + let a = &1; + { + let b = &2; + let c = &3; + CONST_MULTI_FN(a, b, c); + } +} diff --git a/src/test/run-pass/rfc1623.rs.bk b/src/test/run-pass/rfc1623.rs.bk new file mode 100644 index 00000000000..0915118ca27 --- /dev/null +++ b/src/test/run-pass/rfc1623.rs.bk @@ -0,0 +1,81 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +// very simple test for a 'static static with default lifetime +static STATIC_STR : &str = "&'static str"; +const CONST_STR : &str = "&'static str"; + +// this should be the same as without default: +static EXPLICIT_STATIC_STR : &'static str = "&'static str"; +const EXPLICIT_CONST_STR : &'static str = "&'static str"; + +// a function that elides to an unbound lifetime for both in- and output +fn id_u8_slice(arg: &[u8]) -> &[u8] { arg } + +// one with a function, argument elided +static STATIC_SIMPLE_FN : &fn(&[u8]) -> &[u8] = + &(id_u8_slice as fn(&[u8]) -> &[u8]); +const CONST_SIMPLE_FN : &fn(&[u8]) -> &[u8] = + &(id_u8_slice as fn(&[u8]) -> &[u8]); + +// this should be the same as without elision +static STATIC_NON_ELIDED_fN : &for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); +const CONST_NON_ELIDED_fN : &for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); + +// another function that elides, each to a different unbound lifetime +fn multi_args(a: &u8, b: &u8, c: &u8) { } + +static STATIC_MULTI_FN : &fn(&u8, &u8, &u8) = + &(multi_args as fn(&u8, &u8, &u8)); +const CONST_MULTI_FN : &fn(&u8, &u8, &u8) = + &(multi_args as fn(&u8, &u8, &u8)); + +struct Foo<'a> { + bools: &'a [bool] +} + +static STATIC_FOO : Foo = Foo { bools: &[true, false] }; +const CONST_FOO : Foo = Foo { bools: &[true, false] }; + +type Bar<'a> = Foo<'a>; + +static STATIC_BAR : Bar = Bar { bools: &[true, false] }; +const CONST_BAR : Bar = Bar { bools: &[true, false] }; + +type Baz<'a> = fn(&'a [u8]) -> Option; + +fn baz(e: &[u8]) -> Option { e.first().map(|x| *x) } + +static STATIC_BAZ : &Baz = &(baz as Baz); +const CONST_BAZ : &Baz = &(baz as Baz); + +static BYTES : &[u8] = &[1, 2, 3]; + +fn main() { + // make sure that the lifetime is actually elided (and not defaulted) + let x = &[1u8, 2, 3]; + STATIC_SIMPLE_FN(x); + CONST_SIMPLE_FN(x); + + STATIC_BAZ(BYTES); // neees static lifetime + CONST_BAZ(BYTES); + + // make sure this works with different lifetimes + let a = &1; + { + let b = &2; + let c = &3; + CONST_MULTI_FN(a, b, c); + } +}