about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-09 21:35:30 -0700
committerGitHub <noreply@github.com>2016-09-09 21:35:30 -0700
commitf508ddc5470e65243c4f6c79fc72e8b8534e71a6 (patch)
treef35ca3c07625b270560b34acaf04d94f1e8b63aa
parent1284081d33d0e7856c6d242b3e311876c4eec048 (diff)
parent76a2f9f4542ccb15d6eb2426b162ce91094f04e2 (diff)
Auto merge of #36332 - llogiq:static_consts_feature, r=nikomatsakis
add static_in_const feature gate

also updates tests and deletes the spurious .bk files I inadvertently added last time.

r? @nikomatsakis
-rw-r--r--src/doc/reference.md3
-rw-r--r--src/librustc_typeck/collect.rs2
-rw-r--r--src/librustc_typeck/rscope.rs39
-rw-r--r--src/libsyntax/feature_gate.rs3
-rw-r--r--src/test/compile-fail/feature-gate-static-in-const.rs14
-rw-r--r--src/test/compile-fail/issue-24446.rs1
-rw-r--r--src/test/compile-fail/rfc1623.rs2
-rw-r--r--src/test/compile-fail/rfc1623.rs.bk98
-rw-r--r--src/test/run-pass/rfc1623.rs1
-rw-r--r--src/test/run-pass/rfc1623.rs.bk81
10 files changed, 62 insertions, 182 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index f29cdf6b080..b72c3743a69 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -2441,6 +2441,9 @@ The currently implemented features of the reference compiler are:
             into a Rust program. This capability, especially the signature for the
             annotated function, is subject to change.
 
+* `static_in_const` - Enables lifetime elision with a `'static` default for
+                      `const` and `static` item declarations.
+
 * `thread_local` - The usage of the `#[thread_local]` attribute is experimental
                    and should be seen as unstable. This attribute is used to
                    declare a `static` as being unique per-thread leveraging
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 082690149c9..7d111cdc415 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1567,7 +1567,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(&ElidableRscope::new(ty::ReStatic), &t)
+                        ccx.icx(&()).to_ty(&StaticRscope::new(&ccx.tcx), &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/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs
index f5b13c4207d..131ecfc6e0c 100644
--- a/src/librustc_typeck/rscope.rs
+++ b/src/librustc_typeck/rscope.rs
@@ -213,6 +213,45 @@ impl RegionScope for ElidableRscope {
     }
 }
 
+/// A scope that behaves as an ElidabeRscope with a `'static` default region
+/// that should also warn if the `static_in_const` feature is unset.
+#[derive(Copy, Clone)]
+pub struct StaticRscope<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>,
+}
+
+impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> StaticRscope<'a, 'gcx, 'tcx> {
+    /// create a new StaticRscope from a reference to the `TyCtxt`
+    pub fn new(tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>) -> Self {
+        StaticRscope { tcx: tcx }
+    }
+}
+
+impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> RegionScope for StaticRscope<'a, 'gcx, 'tcx> {
+    fn anon_regions(&self,
+                    span: Span,
+                    count: usize)
+                    -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
+        if !self.tcx.sess.features.borrow().static_in_const {
+            self.tcx
+                .sess
+                .struct_span_err(span,
+                                 "this needs a `'static` lifetime or the \
+                                 `static_in_const` feature, see #35897")
+                .emit();
+        }
+        Ok(vec![ty::ReStatic; count])
+    }
+
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        Some(self.base_object_lifetime_default(span))
+    }
+
+    fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
+        ty::ReStatic
+    }
+}
+
 /// A scope in which we generate anonymous, late-bound regions for
 /// omitted regions. This occurs in function signatures.
 pub struct BindingRscope {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index dd2956f706c..8b8a41fc204 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -295,6 +295,9 @@ declare_features! (
 
     // Allows untagged unions `union U { ... }`
     (active, untagged_unions, "1.13.0", Some(32836)),
+
+    // elide `'static` lifetimes in `static`s and `const`s
+    (active, static_in_const, "1.13.0", Some(35897)),
 );
 
 declare_features! (
diff --git a/src/test/compile-fail/feature-gate-static-in-const.rs b/src/test/compile-fail/feature-gate-static-in-const.rs
new file mode 100644
index 00000000000..c1fc7cdd06c
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-static-in-const.rs
@@ -0,0 +1,14 @@
+// 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.
+
+static FOO: &str = "this will work once static_in_const is stable";
+//~^ ERROR: this needs a `'static` lifetime or the `static_in_const` feature
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-24446.rs b/src/test/compile-fail/issue-24446.rs
index b9382520cf9..acd50bcf9e1 100644
--- a/src/test/compile-fail/issue-24446.rs
+++ b/src/test/compile-fail/issue-24446.rs
@@ -12,7 +12,6 @@ fn main() {
     static foo: Fn() -> u32 = || -> u32 {
         //~^ ERROR: mismatched types
         //~| ERROR: `std::ops::Fn() -> u32 + 'static: std::marker::Sized` is not satisfied
-
         0
     };
 }
diff --git a/src/test/compile-fail/rfc1623.rs b/src/test/compile-fail/rfc1623.rs
index 1d8fc7fe111..083cc218eec 100644
--- a/src/test/compile-fail/rfc1623.rs
+++ b/src/test/compile-fail/rfc1623.rs
@@ -7,7 +7,7 @@
 // <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.
-
+#![feature(static_in_const)]
 #![allow(dead_code)]
 
 fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
diff --git a/src/test/compile-fail/rfc1623.rs.bk b/src/test/compile-fail/rfc1623.rs.bk
deleted file mode 100644
index abdcc02de76..00000000000
--- a/src/test/compile-fail/rfc1623.rs.bk
+++ /dev/null
@@ -1,98 +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 <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.
-
-#![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 { 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<u8>;
-
-fn baz(e: &[u8]) -> Option<u8> { 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
index 17453933c8a..fc9143dc450 100644
--- a/src/test/run-pass/rfc1623.rs
+++ b/src/test/run-pass/rfc1623.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(static_in_const)]
 #![allow(dead_code)]
 
 // very simple test for a 'static static with default lifetime
diff --git a/src/test/run-pass/rfc1623.rs.bk b/src/test/run-pass/rfc1623.rs.bk
deleted file mode 100644
index 0915118ca27..00000000000
--- a/src/test/run-pass/rfc1623.rs.bk
+++ /dev/null
@@ -1,81 +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 <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.
-
-#![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<u8>;
-
-fn baz(e: &[u8]) -> Option<u8> { 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);
-    }
-}