about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-10 00:07:08 +0000
committerbors <bors@rust-lang.org>2014-10-10 00:07:08 +0000
commitf9fc49c06e5c71a8d63d6120e1a92b6445fb501d (patch)
tree8a7c52db87b4ff8d5a7fa97dc44fb9ac10b92626 /src/libsyntax
parent8b12fb326b50c40c7b5acadb4403c7021fedb272 (diff)
parent0b517117b3ac9c4981bbe00a529e48e4019554d1 (diff)
downloadrust-f9fc49c06e5c71a8d63d6120e1a92b6445fb501d.tar.gz
rust-f9fc49c06e5c71a8d63d6120e1a92b6445fb501d.zip
auto merge of #17853 : alexcrichton/rust/issue-17718, r=pcwalton
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]
Closes #17718 

[rfc]: https://github.com/rust-lang/rfcs/pull/246
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/abi.rs4
-rw-r--r--src/libsyntax/ast.rs11
-rw-r--r--src/libsyntax/ast_map/mod.rs1
-rw-r--r--src/libsyntax/ast_util.rs14
-rw-r--r--src/libsyntax/codemap.rs4
-rw-r--r--src/libsyntax/ext/build.rs16
-rw-r--r--src/libsyntax/ext/bytes.rs23
-rw-r--r--src/libsyntax/fold.rs3
-rw-r--r--src/libsyntax/parse/parser.rs22
-rw-r--r--src/libsyntax/parse/token.rs16
-rw-r--r--src/libsyntax/print/pprust.rs18
-rw-r--r--src/libsyntax/test.rs9
-rw-r--r--src/libsyntax/visit.rs3
13 files changed, 82 insertions, 62 deletions
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index 3a02d74edff..03325ad4706 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -48,9 +48,9 @@ pub enum Architecture {
 }
 
 #[allow(non_uppercase_statics)]
-static IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint));
+const IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint));
 #[allow(non_uppercase_statics)]
-static ArmBits: u32 = (1 << (Arm as uint));
+const ArmBits: u32 = (1 << (Arm as uint));
 
 pub struct AbiData {
     abi: Abi,
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 0a87c0a344e..274bb2e39e0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -104,8 +104,8 @@ impl PartialEq for Ident {
 // this uint is a reference to a table stored in thread-local
 // storage.
 pub type SyntaxContext = u32;
-pub static EMPTY_CTXT : SyntaxContext = 0;
-pub static ILLEGAL_CTXT : SyntaxContext = 1;
+pub const EMPTY_CTXT : SyntaxContext = 0;
+pub const ILLEGAL_CTXT : SyntaxContext = 1;
 
 /// A name is a part of an identifier, representing a string or gensym. It's
 /// the result of interning.
@@ -198,13 +198,13 @@ pub struct DefId {
 
 /// Item definitions in the currently-compiled crate would have the CrateNum
 /// LOCAL_CRATE in their DefId.
-pub static LOCAL_CRATE: CrateNum = 0;
-pub static CRATE_NODE_ID: NodeId = 0;
+pub const LOCAL_CRATE: CrateNum = 0;
+pub const CRATE_NODE_ID: NodeId = 0;
 
 /// When parsing and doing expansions, we initially give all AST nodes this AST
 /// node value. Then later, in the renumber pass, we renumber them to have
 /// small, positive ids.
-pub static DUMMY_NODE_ID: NodeId = -1;
+pub const DUMMY_NODE_ID: NodeId = -1;
 
 /// The AST represents all type param bounds as types.
 /// typeck::collect::compute_bounds matches these against
@@ -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/codemap.rs b/src/libsyntax/codemap.rs
index dda41070431..5d96cc359c2 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -96,7 +96,7 @@ pub struct Span {
     pub expn_id: ExpnId
 }
 
-pub static DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION };
+pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION };
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Spanned<T> {
@@ -227,7 +227,7 @@ pub struct ExpnInfo {
 #[deriving(PartialEq, Eq, Clone, Show, Hash, Encodable, Decodable)]
 pub struct ExpnId(u32);
 
-pub static NO_EXPANSION: ExpnId = ExpnId(-1);
+pub const NO_EXPANSION: ExpnId = ExpnId(-1);
 
 impl ExpnId {
     pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
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/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
index 3c9e40d850b..a93295815e0 100644
--- a/src/libsyntax/ext/bytes.rs
+++ b/src/libsyntax/ext/bytes.rs
@@ -104,19 +104,14 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
         return DummyResult::expr(sp);
     }
 
-    let e = cx.expr_vec_slice(sp, bytes);
-    let ty = cx.ty(sp, ast::TyVec(cx.ty_ident(sp, cx.ident_of("u8"))));
-    let lifetime = cx.lifetime(sp, cx.ident_of("'static").name);
-    let item = cx.item_static(sp,
-                              cx.ident_of("BYTES"),
-                              cx.ty_rptr(sp,
-                                         ty,
-                                         Some(lifetime),
-                                         ast::MutImmutable),
-                              ast::MutImmutable,
-                              e);
-    let e = cx.expr_block(cx.block(sp,
-                                   vec!(cx.stmt_item(sp, item)),
-                                   Some(cx.expr_ident(sp, cx.ident_of("BYTES")))));
+    let len = bytes.len();
+    let e = cx.expr_vec(sp, bytes);
+    let ty = cx.ty(sp, ast::TyFixedLengthVec(cx.ty_ident(sp, cx.ident_of("u8")),
+                                             cx.expr_uint(sp, len)));
+    let item = cx.item_static(sp, cx.ident_of("BYTES"), ty, ast::MutImmutable, e);
+    let ret = cx.expr_ident(sp, cx.ident_of("BYTES"));
+    let ret = cx.expr_addr_of(sp, ret);
+    let e = cx.expr_block(cx.block(sp, vec![cx.stmt_item(sp, item)],
+                                   Some(ret)));
     MacExpr::new(e)
 }
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..e7f40cf0722 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};
@@ -91,10 +91,10 @@ use std::iter;
 
 bitflags! {
     flags Restrictions: u8 {
-        static UNRESTRICTED                  = 0b0000,
-        static RESTRICTION_STMT_EXPR         = 0b0001,
-        static RESTRICTION_NO_BAR_OP         = 0b0010,
-        static RESTRICTION_NO_STRUCT_LITERAL = 0b0100
+        const UNRESTRICTED                  = 0b0000,
+        const RESTRICTION_STMT_EXPR         = 0b0001,
+        const RESTRICTION_NO_BAR_OP         = 0b0010,
+        const RESTRICTION_NO_STRUCT_LITERAL = 0b0100
     }
 }
 
@@ -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/parse/token.rs b/src/libsyntax/parse/token.rs
index 7cc78891d91..fa6b0c5ad4a 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -385,13 +385,13 @@ macro_rules! declare_special_idents_and_keywords {(
         use ast::{Ident, Name};
         $(
             #[allow(non_uppercase_statics)]
-            pub static $si_static: Ident = Ident { name: Name($si_name), ctxt: 0 };
+            pub const $si_static: Ident = Ident { name: Name($si_name), ctxt: 0 };
          )*
     }
 
     pub mod special_names {
         use ast::Name;
-        $( #[allow(non_uppercase_statics)] pub static $si_static: Name =  Name($si_name); )*
+        $( #[allow(non_uppercase_statics)] pub const $si_static: Name =  Name($si_name); )*
     }
 
     /**
@@ -432,13 +432,13 @@ macro_rules! declare_special_idents_and_keywords {(
 }}
 
 // If the special idents get renumbered, remember to modify these two as appropriate
-pub static SELF_KEYWORD_NAME: Name = Name(SELF_KEYWORD_NAME_NUM);
-static STATIC_KEYWORD_NAME: Name = Name(STATIC_KEYWORD_NAME_NUM);
-static SUPER_KEYWORD_NAME: Name = Name(SUPER_KEYWORD_NAME_NUM);
+pub const SELF_KEYWORD_NAME: Name = Name(SELF_KEYWORD_NAME_NUM);
+const STATIC_KEYWORD_NAME: Name = Name(STATIC_KEYWORD_NAME_NUM);
+const SUPER_KEYWORD_NAME: Name = Name(SUPER_KEYWORD_NAME_NUM);
 
-pub static SELF_KEYWORD_NAME_NUM: u32 = 1;
-static STATIC_KEYWORD_NAME_NUM: u32 = 2;
-static SUPER_KEYWORD_NAME_NUM: u32 = 3;
+pub const SELF_KEYWORD_NAME_NUM: u32 = 1;
+const STATIC_KEYWORD_NAME_NUM: u32 = 2;
+const SUPER_KEYWORD_NAME_NUM: u32 = 3;
 
 // NB: leaving holes in the ident table is bad! a different ident will get
 // interned with the id from the hole, but it will be between the min and max
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c3a3848019a..e1a2b2aeefe 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -90,10 +90,10 @@ pub fn rust_printer_annotated<'a>(writer: Box<io::Writer+'static>,
 }
 
 #[allow(non_uppercase_statics)]
-pub static indent_unit: uint = 4u;
+pub const indent_unit: uint = 4u;
 
 #[allow(non_uppercase_statics)]
-pub static default_columns: uint = 78u;
+pub const default_columns: uint = 78u;
 
 /// Requires you to pass an input filename and reader so that
 /// it can scan the input text for comments and literals to
@@ -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);
         }