Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Add const globals to the language #17853

Merged
merged 24 commits into from
Oct 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a89ad58
rustc: Reformat check_const with modern style
alexcrichton Oct 7, 2014
90d03d7
rustc: Add `const` globals to the language
alexcrichton Oct 6, 2014
4d87af9
core: Convert statics to constants
alexcrichton Oct 6, 2014
1a43377
sync: Convert statics to constants
alexcrichton Oct 6, 2014
34d66de
unicode: Make statics legal
alexcrichton Oct 6, 2014
abb3d3e
collections: Convert statics to constants
alexcrichton Oct 6, 2014
3370053
libc: Convert all statics to constant
alexcrichton Oct 6, 2014
d9874bf
rand: Convert statics to constants
alexcrichton Oct 6, 2014
ab5935c
std: Convert statics to constants
alexcrichton Oct 6, 2014
6d4cf37
term: Convert statics to constants
alexcrichton Oct 6, 2014
abb1b2a
alloc: Convert statics to constants
alexcrichton Oct 6, 2014
a64bb66
regex: Convert statics to constants
alexcrichton Oct 6, 2014
6532a8c
log: Convert statics to constants
alexcrichton Oct 6, 2014
8ccb616
native: Convert statics to constants
alexcrichton Oct 6, 2014
edf8841
syntax: Convert statics to constants
alexcrichton Oct 6, 2014
d3eaf32
serialize: Convert statics to constants
alexcrichton Oct 6, 2014
b8fb0cf
rustrt: Convert statics to constants
alexcrichton Oct 6, 2014
831f909
rustc: Convert statics to constants
alexcrichton Oct 7, 2014
1bfe450
num: Convert statics to constants
alexcrichton Oct 7, 2014
01d58fe
rustdoc: Implement constant documentation
alexcrichton Oct 7, 2014
9c09c94
syntax: Tweak the return value of bytes!()
alexcrichton Oct 7, 2014
d03a4b0
test: Convert statics to constants
alexcrichton Oct 7, 2014
a3e8f41
doc: Document constants in the reference
alexcrichton Oct 7, 2014
0b51711
Test fixes and rebase conflicts
alexcrichton Oct 9, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 65 additions & 19 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1383,44 +1383,87 @@ a = Cat { name: "Spotty".to_string(), weight: 2.7 };
In this example, `Cat` is a _struct-like enum variant_,
whereas `Dog` is simply called an enum variant.

### Static items
### Constant items

```{.ebnf .gram}
static_item : "static" ident ':' type '=' expr ';' ;
const_item : "const" ident ':' type '=' expr ';' ;
```

A *static item* is a named _constant value_ stored in the global data section
of a crate. Immutable static items are stored in the read-only data section.
The constant value bound to a static item is, like all constant values,
evaluated at compile time. Static items have the `static` lifetime, which
outlives all other lifetimes in a Rust program. Only values stored in the
global data section (such as string constants and static items) can have the
`static` lifetime; dynamically constructed values cannot safely be assigned the
`static` lifetime. Static items are declared with the `static` keyword. A
static item must have a _constant expression_ giving its definition.
A *constant item* is a named _constant value_ which is not associated with a
specific memory location in the program. Constants are essentially inlined
wherever they are used, meaning that they are copied directly into the relevant
context when used. References to the same constant are not necessarily
guaranteed to refer to the same memory address.

Constant values must not have destructors, and otherwise permit most forms of
data. Constants may refer to the address of other constants, in which case the
address will have the `static` lifetime. The compiler is, however, still at
liberty to translate the constant many times, so the address referred to may not
be stable.

Static items must be explicitly typed. The type may be `bool`, `char`,
a number, or a type derived from those primitive types. The derived types are
references with the `static` lifetime, fixed-size arrays, tuples, and structs.
Constants must be explicitly typed. The type may be `bool`, `char`, a number, or
a type derived from those primitive types. The derived types are references with
the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs.

```
static BIT1: uint = 1 << 0;
static BIT2: uint = 1 << 1;
const BIT1: uint = 1 << 0;
const BIT2: uint = 1 << 1;

static BITS: [uint, ..2] = [BIT1, BIT2];
static STRING: &'static str = "bitstring";
const BITS: [uint, ..2] = [BIT1, BIT2];
const STRING: &'static str = "bitstring";

struct BitsNStrings<'a> {
mybits: [uint, ..2],
mystring: &'a str
}

static BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
mybits: BITS,
mystring: STRING
};
```

### Static items

```{.ebnf .gram}
static_item : "static" ident ':' type '=' expr ';' ;
```

A *static item* is similar to a *constant*, except that it represents a precise
memory location in the program. A static is never "inlined" at the usage site,
and all references to it refer to the same memory location. Static items have
the `static` lifetime, which outlives all other lifetimes in a Rust program.
Static items may be placed in read-only memory if they do not contain any
interior mutability.

Statics may contain interior mutability through the `UnsafeCell` language item.
All access to a static is safe, but there are a number of restrictions on
statics:

* Statics may not contain any destructors.
* The types of static values must ascribe to `Sync` to allow threadsafe access.
* Statics may not refer to other statics by value, only by reference.
* Constants cannot refer to statics.

Constants should in general be preferred over statics, unless large amounts of
data are being stored, or single-address and mutability properties are required.

```
use std::sync::atomic;

// Note that INIT_ATOMIC_UINT is a *const*, but it may be used to initialize a
// static. This static can be modified, so it is not placed in read-only memory.
static COUNTER: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;

// This table is a candidate to be placed in read-only memory.
static TABLE: &'static [uint] = &[1, 2, 3, /* ... */];

for slot in TABLE.iter() {
println!("{}", slot);
}
COUNTER.fetch_add(1, atomic::SeqCst);
```

#### Mutable statics

If a static item is declared with the `mut` keyword, then it is allowed to
Expand Down Expand Up @@ -1455,6 +1498,9 @@ unsafe fn bump_levels_unsafe2() -> uint {
}
```

Mutable statics have the same restrictions as normal statics, except that the
type of the value is not required to ascribe to `Sync`.

### Traits

A _trait_ describes a set of method types.
Expand Down
8 changes: 4 additions & 4 deletions src/etc/unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,14 @@ def emit_property_module(f, mod, tbl, emit_fn):
def emit_regex_module(f, cats, w_data):
f.write("pub mod regex {\n")
regex_class = "&'static [(char, char)]"
class_table = "&'static [(&'static str, %s)]" % regex_class
class_table = "&'static [(&'static str, &'static %s)]" % regex_class

emit_table(f, "UNICODE_CLASSES", cats, class_table,
pfun=lambda x: "(\"%s\",super::%s::%s_table)" % (x[0], x[1], x[0]))
pfun=lambda x: "(\"%s\",&super::%s::%s_table)" % (x[0], x[1], x[0]))

f.write(" pub static PERLD: %s = super::general_category::Nd_table;\n\n"
f.write(" pub static PERLD: &'static %s = &super::general_category::Nd_table;\n\n"
% regex_class)
f.write(" pub static PERLS: %s = super::property::White_Space_table;\n\n"
f.write(" pub static PERLS: &'static %s = &super::property::White_Space_table;\n\n"
% regex_class)

emit_table(f, "PERLW", w_data, regex_class)
Expand Down
2 changes: 1 addition & 1 deletion src/liballoc/heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub fn stats_print() {
///
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
/// non-zero-size memory allocations.
pub static EMPTY: *mut () = 0x1 as *mut ();
pub const EMPTY: *mut () = 0x1 as *mut ();

/// The allocator for unique pointers.
#[cfg(not(test))]
Expand Down
8 changes: 4 additions & 4 deletions src/libcollections/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ use slice::{Items, MutItems};
use slice;

// FIXME: #5244: need to manually update the TrieNode constructor
static SHIFT: uint = 4;
static SIZE: uint = 1 << SHIFT;
static MASK: uint = SIZE - 1;
static NUM_CHUNKS: uint = uint::BITS / SHIFT;
const SHIFT: uint = 4;
const SIZE: uint = 1 << SHIFT;
const MASK: uint = SIZE - 1;
const NUM_CHUNKS: uint = uint::BITS / SHIFT;

#[deriving(Clone)]
enum Child<T> {
Expand Down
8 changes: 4 additions & 4 deletions src/libcore/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,19 @@ pub enum Ordering {

/// An `AtomicBool` initialized to `false`
#[unstable = "may be renamed, pending conventions for static initalizers"]
pub static INIT_ATOMIC_BOOL: AtomicBool =
pub const INIT_ATOMIC_BOOL: AtomicBool =
AtomicBool { v: UnsafeCell { value: 0 }, nocopy: marker::NoCopy };
/// An `AtomicInt` initialized to `0`
#[unstable = "may be renamed, pending conventions for static initalizers"]
pub static INIT_ATOMIC_INT: AtomicInt =
pub const INIT_ATOMIC_INT: AtomicInt =
AtomicInt { v: UnsafeCell { value: 0 }, nocopy: marker::NoCopy };
/// An `AtomicUint` initialized to `0`
#[unstable = "may be renamed, pending conventions for static initalizers"]
pub static INIT_ATOMIC_UINT: AtomicUint =
pub const INIT_ATOMIC_UINT: AtomicUint =
AtomicUint { v: UnsafeCell { value: 0, }, nocopy: marker::NoCopy };

// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
static UINT_TRUE: uint = -1;
const UINT_TRUE: uint = -1;

#[stable]
impl AtomicBool {
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ pub struct RefCell<T> {
// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
static WRITING: BorrowFlag = -1;
const UNUSED: BorrowFlag = 0;
const WRITING: BorrowFlag = -1;

impl<T> RefCell<T> {
/// Create a new `RefCell` containing `value`
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static MAX_THREE_B: u32 = 0x10000u32;
*/

/// The highest valid code point
pub static MAX: char = '\U0010ffff';
pub const MAX: char = '\U0010ffff';

/// Converts from `u32` to a `char`
#[inline]
Expand Down
66 changes: 33 additions & 33 deletions src/libcore/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,29 @@ use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float;
use option::Option;

pub static RADIX: uint = 2u;
pub const RADIX: uint = 2u;

pub static MANTISSA_DIGITS: uint = 24u;
pub static DIGITS: uint = 6u;
pub const MANTISSA_DIGITS: uint = 24u;
pub const DIGITS: uint = 6u;

pub static EPSILON: f32 = 1.19209290e-07_f32;
pub const EPSILON: f32 = 1.19209290e-07_f32;

/// Smallest finite f32 value
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
pub const MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;
pub const MAX_VALUE: f32 = 3.40282347e+38_f32;

pub static MIN_EXP: int = -125;
pub static MAX_EXP: int = 128;
pub const MIN_EXP: int = -125;
pub const MAX_EXP: int = 128;

pub static MIN_10_EXP: int = -37;
pub static MAX_10_EXP: int = 38;
pub const MIN_10_EXP: int = -37;
pub const MAX_10_EXP: int = 38;

pub static NAN: f32 = 0.0_f32/0.0_f32;
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
pub const NAN: f32 = 0.0_f32/0.0_f32;
pub const INFINITY: f32 = 1.0_f32/0.0_f32;
pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32;

/// Various useful constants.
pub mod consts {
Expand All @@ -53,55 +53,55 @@ pub mod consts {
// of `Float`.

/// Archimedes' constant
pub static PI: f32 = 3.14159265358979323846264338327950288_f32;
pub const PI: f32 = 3.14159265358979323846264338327950288_f32;

/// pi * 2.0
pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;
pub const PI_2: f32 = 6.28318530717958647692528676655900576_f32;

/// pi/2.0
pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;

/// pi/3.0
pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;
pub const FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;

/// pi/4.0
pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;
pub const FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;

/// pi/6.0
pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;
pub const FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;

/// pi/8.0
pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;
pub const FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;

/// 1.0/pi
pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;

/// 2.0/pi
pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;

/// 2.0/sqrt(pi)
pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;

/// sqrt(2.0)
pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32;

/// 1.0/sqrt(2.0)
pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;

/// Euler's number
pub static E: f32 = 2.71828182845904523536028747135266250_f32;
pub const E: f32 = 2.71828182845904523536028747135266250_f32;

/// log2(e)
pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;
pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;

/// log10(e)
pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;
pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;

/// ln(2.0)
pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;
pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32;

/// ln(10.0)
pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}

impl Float for f32 {
Expand Down Expand Up @@ -143,8 +143,8 @@ impl Float for f32 {
/// is going to be tested, it is generally faster to use the specific
/// predicate instead.
fn classify(self) -> FPCategory {
static EXP_MASK: u32 = 0x7f800000;
static MAN_MASK: u32 = 0x007fffff;
const EXP_MASK: u32 = 0x7f800000;
const MAN_MASK: u32 = 0x007fffff;

let bits: u32 = unsafe { mem::transmute(self) };
match (bits & MAN_MASK, bits & EXP_MASK) {
Expand Down
Loading