about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-10-06 08:17:01 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-10-09 09:44:50 -0700
commit90d03d792669fed99b659d1efbe835d4b9b8873c (patch)
tree515a528e1fadef2239236c08d2c11018ea6ebd11 /src/libsyntax
parenta89ad587101b4603c8334f344d303ae6eaa99827 (diff)
downloadrust-90d03d792669fed99b659d1efbe835d4b9b8873c.tar.gz
rust-90d03d792669fed99b659d1efbe835d4b9b8873c.zip
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.

The semantics of these three kinds of globals are:

* A `const` does not represent a memory location, but only a value. Constants
  are translated as rvalues, which means that their values are directly inlined
  at usage location (similar to a #define in C/C++). Constant values are, well,
  constant, and can not be modified. Any "modification" is actually a
  modification to a local value on the stack rather than the actual constant
  itself.

  Almost all values are allowed inside constants, whether they have interior
  mutability or not. There are a few minor restrictions listed in the RFC, but
  they should in general not come up too often.

* A `static` now always represents a memory location (unconditionally). Any
  references to the same `static` are actually a reference to the same memory
  location. Only values whose types ascribe to `Sync` are allowed in a `static`.
  This restriction is in place because many threads may access a `static`
  concurrently. Lifting this restriction (and allowing unsafe access) is a
  future extension not implemented at this time.

* A `static mut` continues to always represent a memory location. All references
  to a `static mut` continue to be `unsafe`.

This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:

* Statics may no longer be used in patterns. Statics now always represent a
  memory location, which can sometimes be modified. To fix code, repurpose the
  matched-on-`static` to a `const`.

      static FOO: uint = 4;
      match n {
          FOO => { /* ... */ }
          _ => { /* ... */ }
      }

  change this code to:

      const FOO: uint = 4;
      match n {
          FOO => { /* ... */ }
          _ => { /* ... */ }
      }

* Statics may no longer refer to other statics by value. Due to statics being
  able to change at runtime, allowing them to reference one another could
  possibly lead to confusing semantics. If you are in this situation, use a
  constant initializer instead. Note, however, that statics may reference other
  statics by address, however.

* Statics may no longer be used in constant expressions, such as array lengths.
  This is due to the same restrictions as listed above. Use a `const` instead.

[breaking-change]

[rfc]: https://github.com/rust-lang/rfcs/pull/246
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/ast_map/mod.rs1
-rw-r--r--src/libsyntax/ast_util.rs14
-rw-r--r--src/libsyntax/ext/build.rs16
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/parser.rs14
-rw-r--r--src/libsyntax/print/pprust.rs14
-rw-r--r--src/libsyntax/test.rs9
-rw-r--r--src/libsyntax/visit.rs3
9 files changed, 50 insertions, 25 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 0a87c0a344e..c47d6b0fc9d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1309,6 +1309,7 @@ pub struct Item {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Item_ {
     ItemStatic(P<Ty>, Mutability, P<Expr>),
+    ItemConst(P<Ty>, P<Expr>),
     ItemFn(P<FnDecl>, FnStyle, Abi, Generics, P<Block>),
     ItemMod(Mod),
     ItemForeignMod(ForeignMod),
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 257bfc632d8..2d0cea2fefc 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -1018,6 +1018,7 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
             let path_str = map.path_to_str_with_ident(id, item.ident);
             let item_str = match item.node {
                 ItemStatic(..) => "static",
+                ItemConst(..) => "const",
                 ItemFn(..) => "fn",
                 ItemMod(..) => "mod",
                 ItemForeignMod(..) => "foreign mod",
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index f746e1f1482..f51c2985f0b 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -12,8 +12,6 @@ use abi::Abi;
 use ast::*;
 use ast;
 use ast_util;
-use attr::{InlineNever, InlineNone};
-use attr;
 use codemap;
 use codemap::Span;
 use owned_slice::OwnedSlice;
@@ -706,18 +704,6 @@ pub fn lit_is_str(lit: &Lit) -> bool {
     }
 }
 
-/// Returns true if the static with the given mutability and attributes
-/// has a significant address and false otherwise.
-pub fn static_has_significant_address(mutbl: ast::Mutability,
-                                              attrs: &[ast::Attribute])
-                                              -> bool {
-    if mutbl == ast::MutMutable {
-        return true
-    }
-    let inline = attr::find_inline_attr(attrs);
-    inline == InlineNever || inline == InlineNone
-}
-
 /// Macro invocations are guaranteed not to occur after expansion is complete.
 /// Extracting fields of a method requires a dynamic check to make sure that it's
 /// not a macro invocation. This check is guaranteed to succeed, assuming
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 1fdb6dd505f..87983e1aea3 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -250,6 +250,13 @@ pub trait AstBuilder {
                    expr: P<ast::Expr>)
                    -> P<ast::Item>;
 
+    fn item_const(&self,
+                   span: Span,
+                   name: Ident,
+                   ty: P<ast::Ty>,
+                   expr: P<ast::Expr>)
+                   -> P<ast::Item>;
+
     fn item_ty_poly(&self,
                     span: Span,
                     name: Ident,
@@ -1033,6 +1040,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.item(span, name, Vec::new(), ast::ItemStatic(ty, mutbl, expr))
     }
 
+    fn item_const(&self,
+                  span: Span,
+                  name: Ident,
+                  ty: P<ast::Ty>,
+                  expr: P<ast::Expr>)
+                  -> P<ast::Item> {
+        self.item(span, name, Vec::new(), ast::ItemConst(ty, expr))
+    }
+
     fn item_ty_poly(&self, span: Span, name: Ident, ty: P<ast::Ty>,
                     generics: Generics) -> P<ast::Item> {
         self.item(span, name, Vec::new(), ast::ItemTy(ty, generics))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 84de6c3b913..32e226361e9 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -903,6 +903,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
         ItemStatic(t, m, e) => {
             ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
         }
+        ItemConst(t, e) => {
+            ItemConst(folder.fold_ty(t), folder.fold_expr(e))
+        }
         ItemFn(decl, fn_style, abi, generics, body) => {
             ItemFn(
                 folder.fold_fn_decl(decl),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9bfb593786e..e73ffd7e581 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -32,7 +32,7 @@ use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
 use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
-use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
+use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
 use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
 use ast::{LifetimeDef, Lit, Lit_};
 use ast::{LitBool, LitChar, LitByte, LitBinary};
@@ -4739,14 +4739,18 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_item_const(&mut self, m: Mutability) -> ItemInfo {
+    fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo {
         let id = self.parse_ident();
         self.expect(&token::COLON);
         let ty = self.parse_ty(true);
         self.expect(&token::EQ);
         let e = self.parse_expr();
         self.commit_expr_expecting(&*e, token::SEMI);
-        (id, ItemStatic(ty, m, e), None)
+        let item = match m {
+            Some(m) => ItemStatic(ty, m, e),
+            None => ItemConst(ty, e),
+        };
+        (id, item, None)
     }
 
     /// Parse a `mod <foo> { ... }` or `mod <foo>;` item
@@ -5296,7 +5300,7 @@ impl<'a> Parser<'a> {
             // STATIC ITEM
             self.bump();
             let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable};
-            let (ident, item_, extra_attrs) = self.parse_item_const(m);
+            let (ident, item_, extra_attrs) = self.parse_item_const(Some(m));
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
@@ -5314,7 +5318,7 @@ impl<'a> Parser<'a> {
                 self.span_err(last_span, "const globals cannot be mutable, \
                                           did you mean to declare a static?");
             }
-            let (ident, item_, extra_attrs) = self.parse_item_const(MutImmutable);
+            let (ident, item_, extra_attrs) = self.parse_item_const(None);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c3a3848019a..321b00db47e 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -757,6 +757,20 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the outer cbox
             }
+            ast::ItemConst(ref ty, ref expr) => {
+                try!(self.head(visibility_qualified(item.vis,
+                                                    "const").as_slice()));
+                try!(self.print_ident(item.ident));
+                try!(self.word_space(":"));
+                try!(self.print_type(&**ty));
+                try!(space(&mut self.s));
+                try!(self.end()); // end the head-ibox
+
+                try!(self.word_space("="));
+                try!(self.print_expr(&**expr));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the outer cbox
+            }
             ast::ItemFn(ref decl, fn_style, abi, ref typarams, ref body) => {
                 try!(self.print_fn(
                     &**decl,
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 3f5b524a9b5..9fb5742bb9b 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -493,11 +493,10 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
                                   Some(static_lt),
                                   ast::MutImmutable);
     // static TESTS: $static_type = &[...];
-    ecx.item_static(sp,
-                    ecx.ident_of("TESTS"),
-                    static_type,
-                    ast::MutImmutable,
-                    test_descs)
+    ecx.item_const(sp,
+                   ecx.ident_of("TESTS"),
+                   static_type,
+                   test_descs)
 }
 
 fn is_test_crate(krate: &ast::Crate) -> bool {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 249f87d3102..5c7b144f4ab 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -211,7 +211,8 @@ pub fn walk_trait_ref_helper<'v,V>(visitor: &mut V, trait_ref: &'v TraitRef)
 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
     visitor.visit_ident(item.span, item.ident);
     match item.node {
-        ItemStatic(ref typ, _, ref expr) => {
+        ItemStatic(ref typ, _, ref expr) |
+        ItemConst(ref typ, ref expr) => {
             visitor.visit_ty(&**typ);
             visitor.visit_expr(&**expr);
         }