Skip to content

Commit f9fc49c

Browse files
committed
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]: rust-lang/rfcs#246
2 parents 8b12fb3 + 0b51711 commit f9fc49c

File tree

193 files changed

+4052
-3272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

193 files changed

+4052
-3272
lines changed

src/doc/reference.md

+65-19
Original file line numberDiff line numberDiff line change
@@ -1383,44 +1383,87 @@ a = Cat { name: "Spotty".to_string(), weight: 2.7 };
13831383
In this example, `Cat` is a _struct-like enum variant_,
13841384
whereas `Dog` is simply called an enum variant.
13851385

1386-
### Static items
1386+
### Constant items
13871387

13881388
```{.ebnf .gram}
1389-
static_item : "static" ident ':' type '=' expr ';' ;
1389+
const_item : "const" ident ':' type '=' expr ';' ;
13901390
```
13911391

1392-
A *static item* is a named _constant value_ stored in the global data section
1393-
of a crate. Immutable static items are stored in the read-only data section.
1394-
The constant value bound to a static item is, like all constant values,
1395-
evaluated at compile time. Static items have the `static` lifetime, which
1396-
outlives all other lifetimes in a Rust program. Only values stored in the
1397-
global data section (such as string constants and static items) can have the
1398-
`static` lifetime; dynamically constructed values cannot safely be assigned the
1399-
`static` lifetime. Static items are declared with the `static` keyword. A
1400-
static item must have a _constant expression_ giving its definition.
1392+
A *constant item* is a named _constant value_ which is not associated with a
1393+
specific memory location in the program. Constants are essentially inlined
1394+
wherever they are used, meaning that they are copied directly into the relevant
1395+
context when used. References to the same constant are not necessarily
1396+
guaranteed to refer to the same memory address.
1397+
1398+
Constant values must not have destructors, and otherwise permit most forms of
1399+
data. Constants may refer to the address of other constants, in which case the
1400+
address will have the `static` lifetime. The compiler is, however, still at
1401+
liberty to translate the constant many times, so the address referred to may not
1402+
be stable.
14011403

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

14061408
```
1407-
static BIT1: uint = 1 << 0;
1408-
static BIT2: uint = 1 << 1;
1409+
const BIT1: uint = 1 << 0;
1410+
const BIT2: uint = 1 << 1;
14091411
1410-
static BITS: [uint, ..2] = [BIT1, BIT2];
1411-
static STRING: &'static str = "bitstring";
1412+
const BITS: [uint, ..2] = [BIT1, BIT2];
1413+
const STRING: &'static str = "bitstring";
14121414
14131415
struct BitsNStrings<'a> {
14141416
mybits: [uint, ..2],
14151417
mystring: &'a str
14161418
}
14171419
1418-
static BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
1420+
const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
14191421
mybits: BITS,
14201422
mystring: STRING
14211423
};
14221424
```
14231425

1426+
### Static items
1427+
1428+
```{.ebnf .gram}
1429+
static_item : "static" ident ':' type '=' expr ';' ;
1430+
```
1431+
1432+
A *static item* is similar to a *constant*, except that it represents a precise
1433+
memory location in the program. A static is never "inlined" at the usage site,
1434+
and all references to it refer to the same memory location. Static items have
1435+
the `static` lifetime, which outlives all other lifetimes in a Rust program.
1436+
Static items may be placed in read-only memory if they do not contain any
1437+
interior mutability.
1438+
1439+
Statics may contain interior mutability through the `UnsafeCell` language item.
1440+
All access to a static is safe, but there are a number of restrictions on
1441+
statics:
1442+
1443+
* Statics may not contain any destructors.
1444+
* The types of static values must ascribe to `Sync` to allow threadsafe access.
1445+
* Statics may not refer to other statics by value, only by reference.
1446+
* Constants cannot refer to statics.
1447+
1448+
Constants should in general be preferred over statics, unless large amounts of
1449+
data are being stored, or single-address and mutability properties are required.
1450+
1451+
```
1452+
use std::sync::atomic;
1453+
1454+
// Note that INIT_ATOMIC_UINT is a *const*, but it may be used to initialize a
1455+
// static. This static can be modified, so it is not placed in read-only memory.
1456+
static COUNTER: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
1457+
1458+
// This table is a candidate to be placed in read-only memory.
1459+
static TABLE: &'static [uint] = &[1, 2, 3, /* ... */];
1460+
1461+
for slot in TABLE.iter() {
1462+
println!("{}", slot);
1463+
}
1464+
COUNTER.fetch_add(1, atomic::SeqCst);
1465+
```
1466+
14241467
#### Mutable statics
14251468

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

1501+
Mutable statics have the same restrictions as normal statics, except that the
1502+
type of the value is not required to ascribe to `Sync`.
1503+
14581504
### Traits
14591505

14601506
A _trait_ describes a set of method types.

src/etc/unicode.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -333,14 +333,14 @@ def emit_property_module(f, mod, tbl, emit_fn):
333333
def emit_regex_module(f, cats, w_data):
334334
f.write("pub mod regex {\n")
335335
regex_class = "&'static [(char, char)]"
336-
class_table = "&'static [(&'static str, %s)]" % regex_class
336+
class_table = "&'static [(&'static str, &'static %s)]" % regex_class
337337

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

341-
f.write(" pub static PERLD: %s = super::general_category::Nd_table;\n\n"
341+
f.write(" pub static PERLD: &'static %s = &super::general_category::Nd_table;\n\n"
342342
% regex_class)
343-
f.write(" pub static PERLS: %s = super::property::White_Space_table;\n\n"
343+
f.write(" pub static PERLS: &'static %s = &super::property::White_Space_table;\n\n"
344344
% regex_class)
345345

346346
emit_table(f, "PERLW", w_data, regex_class)

src/liballoc/heap.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub fn stats_print() {
8585
///
8686
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
8787
/// non-zero-size memory allocations.
88-
pub static EMPTY: *mut () = 0x1 as *mut ();
88+
pub const EMPTY: *mut () = 0x1 as *mut ();
8989

9090
/// The allocator for unique pointers.
9191
#[cfg(not(test))]

src/libcollections/trie.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ use slice::{Items, MutItems};
3434
use slice;
3535

3636
// FIXME: #5244: need to manually update the TrieNode constructor
37-
static SHIFT: uint = 4;
38-
static SIZE: uint = 1 << SHIFT;
39-
static MASK: uint = SIZE - 1;
40-
static NUM_CHUNKS: uint = uint::BITS / SHIFT;
37+
const SHIFT: uint = 4;
38+
const SIZE: uint = 1 << SHIFT;
39+
const MASK: uint = SIZE - 1;
40+
const NUM_CHUNKS: uint = uint::BITS / SHIFT;
4141

4242
#[deriving(Clone)]
4343
enum Child<T> {

src/libcore/atomic.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,19 @@ pub enum Ordering {
7777

7878
/// An `AtomicBool` initialized to `false`
7979
#[unstable = "may be renamed, pending conventions for static initalizers"]
80-
pub static INIT_ATOMIC_BOOL: AtomicBool =
80+
pub const INIT_ATOMIC_BOOL: AtomicBool =
8181
AtomicBool { v: UnsafeCell { value: 0 }, nocopy: marker::NoCopy };
8282
/// An `AtomicInt` initialized to `0`
8383
#[unstable = "may be renamed, pending conventions for static initalizers"]
84-
pub static INIT_ATOMIC_INT: AtomicInt =
84+
pub const INIT_ATOMIC_INT: AtomicInt =
8585
AtomicInt { v: UnsafeCell { value: 0 }, nocopy: marker::NoCopy };
8686
/// An `AtomicUint` initialized to `0`
8787
#[unstable = "may be renamed, pending conventions for static initalizers"]
88-
pub static INIT_ATOMIC_UINT: AtomicUint =
88+
pub const INIT_ATOMIC_UINT: AtomicUint =
8989
AtomicUint { v: UnsafeCell { value: 0, }, nocopy: marker::NoCopy };
9090

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

9494
#[stable]
9595
impl AtomicBool {

src/libcore/cell.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ pub struct RefCell<T> {
219219
// Values [1, MAX-1] represent the number of `Ref` active
220220
// (will not outgrow its range since `uint` is the size of the address space)
221221
type BorrowFlag = uint;
222-
static UNUSED: BorrowFlag = 0;
223-
static WRITING: BorrowFlag = -1;
222+
const UNUSED: BorrowFlag = 0;
223+
const WRITING: BorrowFlag = -1;
224224

225225
impl<T> RefCell<T> {
226226
/// Create a new `RefCell` containing `value`

src/libcore/char.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static MAX_THREE_B: u32 = 0x10000u32;
6363
*/
6464

6565
/// The highest valid code point
66-
pub static MAX: char = '\U0010ffff';
66+
pub const MAX: char = '\U0010ffff';
6767

6868
/// Converts from `u32` to a `char`
6969
#[inline]

src/libcore/num/f32.rs

+33-33
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,29 @@ use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
2020
use num::Float;
2121
use option::Option;
2222

23-
pub static RADIX: uint = 2u;
23+
pub const RADIX: uint = 2u;
2424

25-
pub static MANTISSA_DIGITS: uint = 24u;
26-
pub static DIGITS: uint = 6u;
25+
pub const MANTISSA_DIGITS: uint = 24u;
26+
pub const DIGITS: uint = 6u;
2727

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

3030
/// Smallest finite f32 value
31-
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
31+
pub const MIN_VALUE: f32 = -3.40282347e+38_f32;
3232
/// Smallest positive, normalized f32 value
33-
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
33+
pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
3434
/// Largest finite f32 value
35-
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;
35+
pub const MAX_VALUE: f32 = 3.40282347e+38_f32;
3636

37-
pub static MIN_EXP: int = -125;
38-
pub static MAX_EXP: int = 128;
37+
pub const MIN_EXP: int = -125;
38+
pub const MAX_EXP: int = 128;
3939

40-
pub static MIN_10_EXP: int = -37;
41-
pub static MAX_10_EXP: int = 38;
40+
pub const MIN_10_EXP: int = -37;
41+
pub const MAX_10_EXP: int = 38;
4242

43-
pub static NAN: f32 = 0.0_f32/0.0_f32;
44-
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
45-
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
43+
pub const NAN: f32 = 0.0_f32/0.0_f32;
44+
pub const INFINITY: f32 = 1.0_f32/0.0_f32;
45+
pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
4646

4747
/// Various useful constants.
4848
pub mod consts {
@@ -53,55 +53,55 @@ pub mod consts {
5353
// of `Float`.
5454

5555
/// Archimedes' constant
56-
pub static PI: f32 = 3.14159265358979323846264338327950288_f32;
56+
pub const PI: f32 = 3.14159265358979323846264338327950288_f32;
5757

5858
/// pi * 2.0
59-
pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;
59+
pub const PI_2: f32 = 6.28318530717958647692528676655900576_f32;
6060

6161
/// pi/2.0
62-
pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
62+
pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
6363

6464
/// pi/3.0
65-
pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;
65+
pub const FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;
6666

6767
/// pi/4.0
68-
pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;
68+
pub const FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;
6969

7070
/// pi/6.0
71-
pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;
71+
pub const FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;
7272

7373
/// pi/8.0
74-
pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;
74+
pub const FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;
7575

7676
/// 1.0/pi
77-
pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
77+
pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
7878

7979
/// 2.0/pi
80-
pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
80+
pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
8181

8282
/// 2.0/sqrt(pi)
83-
pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
83+
pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
8484

8585
/// sqrt(2.0)
86-
pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
86+
pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
8787

8888
/// 1.0/sqrt(2.0)
89-
pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
89+
pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
9090

9191
/// Euler's number
92-
pub static E: f32 = 2.71828182845904523536028747135266250_f32;
92+
pub const E: f32 = 2.71828182845904523536028747135266250_f32;
9393

9494
/// log2(e)
95-
pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;
95+
pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;
9696

9797
/// log10(e)
98-
pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;
98+
pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;
9999

100100
/// ln(2.0)
101-
pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;
101+
pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32;
102102

103103
/// ln(10.0)
104-
pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
104+
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
105105
}
106106

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

149149
let bits: u32 = unsafe { mem::transmute(self) };
150150
match (bits & MAN_MASK, bits & EXP_MASK) {

0 commit comments

Comments
 (0)