Silex v0.47.1 / Docs Canonical source ↗

Copy or transfer a value

An ordinary assignment compositionally copies structures, enums, optionals, arrays, and lists. Any class references they contain remain shared.

struct Position {
    var x:int
    var y:int
}

func main() {
    var first = Position(x:1, y:2)
    var second = first
    second.x = 10

    print(first.x)
    print(second.x)
}

After the following copy, both structures still reach the same State instance:

var foo1 = Foo(value:10, instance:State(value:5))
var foo2 = foo1

foo2.instance.value = 8
print(foo1.instance.value) // 8

Detach the entire reachable graph

var foo3 = copy foo1

foo3.instance.value = 12
print(foo1.instance.value) // 8

copy recursively recreates reached class instances. Repeated references remain repeated in the clone, and cycles remain cycles. No constructor runs again.

A class declared nocopy represents a native or external identity that has no safe duplication operation: a device, buffer, system file, or similar resource. Ordinary assignment still shares that identity, directly or through a structure. However, copy is rejected statically as soon as the value can reach such a class: it never silently duplicates a handle and its cleanup.

nocopy class DeviceHandle {}
struct Owner { var handle:DeviceHandle }

var handle = DeviceHandle()
let owner = Owner(handle:handle)
let shared = owner       // shares the same identity
// let detached = copy owner // error: reaches a non-clonable class

The compiler captures one consistent logical snapshot of the graph. A concurrent Silex mutation is ordered before or after that snapshot; the detached copy cannot mix two states of the source.

Read a field from a temporary value

In make_label().text, the selected field remains valid after the temporary value returned by make_label is released. Its other owned fields are released. An extracted class reference keeps its shared identity; it is not cloned. This also applies to named tuples and the present branch of optional access.

Constructing a tuple from existing values or destructuring it into bindings preserves the same copy and transfer rules as other values.

Transfer ownership

var original = Position(x:1, y:2)
let transferred = move original

original = Position()

move consumes a complete local variable or an ordinary parameter. The source cannot be read again until a consumed var receives a complete replacement value. A consumed let cannot be initialized again.

The consumed source no longer runs drop; the transferred value owns the remaining cleanup. Fields, indexed elements, self, and temporary expressions are not accepted sources for an explicit move.

Reading a temporary collection

make_values()[0] preserves the selected element before releasing the temporary array or list. A class reference keeps its shared identity; other temporary elements are released. Reads such as make_values().count(), make_values().is_empty() and make_label().count() release their temporary receiver after producing the scalar result. These operations do not release a collection or string stored in a variable: its owner still controls its lifetime.

Callback calls

A callback call follows the same ownership rules as a direct call. For a parameter passed by value, a temporary argument is transferred and a stored argument keeps its owner. An owned result is transferred to its next use.

Back to ownership · Borrow without transferring