15. Ownership and Destruction¶
15.1. Ownership¶
Legality Rules
15.1:1 Ownership is a property of values that is central to the resource management model of Rust.
15.2. Initialization¶
Legality Rules
15.2:1 Initialization is the act of supplying an initial value to a variable.
15.2:2 When a variable holds a value, the variable is considered to be initialized.
15.2:3 When a variable lacks a value or its value has been passed by move, the variable is considered to be uninitialized.
15.2:4 A variable shall be initialized before it is accessed.
Runtime Semantics
15.2:5 All memory starts as uninitialized.
Examples
15.2:6
Variable a
is initialized.
let a: i32 = 42;
15.2:7
Variable b
starts off as uninitialized, but is later initialized by virtue
of the assignment statement.
let b: i32;
b = 42;
15.2:8
Variable c
starts off initialized, but is later uninitialized by virtue of a
transfer by move.
use core::sync::atomic::AtomicI32;
let c: AtomicI32 = AtomicI32::new(42);
let d: AtomicI32 = c;
15.3. References¶
Legality Rules
15.3:1 A reference is a value of a reference type. A reference can be obtained explicitly by using a borrow expression or implicitly in certain scenarios.
15.3:2 A referent is the value pointed-to by a reference.
15.3:3 A reference shall point to an initialized referent.
15.3:4 The lifetime of a referent shall be at least as long as the lifetime of its reference.
15.3:5 A reference is active from the point of obtaining its referent upto the last use of the reference, prior to another assignment to the reference or the end of the scope of the reference.
15.3:6 A referent shall not be passed by move while a reference to it is active.
15.3:7 A referent shall not be modified while a reference to it is active.
15.3:8 An immutable reference is a value of a shared reference type, and prevents the mutation of its referent.
15.3:9 A mutable reference is a value of a mutable reference type, and allows the mutation of its referent.
15.3:10 The referent of an immutable reference shall be mutated only when the type of the referent is subject to interior mutability.
15.3:11 While a mutable reference is active, no other reference shall refer to a value that overlaps with the referent of the mutable reference.
Undefined Behavior
15.3:12 It is undefined behavior to access a value through aliasing mutable references from unsafe context.
Examples
let immutable_reference: &i32 = &42;
let mutable_reference: &mut i32 = &mut 42;
15.4. Borrowing¶
Legality Rules
15.4:1 Borrowing is the process of temporarily associating a reference with a value without transferring ownership permanently.
15.4:2 A borrow is a reference produced by borrowing.
15.4:3 An implicit borrow is a borrow that is not present syntactically in program text. An implicit borrow occurs in the following contexts:
15.4:4 The call operand of a call expression,
15.4:5 The operands of a comparison expression,
15.4:6 The assigned operand of a compound assignment expression,
15.4:7 The operand of a field access expression,
15.4:8 The operand of a dereference expression,
15.4:9 The indexed operand of an index expression,
15.4:10 The receiver operand of a method call expression.
15.4:11 An implicit borrow may be an immutable borrow or a mutable borrow if required.
15.4:12 An immutable borrow is an immutable reference produced by borrowing.
15.4:13 A mutable borrow is a mutable reference produced by borrowing.
15.4:14 Borrowing a field of a union type borrows all remaining fields using the same lifetime.
15.4:15 Immutably borrowing a value proceeds as follows:
15.4:16 ??? (this should describe the order of borrowing and when the borrow is returned)
15.4:17 An immutable borrow of type
&'a T
is created, where lifetime'a
is replaced by a lifetime variable, andT
is replaced by the borrowed type.15.4:18 Lifetime inference is performed.
15.4:19 The immutable borrow is checked against other borrows and by move passing within the enclosing item.
15.4:20 An immutable reference to the borrowed value is produced.
15.4:21 The immutable borrow is released immediately after the last usage of its related immutable reference.
15.4:22 Mutably borrowing a value proceeds as follows:
15.4:23 A mutable borrow of type
&'a mut T
is created, where lifetime'a
is replaced by a lifetime variable, andT
is replaced by the borrowed type.15.4:24 Lifetime inference is performed.
15.4:25 The mutable borrow is checked against other borrows and by move passing within the enclosing item.
15.4:26 A mutable reference to the borrowed value is produced.
15.4:27 The mutable borrow is released immediately after the last usage of its related mutable reference.
Examples
let mutable_borrow = &mut 42;
let immutable_borrow = &42;
15.5. Passing Conventions¶
Legality Rules
15.5:1 A passing convention is the mechanism that defines how a value is transferred between places.
15.5:2
A copy type is a type that implements the core::marker::Copy
trait.
15.5:3 A value of a copy type is passed by copy. Passing by copy does not change the owner of the value.
15.5:4
A move type is a type that implements the core::marker::Sized
trait and is not a copy type.
15.5:5 A value of a move type is passed by move. Passing by move changes the owner of the value.
15.5:6 A value of a place expression shall be passed by move only when it denotes:
15.5:7 A field of a place expression that can be passed by move and whose type does not implement the
core::ops::Drop
trait, or15.5:8 A temporary, or
15.5:10 A value of a value expression is always passed by move.
15.5:11 A value not subject to by copy or by move passing convention shall not be passed between places.
Dynamic Semantics
15.5:12 Passing a value by copy from a source owner to a target owner proceeds as follows:
15.5:15 Passing a value by move from a source owner to a target owner proceeds as follows:
Examples
15.5:18
Type i32
is a copy type. By the end of the second let statement, x
is
the owner of the original 42
and y
is the owner of a cloned 42
.
let x: i32 = 42;
let y: i32 = x;
15.5:19
Type core::sync::atomic::AtomicI32
is a move type. By the end of the
second let statement, x
is uninitialized and y
is the sole owner of the
atomic 42
.
use core::sync::atomic::AtomicI32;
let x: AtomicI32 = AtomicI32::new(42);
let y: AtomicI32 = x;
15.6. Destruction¶
Legality Rules
15.6:1 Destruction is the process of recovering resources associated with a value as it goes out of scope.
15.7. Destructors¶
Legality Rules
15.7:1
A drop type is a type that implements the core::ops::Drop
trait or contains a field that has a drop type.
15.7:2 A destructor is a function that is invoked immediately before the destruction of a value of a drop type.
15.7:3 Dropping a value is the act of invoking the destructor of the related type. Such an object is said to be dropped.
15.7:4 An uninitialized variable is not dropped.
Dynamic Semantics
15.7:5 Dropping an initialized variable proceeds as follows:
15.7:6 If the drop type implements the
core::ops::Drop
trait, thencore::ops::Drop::drop
of the drop type is invoked.15.7:7 If the drop type is an array type, then its elements are dropped from the first element to the last element.
15.7:8 Otherwise, if the drop type is a closure type, then all capture targets whose capture mode is by move mode are dropped in unspecified order.
15.7:9 Otherwise, if the drop type is an enum type, then the fields of the active enum variant are dropped in declaration order.
15.7:10 Otherwise, if the drop type is a slice type, then its elements are dropped from the first element to the last element.
15.7:11 Otherwise, if the drop type is a struct type, then its fields are dropped in declaration order.
15.7:12 Otherwise, if the drop type is a trait object type, then the destructor of the underlying type is invoked.
15.7:13 Otherwise, if the drop type is a tuple type, then its fields are dropped in declaration order.
15.7:14 Otherwise, dropping has no effect.
Examples
struct PrintOnDrop(&'static str);
impl core::ops::Drop for PrintOnDrop {
fn drop(&mut self) {
println!("{}", self.0);
}
}
15.7:15
When object array
is dropped, its destructor drops the first element, then
the second element.
let array = [PrintOnDrop("first element to be dropped"),
PrintOnDrop("second element to be dropped")];
15.7:16
Object uninitialized
is not dropped.
let uninitialized: PrintOnDrop;
15.8. Drop Scopes¶
Legality Rules
15.8:1 A drop scope is a region of program text that governs the dropping of values. When control flow leaves a drop scope, all values associated with that drop scope are dropped based on a drop order.
15.8:2 A drop construct is a construct that employs a drop scope. The following constructs are drop constructs:
15.8:3 Expressions,
15.8:4 Functions,
15.8:5 A match arm of a match expression,
15.8:6 Statements.
15.8:7 Drop scopes are nested within one another as follows:
15.8:8 The drop scope of a function is the outermost drop scope.
15.8:9 The parent drop scope of a function body is the drop scope of its related function.
15.8:10 The parent drop scope of an operand in an expression statement is the drop scope of the expression statement.
15.8:11 The parent drop scope of the expression of a let statement is the drop scope of the let statement.
15.8:12 The parent drop scope of a statement is the drop scope of the block expression that contains the statement.
15.8:13 The parent drop scope of the operand of a match arm guard is the drop scope of the match arm that contains the match arm guard.
15.8:14 The parent drop scope of the operand of a match arm is the drop scope of the match arm that contains the operand.
15.8:15 The parent drop scope of a match arm is the drop scope of the related match expression.
15.8:16 The parent drop scope of all other drop scopes is the drop scope of the immediately enclosing expression.
15.8:17 A binding declared in a for loop expression is associated with the drop scope of the block expression of the for loop expression.
15.8:18 A binding declared in an if let expression is associated with the drop scope of the block expression of the if let expression.
15.8:19 A binding declared in a let statement is associated with the drop scope of the block expression that contains the let statement.
15.8:20 A binding declared in a match expression is associated with the drop scope of the match arm of the match expression.
15.8:21 A binding declared in a while let loop expression is associated with the drop scope of the block expression of the while let loop expression.
15.8:22 A value or binding of a function parameter is associated with the drop scope of the function of the function parameter.
15.8:23 A temporary that is not subject to constant promotion is associated with the innermost drop scope that contains the expression which produced the temporary, taking into account drop scope extension. The possible drop scopes are as follows:
15.8:24 The drop scope of a function body.
15.8:25 The drop scope of a statement.
15.8:26 The drop scope of a block expression of an if expression, an infinite loop expression, or a while loop expression.
15.8:27 The drop scope of an else expression.
15.8:28 The drop scope of the subject expression of an if expression.
15.8:29 The drop scope of the iteration expression of a while loop expression.
15.8:30 The drop scope of the operand of a match arm.
15.8:31 The drop scope of the operand of a match arm guard.
15.8:32 The drop scope of the right operand of a lazy boolean expression.
15.8.1. Drop Scope Extension¶
Legality Rules
15.8.1:1 Drop scope extension is the process of extending a drop scope associated with a temporary to prevent the premature dropping of the temporary.
15.8.1:2 An extending pattern is either
15.8.1:3 A reference identifier pattern, or
15.8.1:4 A slice pattern, a struct pattern, tuple pattern or a tuple struct pattern that contains at least one subpattern that is an extending pattern.
15.8.1:5 If the pattern-without-alternation of a let statement is an extending pattern, then the drop scope of the expression of the let statement is extended to the drop scope of the block expression that contains the let statement.
15.8.1:6 An extending expression is either
15.8.1:7 The expression of a let statement, or
15.8.1:8 The operand of an extending expression that is an array expression, a borrow expression, a struct expression, a tuple expression, or a type cast expression, or
15.8.1:9 The block expression and else expression of an if expression that is an extending expression.
15.8.1:10 The expression of an else expression that is an extending expression.
15.8.1:11 The expression of a match arm of a match expression that is an extending expression.
15.8.1:12 The tail expression of a block expression that is an extending expression.
15.8.1:13 The drop scope of the operand of a borrow expression that is an extending expression is extended to the drop scope of the block expression that contains the let statement.
15.8.1:14 The drop scope of the operand of a borrow expression, a dereference expression, or a field access expression that has an extended drop scope is extended to the drop scope of the expression.
15.8.1:15 The drop scope of the indexed operand of an index expression that has an extended drop scope is extended to the drop scope of the expression.
Examples
15.8.1:16
See Paragraph 15.6.1. for the declaration of PrintOnDrop
.
15.8.1:17
The drop scope of the temporary created for expression AtomicI32::new(42)
is
extended to the drop scope of the block expression.
use core::sync::atomic::AtomicI32;
{
let ref mut a = AtomicI32::new(42);
println!("{}", a);
}
15.9. Drop Order¶
Legality Rules
15.9:1 Drop order is the order by which values are dropped when a drop scope is left.
15.9:2 When a drop scope is left, all values associated with that drop scope are dropped as follows:
15.9:4 Temporaries are dropped in reverse creation order.
15.9:5 When a drop scope of a function is left, then each function parameter is dropped from right to left as follows:
15.9:6 All bindings introduced by the pattern of the function parameter are dropped in reverse declaration order,
15.9:7 The value of the function parameter is dropped.
15.9:8 When multiple drop scopes are left at once, the values are dropped from the innermost drop scope to the outermost drop scope.
Examples
15.9:9
See Paragraph 15.6.1. for the declaration of PrintOnDrop
.
15.9:10
The drop order of the following variables is b
, c
, a
. Dropping
proceeds as follows:
15.9:11 The scope of the block expression is left first because it is an inner scope.
15.9:12
b
is dropped.15.9:13 The outer scope is left.
15.9:14
c
is dropped because dropping occurs in reverse declarative order.15.9:15
a
is dropped.
let a = PrintOnDrop("3");
{
let b = PrintOnDrop("1");
}
let c = PrintOnDrop("2");