diff --git a/src/expressions.md b/src/expressions.md index 18ebc0c61..c433caca7 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -209,25 +209,25 @@ then it is a compiler error if the value must be evaluated at compile time, otherwise it is just a warning, but the code will most likely panic when run. The following expressions are constant expressions, so long as any operands are -also constant expressions: +also constant expressions and do not cause any [`Drop::drop`][destructors] calls +to be ran. * [Literals]. * [Paths] to [functions](items/functions.html) and constants. Recursively defining constants is not allowed. * [Tuple expressions]. * [Array expressions]. -* [Struct] expressions, where the type does not implement [`Drop`](the-drop-trait.html). -* [Enum variant] expressions, where the enumeration type does not implement `Drop`. -* [Block expressions] (and `unsafe` blocks) which only contain items and - possibly a (constant) tail expression. +* [Struct] expressions. +* [Enum variant] expressions. +* [Block expressions], including `unsafe` blocks, which only contain items and + possibly a constant tail expression. * [Field] expressions. * Index expressions, [array indexing] or [slice] with a `usize`. * [Range expressions]. * [Closure expressions] which don't capture variables from the environment. * Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean] operators used on integer and floating point types, `bool` and `char`. -* Shared [borrow], except if applied to a type with [interior - mutability](interior-mutability.html). +* Shared [borrow]s, except if applied to a type with [interior mutability]. * The [dereference operator]. * [Grouped] expressions. * [Cast] expressions, except pointer to address and @@ -269,4 +269,6 @@ exist in `core::ops` and `core::cmp` with the same names. [negation]: expressions/operator-expr.html#negation-operators [overflow]: expressions/operator-expr.html#overflow +[destructors]: destructors.html +[interior-mutability]: interior-mutability.html [slice]: types.html#array-and-slice-types diff --git a/src/interior-mutability.md b/src/interior-mutability.md index 6a697a753..f10d3679c 100644 --- a/src/interior-mutability.md +++ b/src/interior-mutability.md @@ -1,13 +1,13 @@ # Interior Mutability -Sometimes a type needs be mutated while having multiple aliases, in Rust this +Sometimes a type needs be mutated while having multiple aliases. In Rust this is achieved using a pattern called _interior mutability_. A type has interior mutability if its internal state can be changed through a [shared reference] to it. This goes against the usual [requirement][ub] that the value pointed to by a shared reference is not mutated. -[`std::cell::UnsafeCell`] type is the only legal way in Rust to disable this -requirement. When `UnsafeCell` is immutably aliased, it is still safe to +[`std::cell::UnsafeCell`] type is the only allowed way in Rust to disable +this requirement. When `UnsafeCell` is immutably aliased, it is still safe to mutate, or obtain a mutable reference to, the `T` it contains. As with all other types, it is undefined behavior to have multiple `&mut UnsafeCell` aliases. diff --git a/src/items/constant-items.md b/src/items/constant-items.md index 45f273255..e395cb215 100644 --- a/src/items/constant-items.md +++ b/src/items/constant-items.md @@ -10,17 +10,15 @@ 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 +Constants must be explicitly typed. The type must have a `'static` lifetime: any +references it contains must have `'static` lifetimes. + +Constants may refer to the address of other constants, in which case the address will have elided lifetimes where applicable, otherwise – in most cases -– defaulting to the `static` lifetime. (See below on [static lifetime +– defaulting to the `static` lifetime. (See [static lifetime elision].) The compiler is, however, still at liberty to translate the constant many times, so the address referred to may not be stable. -Constants must be explicitly typed. The type may be any type that doesn't -implement [`Drop`] and has a `'static` lifetime: any references it contains -must have `'static` lifetimes. - ```rust const BIT1: u32 = 1 << 0; const BIT2: u32 = 1 << 1; @@ -39,6 +37,29 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { }; ``` +## Constants with Destructors + +Constants can contain destructors. Destructors are ran when the value goes out +of scope. + +```rust +struct TypeWithDestructor(i32); + +impl Drop for TypeWithDestructor { + fn drop(&mut self) { + println!("Dropped. Held {}.", self.0); + } +} + +const ZERO_WITH_DESTRUCTOR: TypeWithDestructor = TypeWithDestructor(0); + +fn create_and_drop_zero_with_destructor() { + let x = ZERO_WITH_DESTRUCTOR; + // x gets dropped at end of function, calling drop. + // prints "Dropped. Held 0.". +} +``` + [constant value]: expressions.html#constant-expressions [static lifetime elision]: items/static-items.html#static-lifetime-elision [`Drop`]: the-drop-trait.html diff --git a/src/items/static-items.md b/src/items/static-items.md index 59399912b..03354ef2a 100644 --- a/src/items/static-items.md +++ b/src/items/static-items.md @@ -5,30 +5,23 @@ >    `static` `mut`? [IDENTIFIER] `:` [_Type_] > `=` [_Expression_] `;` -A *static item* is similar to a *constant*, except that it represents a precise +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. +Static items may be placed in read-only memory if the type is not [interior +mutable]. Static items do not call `drop` at the end of the program. -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 thread-safe - access. +* The type must have the `Sync` trait bound to allow thread-safe access. * Statics allow using paths to statics in the [constant-expression](expressions.html#constant-expressions) used to - initialize them, but statics may not refer to other statics by value, only by - reference. + initialize them, but statics may not refer to other statics by value, only + through a 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. - ## Mutable statics If a static item is declared with the `mut` keyword, then it is allowed to be @@ -64,7 +57,7 @@ unsafe fn bump_levels_unsafe2() -> u32 { ``` Mutable statics have the same restrictions as normal statics, except that the -type of the value is not required to ascribe to `Sync`. +type does not have to implement the `Sync` trait. ## `'static` lifetime elision @@ -97,8 +90,6 @@ the standard elision rules ([see discussion in the nomicon][elision-nomicon]). If it is unable to resolve the lifetimes by its usual rules, it will default to using the `'static` lifetime. By way of example: -[elision-nomicon]: ../nomicon/lifetime-elision.html - ```rust,ignore // Resolved as `fn<'a>(&'a str) -> &'a str`. const RESOLVED_SINGLE: fn(&str) -> &str = .. @@ -112,6 +103,19 @@ const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = .. const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = .. ``` +## Using Statics or Consts + +In can be confusing whether or not you should use a constant item or a static +item. Constants should, in general, be preferred over statics unless one of the +following are true: + +* Large amounts of data are being stored +* The single-address or non-inlining property of statics is required. +* Interior mutability is required. + +[constant]: items/constant-items.html +[interior mutable]: interior_mutability.html [IDENTIFIER]: identifiers.html [_Type_]: types.html [_Expression_]: expressions.html +[elision-nomicon]: ../nomicon/lifetime-elision.html \ No newline at end of file