Modify manual to reflect new box/local terminology and new slot/type roles for box and mutable.
This commit is contained in:
parent
6a0b06e562
commit
aa614d5280
1 changed files with 260 additions and 230 deletions
490
doc/rust.texi
490
doc/rust.texi
|
@ -223,6 +223,67 @@ Unlike many languages, individual modules do @emph{not} carry all the
|
||||||
mechanisms or restrictions of crates. Modules and crates serve different
|
mechanisms or restrictions of crates. Modules and crates serve different
|
||||||
roles.
|
roles.
|
||||||
|
|
||||||
|
@sp 1
|
||||||
|
@item Static control over memory allocation, packing and aliasing.
|
||||||
|
|
||||||
|
Many values in Rust are allocated @emph{within} their containing stack-frame
|
||||||
|
or parent strucure. Numbers, records, tuples and tags are all allocated this
|
||||||
|
way. To allocate such values in the heap, they must be explicitly
|
||||||
|
@emph{boxed}. A @dfn{box} is a pointer to a heap allocation that holds another
|
||||||
|
value, its @emph{content}. If the content of a box is a @emph{state} value --
|
||||||
|
the sort that may contain mutable members -- then the heap allocation is also
|
||||||
|
subject to garbage collection.
|
||||||
|
|
||||||
|
Boxing and unboxing in Rust is explicit, though in many cases (arithmetic
|
||||||
|
operations, name-component dereferencing) Rust will automatically ``reach
|
||||||
|
through'' the box to access its content. Box values can be passed and assigned
|
||||||
|
independently, like pointers in C; the difference is that in Rust they always
|
||||||
|
point to live contents, and are not subject to pointer arithmetic.
|
||||||
|
|
||||||
|
In addition to boxes, Rust supports a kind of pass-by-reference slot called an
|
||||||
|
alias. Forming or releasing an alias does not perform reference-count
|
||||||
|
operations; aliases can only be formed on referents that will provably outlive
|
||||||
|
the alias, and are therefore only used for passing arguments to
|
||||||
|
functions. Aliases are not ``general values'', in the sense that they cannot
|
||||||
|
be independently manipulated. They are more like C++ references, except that
|
||||||
|
like boxes, aliases are safe: they always point to live values.
|
||||||
|
|
||||||
|
In addition, each slot (stack-local allocation or alias) has a static
|
||||||
|
initialization state that is calculated by the typestate system. This permits
|
||||||
|
late initialization of slotsx in functions with complex control-flow, while
|
||||||
|
still guaranteeing that every use of a slot occurs after it has been
|
||||||
|
initialized.
|
||||||
|
|
||||||
|
@sp 1
|
||||||
|
@item Static control over mutability.
|
||||||
|
|
||||||
|
Types in Rust are classified as either immutable or mutable. By default,
|
||||||
|
all types are immutable.
|
||||||
|
|
||||||
|
If a type is declared as @code{mutable}, then the type is a @code{state} type
|
||||||
|
and must be declared as such. Any type directly marked as @code{mutable}
|
||||||
|
@emph{or indirectly containing} a state type is also a state type.
|
||||||
|
|
||||||
|
This classification of data types in Rust interacts with the memory allocation
|
||||||
|
and transmission rules. In particular:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item Only immutable (non-state) values can be sent over channels.
|
||||||
|
@item Only immutable (non-state) objects can have destructor functions.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Boxed state values are subject to local (per-task) garbage-collection. Garbage
|
||||||
|
collection costs are therefore also task-local and do not interrupt or suspend
|
||||||
|
other tasks.
|
||||||
|
|
||||||
|
Boxed immutable values are reference-counted and have a deterministic
|
||||||
|
destruction order: top-down, immediately upon release of the last live
|
||||||
|
reference.
|
||||||
|
|
||||||
|
State values can refer to immutable values, but not vice-versa. Rust therefore
|
||||||
|
encourages the programmer to write in a style that consists primarily of
|
||||||
|
immutable types, but also permits limited, local (per-task) mutability.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
@item Stack-based iterators
|
@item Stack-based iterators
|
||||||
|
|
||||||
|
@ -284,9 +345,9 @@ destructors.
|
||||||
@sp 1
|
@sp 1
|
||||||
@item Dynamic type
|
@item Dynamic type
|
||||||
|
|
||||||
Rust includes support for slots of a top type, @code{any}, that can hold any
|
Rust includes support for values of a top type, @code{any}, that can hold any
|
||||||
type of value whatsoever. An @code{any} slot is a pair of a type code and an
|
type of value whatsoever. An @code{any} value is a pair of a type code and a
|
||||||
exterior value of that type. Injection into an @code{any} and projection by
|
boxed value of that type. Injection into an @code{any} and projection by
|
||||||
type-case-selection is integrated into the language.
|
type-case-selection is integrated into the language.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
|
@ -331,100 +392,41 @@ and/or objects are otherwise freed from data structures holding them. The same
|
||||||
destructors are run in the same order whether the object is deleted by
|
destructors are run in the same order whether the object is deleted by
|
||||||
unwinding during failure or normal execution.
|
unwinding during failure or normal execution.
|
||||||
|
|
||||||
Similarly, the rules for freeing immutable memory are deterministic and
|
Similarly, the rules for freeing immutable values are deterministic and
|
||||||
predictable: on scope-exit or structure-release, interior slots are released
|
predictable: on scope-exit or structure-release, local slots are released
|
||||||
immediately, exterior slots have their reference count decreased and are
|
immediately. Referenced boxes have their reference count decreased and are
|
||||||
released if the count drops to zero. Alias slots are not affected by scope
|
released if the count drops to zero. Aliases are silently forgotten.
|
||||||
exit.
|
|
||||||
|
|
||||||
Mutable memory is local to a task, and is subject to per-task garbage
|
State values are local to a task, and are subject to per-task garbage
|
||||||
collection. As a result, unreferenced mutable memory is not necessarily freed
|
collection. As a result, unreferenced state boxes are not necessarily freed
|
||||||
immediately; if it is acyclic it is freed when the last reference to it drops,
|
immediately; if an unreferenced state box is part of an acyclic graph, it is
|
||||||
but if it is part of a reference cycle it will be freed when the GC collects
|
freed when the last reference to it drops, but if it is part of a reference
|
||||||
it (or when the owning task terminates, at the latest).
|
cycle it will be freed when the GC collects it (or when the owning task
|
||||||
|
terminates, at the latest).
|
||||||
|
|
||||||
Mutable memory can point to immutable memory but not vice-versa. Doing so
|
State values can point to immutable values but not vice-versa. Doing so merely
|
||||||
merely delays (to an undefined future time) the moment when the deterministic,
|
delays (to an undefined future time) the moment when the deterministic,
|
||||||
top-down destruction sequence for the referenced immutable memory
|
top-down destruction sequence for the referenced immutable values
|
||||||
@emph{starts}. In other words, the immutable ``leaves'' of a mutable structure
|
@emph{start}. In other words, the immutable ``leaves'' of a state value are
|
||||||
are released in a locally-predictable order, even if the ``interior'' of the
|
released in a locally-predictable order, even if the ``interior'' of the state
|
||||||
mutable structure is released in an unpredictable order.
|
value is released in an unpredictable order.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
@item Typestate system
|
@item Typestate system
|
||||||
|
|
||||||
Every storage slot in Rust participates in not only a conventional structural
|
Every storage slot in a Rust frame participates in not only a conventional
|
||||||
static type system, describing the interpretation of memory in the slot, but
|
structural static type system, describing the interpretation of memory in the
|
||||||
also a @emph{typestate} system. The static typestates of a program describe
|
slot, but also a @emph{typestate} system. The static typestates of a program
|
||||||
the set of @emph{pure, dynamic predicates} that provably hold over some set of
|
describe the set of @emph{pure, dynamic predicates} that provably hold over
|
||||||
slots, at each point in the program's control flow graph. The static
|
some set of slots, at each point in the program's control flow graph within
|
||||||
calculation of the typestates of a program is a dataflow problem, and handles
|
each frame. The static calculation of the typestates of a program is a
|
||||||
user-defined predicates in a similar fashion to the way the type system
|
function-local dataflow problem, and handles user-defined predicates in a
|
||||||
permits user-defined types.
|
similar fashion to the way the type system permits user-defined types.
|
||||||
|
|
||||||
A short way of thinking of this is: types statically model the kinds of values
|
A short way of thinking of this is: types statically model the kinds of values
|
||||||
held in slots, typestates statically model @emph{assertions that hold} before
|
held in slots, typestates statically model @emph{assertions that hold} before
|
||||||
and after statements.
|
and after statements.
|
||||||
|
|
||||||
@sp 1
|
|
||||||
@item Static control over memory allocation, packing and aliasing.
|
|
||||||
|
|
||||||
Every variable or field in Rust is a combination of a type, a mutability flag
|
|
||||||
and a @emph{mode}; this combination is called a @emph{slot}. There are 3 kinds
|
|
||||||
of @dfn{slot mode}, denoting 3 ways of referring to a value:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
@item ``interior'' (slot contains value)
|
|
||||||
@item ``exterior'', (slot points to to managed heap allocation)
|
|
||||||
@item ``alias'', (slot points directly to provably-live address)
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
Interior slots declared as variables in a function are allocated very quickly
|
|
||||||
on the stack, as part of a local activation frame, as in C or C++. Alias slots
|
|
||||||
permit efficient by-reference parameter passing without adjusting heap
|
|
||||||
reference counts or interacting with garbage collection, as alias lifetimes
|
|
||||||
are statically guaranteed to outlive callee lifetimes.
|
|
||||||
|
|
||||||
Copying data between slots of different modes may cause either a simple
|
|
||||||
address assignment or reference-count adjustment, or may cause a value to be
|
|
||||||
``transplanted'': copied by value from the interior of one memory structure to
|
|
||||||
another, or between stack and heap. Transplanting, when necessary, is
|
|
||||||
predictable and automatic, as part of the definition of the copy operator
|
|
||||||
(@code{=}).
|
|
||||||
|
|
||||||
In addition, slots have a static initialization state that is calculated by
|
|
||||||
the typestate system. This permits late initialization of variables in
|
|
||||||
functions with complex control-flow, while still guaranteeing that every use
|
|
||||||
of a slot occurs after it has been initialized.
|
|
||||||
|
|
||||||
@sp 1
|
|
||||||
@item Static control over mutability.
|
|
||||||
|
|
||||||
Slots in Rust are classified as either immutable or mutable. By default,
|
|
||||||
all slots are immutable.
|
|
||||||
|
|
||||||
If a slot within a type is declared as @code{mutable}, the type is a
|
|
||||||
@code{state} type and must be declared as such.
|
|
||||||
|
|
||||||
This classification of data types in Rust interacts with the memory allocation
|
|
||||||
and transmission rules. In particular:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
@item Only immutable (non-state) values can be sent over channels.
|
|
||||||
@item Only immutable (non-state) objects can have destructor functions.
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
State values are subject to local (per-task) garbage-collection. Garbage
|
|
||||||
collection costs are therefore also task-local and do not interrupt or suspend
|
|
||||||
other tasks.
|
|
||||||
|
|
||||||
Immutable values are reference-counted and have a deterministic destruction
|
|
||||||
order: top-down, immediately upon release of the last live reference.
|
|
||||||
|
|
||||||
State values can refer to immutable values, but not vice-versa. Rust therefore
|
|
||||||
encourages the programmer to write in a style that consists primarily of
|
|
||||||
immutable types, but also permits limited, local (per-task) mutability.
|
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
|
@ -817,9 +819,10 @@ Paths fall into two important categories: @emph{names} and
|
||||||
A @dfn{name} denotes an item, and is statically resolved to its
|
A @dfn{name} denotes an item, and is statically resolved to its
|
||||||
referent at compile time.
|
referent at compile time.
|
||||||
|
|
||||||
An @dfn{lval} denotes a slot, and is statically resolved to a sequence of
|
An @dfn{lval} denotes a slot or some component of a value held within a slot,
|
||||||
memory operations and primitive (arithmetic) expressions required to load or
|
and is statically resolved at compile time to a sequence of memory operations
|
||||||
store to the slot at compile time.
|
and primitive (arithmetic) expressions that will be executed to load or store
|
||||||
|
the associated value, starting from the task stack frame, at run time.
|
||||||
|
|
||||||
In some contexts, the Rust grammar accepts a general @emph{path}, but a
|
In some contexts, the Rust grammar accepts a general @emph{path}, but a
|
||||||
subsequent syntactic restriction requires the path to be an lval or a name. In
|
subsequent syntactic restriction requires the path to be an lval or a name. In
|
||||||
|
@ -1039,13 +1042,14 @@ A Rust task's memory consists of a static set of @emph{items}, a set of tasks
|
||||||
each with its own @emph{stack}, and a @emph{heap}. Immutable portions of the
|
each with its own @emph{stack}, and a @emph{heap}. Immutable portions of the
|
||||||
heap may be shared between tasks, mutable portions may not.
|
heap may be shared between tasks, mutable portions may not.
|
||||||
|
|
||||||
Allocations in the stack and the heap consist of @emph{slots}.
|
Allocations in the stack consist of @emph{slots}, and allocations in the heap
|
||||||
|
consist of @emph{boxes}.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Ref.Mem.Alloc:: Memory allocation model.
|
* Ref.Mem.Alloc:: Memory allocation model.
|
||||||
* Ref.Mem.Own:: Memory ownership model.
|
* Ref.Mem.Own:: Memory ownership model.
|
||||||
* Ref.Mem.Slot:: Memory containment and reference model.
|
* Ref.Mem.Slot:: Stack memory model.
|
||||||
* Ref.Mem.Init:: Initialization state of memory.
|
* Ref.Mem.Box:: Heap memory model.
|
||||||
* Ref.Mem.Acct:: Memory accounting model.
|
* Ref.Mem.Acct:: Memory accounting model.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
@ -1063,21 +1067,23 @@ A task's @dfn{stack} consists of activation frames automatically allocated on
|
||||||
entry to each function as the task executes. A stack allocation is reclaimed
|
entry to each function as the task executes. A stack allocation is reclaimed
|
||||||
when control leaves the frame containing it.
|
when control leaves the frame containing it.
|
||||||
|
|
||||||
The @dfn{heap} is a general term that describes two separate sets of exterior
|
The @dfn{heap} is a general term that describes two separate sets of boxes:
|
||||||
allocations: @emph{local heap} allocations and the @emph{shared heap}
|
@emph{task-local} state boxes and the @emph{shared} immutable boxes.
|
||||||
allocations.
|
|
||||||
|
|
||||||
Exterior allocations of mutable types are @dfn{local heap} allocations,
|
State boxes are @dfn{task-local}, owned by the task. Like any other state
|
||||||
owned by the task. Such @dfn{local allocations} cannot pass over channels and
|
value, they cannot pass over channels. State boxes do not outlive the task
|
||||||
do not outlive the task that owns them. When unreferenced, they are collected
|
that owns them. When unreferenced, they are collected using a general
|
||||||
using a general (cycle-aware) garbage-collector local to each task. Garbage
|
(cycle-aware) garbage-collector local to each task. Garbage collection within
|
||||||
collection within a local heap does not interrupt execution of other tasks.
|
a local heap does not interrupt execution of other tasks.
|
||||||
|
|
||||||
Exterior allocations of immutable types are @dfn{shared heap} allocations,
|
Immutable boxes are @dfn{shared}, and can be multiply-referenced by many
|
||||||
and can be multiply-referenced by many different tasks. Such @dfn{shared
|
different tasks. Like any other immutable type, they can pass over channels,
|
||||||
allocations} can pass over channels, and live as long as the last task
|
and live as long as the last task referencing them within a given domain. When
|
||||||
referencing them. When unreferenced, they are collected immediately using
|
unreferenced, they are destroyed immediately (due to reference-counting) and
|
||||||
reference-counting.
|
returned to the heap memory allocator. Destruction of an immutable box also
|
||||||
|
executes within the context of task that drops the last reference to a shared
|
||||||
|
heap allocation, so executing a long-running destructor does not interrupt
|
||||||
|
execution of other tasks.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1086,72 +1092,57 @@ reference-counting.
|
||||||
@subsection Ref.Mem.Own
|
@subsection Ref.Mem.Own
|
||||||
@c * Ref.Mem.Own:: Memory ownership model.
|
@c * Ref.Mem.Own:: Memory ownership model.
|
||||||
|
|
||||||
A task @emph{owns} all the interior allocations in its stack and @emph{local}
|
A task @emph{owns} all the @emph{stack-local} slot allocations in its stack
|
||||||
exterior allocations. A task @emph{shares} ownership of @emph{shared} exterior
|
and @emph{task-local} boxes accessible from its stack. A task @emph{shares}
|
||||||
allocations. A task does not own any items.
|
ownership of @emph{shared} boxes accessible from its stack. A task does not
|
||||||
|
own any items.
|
||||||
|
|
||||||
@dfn{Ownership} of an allocation means that the owning task is the only task
|
@dfn{Ownership} of an allocation means that the owning task is the only task
|
||||||
that can access the allocation.
|
that can access the allocation.
|
||||||
|
|
||||||
@dfn{Sharing} of an allocation means that the same allocation may be
|
@dfn{Sharing} of an allocation means that the same allocation may be
|
||||||
concurrently referenced by multiple tasks. The only shared allocations are
|
concurrently read by multiple tasks. The only shared allocations are those
|
||||||
those that are immutable.
|
that are immutable.
|
||||||
|
|
||||||
When a stack frame is exited, its interior allocations are all released, and
|
When a stack frame is exited, its local allocations are all released, and its
|
||||||
its references to heap allocations (both shared and owned) are dropped.
|
references to boxes (both shared and owned) are dropped.
|
||||||
|
|
||||||
When a task finishes, its stack is necessarily empty. The task's interior
|
When a task finishes, its stack is necessarily empty and it therefore has no
|
||||||
slots are released as the task itself is released, and its references to heap
|
references to any boxes.
|
||||||
allocations are dropped.
|
|
||||||
|
|
||||||
@page
|
@page
|
||||||
@node Ref.Mem.Slot
|
@node Ref.Mem.Slot
|
||||||
@subsection Ref.Mem.Slot
|
@subsection Ref.Mem.Slot
|
||||||
@c * Ref.Mem.Slot:: Memory containment and reference model.
|
@c * Ref.Mem.Slot:: Stack memory model.
|
||||||
|
|
||||||
A @dfn{slot} is a component of an allocation. A slot either holds a value or
|
A task's stack contains slots.
|
||||||
the address of another allocation. Every slot has one of three possible
|
|
||||||
@emph{modes}.
|
|
||||||
|
|
||||||
The possible @dfn{modes} of a slot are:
|
A @dfn{slot} is a component of a stack frame. A slot is either @emph{local} or
|
||||||
|
an @emph{alias}.
|
||||||
|
|
||||||
@itemize
|
A @dfn{local} slot (or @emph{stack-local} allocation) holds a value directly,
|
||||||
@sp 1
|
allocated within the stack's memory. The value is a part of the stack frame.
|
||||||
@item @dfn{Interior mode}
|
|
||||||
|
|
||||||
The slot holds the value of the slot.
|
An @dfn{alias} references a value outside the frame. An alias may refer to a
|
||||||
|
value allocated in another frame @emph{or} a boxed valaue in the heap. The
|
||||||
|
alias-formation rules ensure that the referent of an alias will outlive the
|
||||||
|
alias.
|
||||||
|
|
||||||
@sp 1
|
Local slots are always implicitly mutable.
|
||||||
@item @dfn{Exterior mode}
|
|
||||||
|
|
||||||
The slot holds the address of a heap allocation that holds the value of the
|
Local slots are not initialized when allocated; the entire frame worth of
|
||||||
slot.
|
local slots are allocated at once, on frame-entry, in an uninitialized
|
||||||
|
state. Subsequent statements within a function may or may not initialize the
|
||||||
|
local slots. Local slots can only be used after they have been initialized;
|
||||||
|
this condition is guaranteed by the typestate system.
|
||||||
|
|
||||||
Exterior slots are indicated by the @emph{at} sigil @code{@@}.
|
Aliases can @emph{only} be declared as arguments in a function or iterator
|
||||||
|
signature, bound to the lifetime of a stack frame. Aliases are not general
|
||||||
For example, the following code allocates an exterior record, copies it by
|
values and cannot be held in boxed allocations or other general data types.
|
||||||
counted-reference to a second exterior slot, then modifies the record through
|
|
||||||
the second exterior slot that points to the same exterior allocation.
|
|
||||||
@example
|
|
||||||
type point3d = rec(int x, int y, int z);
|
|
||||||
let @@point3d pt1 = rec(x=1, y=2, z=3);
|
|
||||||
let @@point3d pt2 = pt1;
|
|
||||||
pt2.z = 4;
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@sp 1
|
|
||||||
@item @dfn{Alias mode}
|
|
||||||
|
|
||||||
The slot holds the address of a value. The referenced value may reside within
|
|
||||||
a stack allocation @emph{or} a heap allocation.
|
|
||||||
|
|
||||||
Alias slots can @emph{only} be declared as members of a function or iterator
|
|
||||||
signature, bound to the lifetime of a stack frame. Alias slots cannot be
|
|
||||||
declared as members of general data types.
|
|
||||||
|
|
||||||
Alias slots are indicated by the @emph{ampersand} sigil @code{&}.
|
Alias slots are indicated by the @emph{ampersand} sigil @code{&}.
|
||||||
|
|
||||||
The following example function accepts a single read-only alias parameter:
|
An example function that accepts an alias parameter:
|
||||||
@example
|
@example
|
||||||
type point3d = rec(int x, int y, int z);
|
type point3d = rec(int x, int y, int z);
|
||||||
|
|
||||||
|
@ -1160,28 +1151,68 @@ fn extract_z(&point3d p) -> int @{
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
The following example function accepts a single mutable alias
|
An example function that accepts an alias to a mutable value:
|
||||||
parameter:
|
|
||||||
@example
|
@example
|
||||||
fn incr(mutable &int i) @{
|
fn incr(& mutable int i) @{
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@page
|
||||||
|
@node Ref.Mem.Box
|
||||||
|
@subsection Ref.Mem.Box
|
||||||
|
@c * Ref.Mem.Box:: Heap memory model.
|
||||||
|
|
||||||
|
A @dfn{box} is a reference to a reference-counted heap allocation holding
|
||||||
|
another value.
|
||||||
|
|
||||||
|
Box types and values are constructed by the @emph{at} sigil @code{@@}.
|
||||||
|
|
||||||
|
An example of constructing a box type and value:
|
||||||
|
@example
|
||||||
|
let @@int x = @@10;
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Some operations implicitly dereference boxes. Examples of such @dfn{implicit
|
||||||
|
dereference} operations are:
|
||||||
|
@itemize
|
||||||
|
@item arithmetic operators (@code{x + y - z})
|
||||||
|
@item name-component selection (@code{x.y.z})
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@page
|
An example of an implicit-dereference operation performed on box values:
|
||||||
@node Ref.Mem.Init
|
@example
|
||||||
@subsection Ref.Mem.Init
|
let @@int x = @@10;
|
||||||
@c * Ref.Mem.Init:: Initialization state of memory.
|
let @@int y = @@12;
|
||||||
|
check (x + y == 22);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Other operations act on box values as single-word-sized address values,
|
||||||
|
automatically adjusting reference counts on the associated heap
|
||||||
|
allocation. For these operations, to access the value held in the box requires
|
||||||
|
an explicit dereference of the box value. Explicitly dereferencing a box is
|
||||||
|
indicated with the @emph{star} sigil @code{*}. Examples of such @dfn{explicit
|
||||||
|
dererence} operations are:
|
||||||
|
@itemize
|
||||||
|
@item copying box values (@code{x = y})
|
||||||
|
@item passing box values to functions (@code{f(x,y)})
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
An example of an explicit-dereference operation performed on box values:
|
||||||
|
@example
|
||||||
|
fn takes_boxed(@@int b) @{
|
||||||
|
@}
|
||||||
|
|
||||||
|
fn takes_unboxed(int b) @{
|
||||||
|
@}
|
||||||
|
|
||||||
|
fn main() @{
|
||||||
|
let @@int x = @@10;
|
||||||
|
takes_boxed(x);
|
||||||
|
takes_unboxed(*x);
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
A slot is either initialized or uninitialized at every point in a program. An
|
|
||||||
@dfn{initialized} slot is one that holds a value. An @dfn{uninitialized} slot
|
|
||||||
is one that has not yet had a value written into it, or has had its value
|
|
||||||
deleted, and so holds undefined memory. The typestate system ensures that an
|
|
||||||
uninitialized slot cannot be read, but can be written to. A slot becomes
|
|
||||||
initialized in any statement that writes to it, and remains initialized until
|
|
||||||
explicitly destroyed or until its enclosing allocation is destroyed.
|
|
||||||
|
|
||||||
@page
|
@page
|
||||||
@node Ref.Mem.Acct
|
@node Ref.Mem.Acct
|
||||||
|
@ -1245,10 +1276,10 @@ messages. Ports receive messages from channels.
|
||||||
A @dfn{channel} is a communication endpoint that can @emph{send}
|
A @dfn{channel} is a communication endpoint that can @emph{send}
|
||||||
messages. Channels send messages to ports.
|
messages. Channels send messages to ports.
|
||||||
|
|
||||||
Each port has a unique identity and cannot be replicated. If a port value is
|
Each port is implicitly boxed and mutable; as such a port has has a unique
|
||||||
copied from one slot to another, both slots refer to the @emph{same} port,
|
per-task identity and cannot be replicated or transmitted. If a port value is
|
||||||
even if the slots are declared as interior-mode. New ports can be constructed
|
copied, both copies refer to the @emph{same} port. New ports can be
|
||||||
dynamically and stored in data structures.
|
constructed dynamically and stored in data structures.
|
||||||
|
|
||||||
Each channel is bound to a port when the channel is constructed, so the
|
Each channel is bound to a port when the channel is constructed, so the
|
||||||
destination port for a channel must exist before the channel itself. A channel
|
destination port for a channel must exist before the channel itself. A channel
|
||||||
|
@ -1672,8 +1703,8 @@ Rust; they cannot be used as user-defined identifiers in any context.
|
||||||
@subsection Ref.Type.Any
|
@subsection Ref.Type.Any
|
||||||
|
|
||||||
The type @code{any} is the union of all possible Rust types. A value of type
|
The type @code{any} is the union of all possible Rust types. A value of type
|
||||||
@code{any} is represented in memory as a pair consisting of an exterior value
|
@code{any} is represented in memory as a pair consisting of a boxed value of
|
||||||
of some non-@code{any} type @var{T} and a reflection of the type @var{T}.
|
some non-@code{any} type @var{T} and a reflection of the type @var{T}.
|
||||||
|
|
||||||
Values of type @code{any} can be used in an @code{alt type} statement, in
|
Values of type @code{any} can be used in an @code{alt type} statement, in
|
||||||
which the reflection is used to select a block corresponding to a particular
|
which the reflection is used to select a block corresponding to a particular
|
||||||
|
@ -1754,10 +1785,10 @@ The primitive types are the following:
|
||||||
@item
|
@item
|
||||||
The ``nil'' type @code{()}, having the single ``nil'' value
|
The ``nil'' type @code{()}, having the single ``nil'' value
|
||||||
@code{()}.@footnote{The ``nil'' value @code{()} is @emph{not} a sentinel
|
@code{()}.@footnote{The ``nil'' value @code{()} is @emph{not} a sentinel
|
||||||
``null pointer'' value for alias or exterior slots; the ``nil'' type is the
|
``null pointer'' value for alias slots; the ``nil'' type is the implicit
|
||||||
implicit return type from functions otherwise lacking a return type, and can
|
return type from functions otherwise lacking a return type, and can be used in
|
||||||
be used in other contexts (such as message-sending or type-parametric code) as
|
other contexts (such as message-sending or type-parametric code) as a
|
||||||
a zero-byte type.}
|
zero-size type.}
|
||||||
@item
|
@item
|
||||||
The boolean type @code{bool} with values @code{true} and @code{false}.
|
The boolean type @code{bool} with values @code{true} and @code{false}.
|
||||||
@item
|
@item
|
||||||
|
@ -1798,7 +1829,7 @@ A value of type @code{str} is a Unicode string, represented as a vector of
|
||||||
@subsection Ref.Type.Rec
|
@subsection Ref.Type.Rec
|
||||||
|
|
||||||
The record type-constructor @code{rec} forms a new heterogeneous product of
|
The record type-constructor @code{rec} forms a new heterogeneous product of
|
||||||
slots.@footnote{The @code{rec} type-constructor is analogous to the
|
values.@footnote{The @code{rec} type-constructor is analogous to the
|
||||||
@code{struct} type-constructor in the Algol/C family, the @emph{record} types
|
@code{struct} type-constructor in the Algol/C family, the @emph{record} types
|
||||||
of the ML family, or the @emph{structure} types of the Lisp family.} Fields of
|
of the ML family, or the @emph{structure} types of the Lisp family.} Fields of
|
||||||
a @code{rec} type are accessed by name and are arranged in memory in the order
|
a @code{rec} type are accessed by name and are arranged in memory in the order
|
||||||
|
@ -1816,10 +1847,10 @@ let int px = p.x;
|
||||||
@subsection Ref.Type.Tup
|
@subsection Ref.Type.Tup
|
||||||
|
|
||||||
The tuple type-constructor @code{tup} forms a new heterogeneous product of
|
The tuple type-constructor @code{tup} forms a new heterogeneous product of
|
||||||
slots exactly as the @code{rec} type-constructor does, with the difference
|
values exactly as the @code{rec} type-constructor does, with the difference
|
||||||
that tuple slots are automatically assigned implicit field names, given by
|
that tuple members are automatically assigned implicit field names, given by
|
||||||
ascending integers prefixed by the underscore character: @code{_0}, @code{_1},
|
ascending integers prefixed by the underscore character: @code{_0}, @code{_1},
|
||||||
@code{_2}, etc. The fields of a tuple are laid out in memory contiguously,
|
@code{_2}, etc. The members of a tuple are laid out in memory contiguously,
|
||||||
like a record, in order specified by the tuple type.
|
like a record, in order specified by the tuple type.
|
||||||
|
|
||||||
An example of a tuple type and its use:
|
An example of a tuple type and its use:
|
||||||
|
@ -1837,9 +1868,9 @@ check (p._1 == "world");
|
||||||
@subsection Ref.Type.Vec
|
@subsection Ref.Type.Vec
|
||||||
|
|
||||||
The vector type-constructor @code{vec} represents a homogeneous array of
|
The vector type-constructor @code{vec} represents a homogeneous array of
|
||||||
slots. A vector has a fixed size, and may or may not have mutable member
|
values of a given type. A vector has a fixed size. If the member-type of a
|
||||||
slots. If the slots of a vector are mutable, the vector is a @emph{state}
|
vector is a state type, then vector is a @emph{state} type, like any type
|
||||||
type.
|
containing another type.
|
||||||
|
|
||||||
Vectors can be sliced. A slice expression builds a new vector by copying a
|
Vectors can be sliced. A slice expression builds a new vector by copying a
|
||||||
contiguous range -- given by a pair of indices representing a half-open
|
contiguous range -- given by a pair of indices representing a half-open
|
||||||
|
@ -1854,8 +1885,8 @@ let vec[int] v2 = v.(0,1); // Form a slice.
|
||||||
|
|
||||||
Vectors always @emph{allocate} a storage region sufficient to store the first
|
Vectors always @emph{allocate} a storage region sufficient to store the first
|
||||||
power of two worth of elements greater than or equal to the size of the
|
power of two worth of elements greater than or equal to the size of the
|
||||||
largest slice sharing the storage. This behaviour supports idiomatic in-place
|
vector. This behaviour supports idiomatic in-place ``growth'' of a mutable
|
||||||
``growth'' of a mutable slot holding a vector:
|
slot holding a vector:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
let mutable vec[int] v = vec(1, 2, 3);
|
let mutable vec[int] v = vec(1, 2, 3);
|
||||||
|
@ -1888,8 +1919,8 @@ a @code{tag} type may refer to type definitions that include the defined
|
||||||
@item Recursive types can only be introduced through @code{tag} types.
|
@item Recursive types can only be introduced through @code{tag} types.
|
||||||
@item A recursive @code{tag} type must have at least one non-recursive
|
@item A recursive @code{tag} type must have at least one non-recursive
|
||||||
variant (in order to give the recursion a basis case).
|
variant (in order to give the recursion a basis case).
|
||||||
@item The recursive slots of recursive variants must be @emph{exterior}
|
@item The recursively-typed members of recursive variants must be @emph{box}
|
||||||
slots (in order to bound the in-memory size of the variant).
|
values (in order to bound the in-memory size of the variant).
|
||||||
@item Recursive type definitions can cross module boundaries, but not module
|
@item Recursive type definitions can cross module boundaries, but not module
|
||||||
@emph{visibility} boundaries, nor crate boundaries (in order to simplify the
|
@emph{visibility} boundaries, nor crate boundaries (in order to simplify the
|
||||||
module system).
|
module system).
|
||||||
|
@ -2028,7 +2059,7 @@ Like ports, tasks are modeled as mutable native types with built-in meaning to
|
||||||
the language. They cannot be transmitted over channels or otherwise
|
the language. They cannot be transmitted over channels or otherwise
|
||||||
replicated, and are always local to the task that spawns them.
|
replicated, and are always local to the task that spawns them.
|
||||||
|
|
||||||
If all references to a task are dropped (due to the release of any slots
|
If all references to a task are dropped (due to the release of any structure
|
||||||
holding those references), the released task immediately fails.
|
holding those references), the released task immediately fails.
|
||||||
@xref{Ref.Task.Life}.
|
@xref{Ref.Task.Life}.
|
||||||
|
|
||||||
|
@ -2163,7 +2194,7 @@ actions.
|
||||||
@menu
|
@menu
|
||||||
* Ref.Stmt.Stat:: The static typestate system of statement analysis.
|
* Ref.Stmt.Stat:: The static typestate system of statement analysis.
|
||||||
* Ref.Stmt.Decl:: Statement declaring an item or slot.
|
* Ref.Stmt.Decl:: Statement declaring an item or slot.
|
||||||
* Ref.Stmt.Copy:: Statement for copying a value between two slots.
|
* Ref.Stmt.Copy:: Statement for copying a value.
|
||||||
* Ref.Stmt.Spawn:: Statements for creating new tasks.
|
* Ref.Stmt.Spawn:: Statements for creating new tasks.
|
||||||
* Ref.Stmt.Send:: Statements for sending a value into a channel.
|
* Ref.Stmt.Send:: Statements for sending a value into a channel.
|
||||||
* Ref.Stmt.Flush:: Statement for flushing a channel queue.
|
* Ref.Stmt.Flush:: Statement for flushing a channel queue.
|
||||||
|
@ -2198,7 +2229,7 @@ on a statement-by-statement basis, the @emph{effects} the statement has on its
|
||||||
environment, as well the @emph{legality} of the statement in its environment.
|
environment, as well the @emph{legality} of the statement in its environment.
|
||||||
|
|
||||||
The legality of a statement is partly governed by syntactic rules, partly by
|
The legality of a statement is partly governed by syntactic rules, partly by
|
||||||
its conformance to the types of slots it affects, and partly by a
|
its conformance to the types of value it affects, and partly by a
|
||||||
statement-oriented static dataflow analysis. This section describes the
|
statement-oriented static dataflow analysis. This section describes the
|
||||||
statement-oriented static dataflow analysis, also called the @emph{typestate}
|
statement-oriented static dataflow analysis, also called the @emph{typestate}
|
||||||
system.
|
system.
|
||||||
|
@ -2427,13 +2458,13 @@ declaring a function-local item.
|
||||||
A @code{slot declaration statement} has one one of two forms:
|
A @code{slot declaration statement} has one one of two forms:
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
@item @code{let} @var{mode-and-type} @var{slot} @var{optional-init};
|
@item @code{let} @var{type} @var{slot} @var{optional-init};
|
||||||
@item @code{auto} @var{slot} @var{optional-init};
|
@item @code{auto} @var{slot} @var{optional-init};
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
Where @var{mode-and-type} is a slot mode and type expression, @var{slot} is
|
Where @var{type} is a type expression, @var{slot} is the name of the slot
|
||||||
the name of the slot being declared, and @var{optional-init} is either the
|
being declared, and @var{optional-init} is either the empty string or an
|
||||||
empty string or an equals sign (@code{=}) followed by a primitive expression.
|
equals sign (@code{=}) followed by a primitive expression.
|
||||||
|
|
||||||
Both forms introduce a new slot into the containing block scope. The new slot
|
Both forms introduce a new slot into the containing block scope. The new slot
|
||||||
is visible across the entire scope, but is initialized only at the point
|
is visible across the entire scope, but is initialized only at the point
|
||||||
|
@ -2441,28 +2472,30 @@ following the declaration statement.
|
||||||
|
|
||||||
The latter (@code{auto}) form of slot declaration causes the compiler to infer
|
The latter (@code{auto}) form of slot declaration causes the compiler to infer
|
||||||
the static type of the slot through unification with the types of values
|
the static type of the slot through unification with the types of values
|
||||||
assigned to the slot in the the remaining code in the block scope. Inferred
|
assigned to the slot in the the remaining code in the block scope. Inference
|
||||||
slots always have @emph{interior} mode. @xref{Ref.Mem.Slot}.
|
only occurs on frame-local slots, not argument slots. Function, iterator and
|
||||||
|
object signatures must always declared types for all argument slots.
|
||||||
|
@xref{Ref.Mem.Slot}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@page
|
@page
|
||||||
@node Ref.Stmt.Copy
|
@node Ref.Stmt.Copy
|
||||||
@subsection Ref.Stmt.Copy
|
@subsection Ref.Stmt.Copy
|
||||||
@c * Ref.Stmt.Copy:: Statement for copying a value between two slots.
|
@c * Ref.Stmt.Copy:: Statement for copying a value.
|
||||||
|
|
||||||
A @dfn{copy statement} consists of an @emph{lval} -- a name denoting a slot --
|
A @dfn{copy statement} consists of an @emph{lval} followed by an equals-sign
|
||||||
followed by an equals-sign (@code{=}) and a primitive
|
(@code{=}) and a primitive expression. @xref{Ref.Expr}.
|
||||||
expression. @xref{Ref.Expr}.
|
|
||||||
|
|
||||||
Executing a copy statement causes the value denoted by the expression --
|
Executing a copy statement causes the value denoted by the expression --
|
||||||
either a value in a slot or a primitive combination of values held in slots --
|
either a value or a primitive combination of values -- to be copied into the
|
||||||
to be copied into the slot denoted by the @emph{lval}.
|
memory location denoted by the @emph{lval}.
|
||||||
|
|
||||||
A copy may entail the formation of references, the adjustment of reference
|
A copy may entail the the adjustment of reference counts, execution of
|
||||||
counts, execution of destructors, or similar adjustments in order to respect
|
destructors, or similar adjustments in order to respect the path through the
|
||||||
the @code{lval} slot mode and any existing value held in it. All such
|
memory graph implied by the @code{lval}, as well as any existing value held in
|
||||||
adjustment is automatic and implied by the @code{=} operator.
|
the memory being written-to. All such adjustment is automatic and implied by
|
||||||
|
the @code{=} operator.
|
||||||
|
|
||||||
An example of three different copy statements:
|
An example of three different copy statements:
|
||||||
@example
|
@example
|
||||||
|
@ -2483,8 +2516,8 @@ function. The called function is referred to as the @dfn{entry function} for
|
||||||
the spawned task, and its arguments are copied form the spawning task to the
|
the spawned task, and its arguments are copied form the spawning task to the
|
||||||
spawned task before the spawned task begins execution.
|
spawned task before the spawned task begins execution.
|
||||||
|
|
||||||
Only arguments of interior or exterior mode are permitted in the function
|
Functions taking alias-slot arguments, or returning non-nil values, cannot be
|
||||||
called by a spawn statement, not arguments with alias mode.
|
spawned. Iterators cannot be spawned.
|
||||||
|
|
||||||
The result of a @code{spawn} statement is a @code{task} value.
|
The result of a @code{spawn} statement is a @code{task} value.
|
||||||
|
|
||||||
|
@ -2561,8 +2594,8 @@ expression denoting a port, and applies the @emph{receive operator}
|
||||||
@var{lval}. The statement causes the receiving task to enter the @emph{blocked
|
@var{lval}. The statement causes the receiving task to enter the @emph{blocked
|
||||||
reading} state until a task is sending a value to the port, at which point the
|
reading} state until a task is sending a value to the port, at which point the
|
||||||
runtime pseudo-randomly selects a sending task and copies a value from the
|
runtime pseudo-randomly selects a sending task and copies a value from the
|
||||||
head of one of the task queues to the receiving slot, and un-blocks the
|
head of one of the task queues to the receiving location in memory, and
|
||||||
receiving task. @xref{Ref.Run.Comm}.
|
un-blocks the receiving task. @xref{Ref.Run.Comm}.
|
||||||
|
|
||||||
An example of a @emph{receive}:
|
An example of a @emph{receive}:
|
||||||
@example
|
@example
|
||||||
|
@ -2576,7 +2609,8 @@ let str s <- p;
|
||||||
@c * Ref.Stmt.Call:: Statement for calling a function.
|
@c * Ref.Stmt.Call:: Statement for calling a function.
|
||||||
|
|
||||||
A @dfn{call statement} invokes a function, providing a tuple of input slots
|
A @dfn{call statement} invokes a function, providing a tuple of input slots
|
||||||
and a reference to an output slot. If the function eventually returns, then
|
and an alias slot to serve as the function's output, bound to the @var{lval}
|
||||||
|
on the right hand side of the call. If the function eventually returns, then
|
||||||
the statement completes.
|
the statement completes.
|
||||||
|
|
||||||
A call statement statically requires that the precondition declared in the
|
A call statement statically requires that the precondition declared in the
|
||||||
|
@ -2596,7 +2630,7 @@ let int x = add(1, 2);
|
||||||
A @dfn{bind statement} constructs a new function from an existing
|
A @dfn{bind statement} constructs a new function from an existing
|
||||||
function.@footnote{The @code{bind} statement is analogous to the @code{bind}
|
function.@footnote{The @code{bind} statement is analogous to the @code{bind}
|
||||||
expression in the Sather language.} The new function has zero or more of its
|
expression in the Sather language.} The new function has zero or more of its
|
||||||
arguments @emph{bound} into a new, hidden exterior tuple that holds the
|
arguments @emph{bound} into a new, hidden boxed tuple that holds the
|
||||||
bindings. For each concrete argument passed in the @code{bind} statement, the
|
bindings. For each concrete argument passed in the @code{bind} statement, the
|
||||||
corresponding parameter in the existing function is @emph{omitted} as a
|
corresponding parameter in the existing function is @emph{omitted} as a
|
||||||
parameter of the new function. For each argument passed the placeholder symbol
|
parameter of the new function. For each argument passed the placeholder symbol
|
||||||
|
@ -2624,11 +2658,9 @@ check (add(4,5) == add5(4));
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
A @code{bind} statement generally stores a copy of the bound arguments in the
|
A @code{bind} statement generally stores a copy of the bound arguments in the
|
||||||
hidden exterior tuple. For bound interior slots and alias slots in the bound
|
hidden, boxed tuple, owned by the resulting first-class function. For each
|
||||||
function signature, an interior slot is allocated in the hidden tuple and
|
bound slot in the bound function's signature, space is allocated in the hidden
|
||||||
populated with a copy of the bound value. For bound exterior slots in the
|
tuple and populated with a copy of the bound value.
|
||||||
bound function signature, an exterior slot is allocated in the hidden tuple
|
|
||||||
and populated with a copy of the bound value, an exterior (pointer) value.
|
|
||||||
|
|
||||||
The @code{bind} statement is a lightweight mechanism for simulating the more
|
The @code{bind} statement is a lightweight mechanism for simulating the more
|
||||||
elaborate construct of @emph{lexical closures} that exist in other
|
elaborate construct of @emph{lexical closures} that exist in other
|
||||||
|
@ -2641,11 +2673,10 @@ of them can be achieved with @code{bind} statements.
|
||||||
@subsection Ref.Stmt.Ret
|
@subsection Ref.Stmt.Ret
|
||||||
@c * Ref.Stmt.Ret:: Statement for stopping and producing a value.
|
@c * Ref.Stmt.Ret:: Statement for stopping and producing a value.
|
||||||
|
|
||||||
Executing a @code{ret} statement@footnote{A @code{ret} statement is
|
Executing a @code{ret} statement@footnote{A @code{ret} statement is analogous
|
||||||
analogous to a @code{return} statement in the C family.} copies a
|
to a @code{return} statement in the C family.} copies a value into the output
|
||||||
value into the return slot of the current function, destroys the
|
slot of the current function, destroys the current function activation frame,
|
||||||
current function activation frame, and transfers control to the caller
|
and transfers control to the caller frame.
|
||||||
frame.
|
|
||||||
|
|
||||||
An example of a @code{ret} statement:
|
An example of a @code{ret} statement:
|
||||||
@example
|
@example
|
||||||
|
@ -2692,7 +2723,7 @@ copy of itself.
|
||||||
@subsection Ref.Stmt.Put
|
@subsection Ref.Stmt.Put
|
||||||
@c * Ref.Stmt.Put:: Statement for pausing and producing a value.
|
@c * Ref.Stmt.Put:: Statement for pausing and producing a value.
|
||||||
|
|
||||||
Executing a @code{put} statement copies a value into the put slot of the
|
Executing a @code{put} statement copies a value into the output slot of the
|
||||||
current iterator, suspends execution of the current iterator, and transfers
|
current iterator, suspends execution of the current iterator, and transfers
|
||||||
control to the current put-recipient frame.
|
control to the current put-recipient frame.
|
||||||
|
|
||||||
|
@ -2772,13 +2803,12 @@ In this example, if the task fails while attempting to open or read a file,
|
||||||
the runtime will log the path name that was being read. If the function
|
the runtime will log the path name that was being read. If the function
|
||||||
completes normally, the runtime will not log the path.
|
completes normally, the runtime will not log the path.
|
||||||
|
|
||||||
A slot that is marked by a @code{note} statement does @emph{not} have its
|
A value that is marked by a @code{note} statement is @emph{not} copied aside
|
||||||
value copied aside when control passes through the @code{note}. In other
|
when control passes through the @code{note}. In other words, if a @code{note}
|
||||||
words, if a @code{note} statement notes a particular slot, and code after the
|
statement notes a particular @var{lval}, and code after the @code{note} that
|
||||||
@code{note} that slot, and then a subsequent failure occurs, the
|
slot, and then a subsequent failure occurs, the @emph{mutated} value will be
|
||||||
@emph{mutated} value will be logged during unwinding, @emph{not} the original
|
logged during unwinding, @emph{not} the original value that was denoted by the
|
||||||
value that was held in the slot at the moment control passed through the
|
@var{lval} at the moment control passed through the @code{note} statement.
|
||||||
@code{note} statement.
|
|
||||||
|
|
||||||
@page
|
@page
|
||||||
@node Ref.Stmt.While
|
@node Ref.Stmt.While
|
||||||
|
@ -3124,7 +3154,7 @@ if check even(x) @{
|
||||||
The Rust @dfn{runtime} is a relatively compact collection of C and Rust code
|
The Rust @dfn{runtime} is a relatively compact collection of C and Rust code
|
||||||
that provides fundamental services and datatypes to all Rust tasks at
|
that provides fundamental services and datatypes to all Rust tasks at
|
||||||
run-time. It is smaller and simpler than many modern language runtimes. It is
|
run-time. It is smaller and simpler than many modern language runtimes. It is
|
||||||
tightly integrated into the language's execution model of slots, tasks,
|
tightly integrated into the language's execution model of memory, tasks,
|
||||||
communication, reflection, logging and signal handling.
|
communication, reflection, logging and signal handling.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
|
@ -3149,7 +3179,7 @@ of the C runtime functions @code{malloc} and @code{free}.
|
||||||
|
|
||||||
The runtime memory-management system in turn supplies Rust tasks with
|
The runtime memory-management system in turn supplies Rust tasks with
|
||||||
facilities for allocating, extending and releasing stacks, as well as
|
facilities for allocating, extending and releasing stacks, as well as
|
||||||
allocating and freeing exterior values.
|
allocating and freeing boxed values.
|
||||||
|
|
||||||
@page
|
@page
|
||||||
@node Ref.Run.Type
|
@node Ref.Run.Type
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue