diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-10-06 08:17:01 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-10-09 09:44:50 -0700 |
| commit | 90d03d792669fed99b659d1efbe835d4b9b8873c (patch) | |
| tree | 515a528e1fadef2239236c08d2c11018ea6ebd11 /src/libsyntax | |
| parent | a89ad587101b4603c8334f344d303ae6eaa99827 (diff) | |
| download | rust-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.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ast_map/mod.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 3 |
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); } |
