1
Fork 0

docs: remove mentions of Gc.

This commit is contained in:
Eduard Burtescu 2014-10-01 01:45:17 +03:00
parent 39de8464ed
commit aa0b350c97
5 changed files with 20 additions and 110 deletions

View file

@ -632,19 +632,6 @@ This part is coming soon.
This part is coming soon. This part is coming soon.
# Gc
The `Gc<T>` type exists for historical reasons, and is [still used
internally](https://github.com/rust-lang/rust/issues/7929) by the compiler.
It is not even a 'real' garbage collected type at the moment.
In the future, Rust may have a real garbage collected type, and so it
has not yet been removed for that reason.
## Best practices
There is currently no legitimate use case for the `Gc<T>` type.
# Raw Pointers # Raw Pointers
This part is coming soon. This part is coming soon.

View file

@ -31,7 +31,6 @@ list):
* Task synchronization * Task synchronization
* Task-local storage * Task-local storage
* Logging * Logging
* Local heaps (GC heaps)
* Task unwinding * Task unwinding
## What is the runtime accomplishing? ## What is the runtime accomplishing?

View file

@ -208,9 +208,7 @@ pub struct Unique<T> {
// Implement methods for creating and using the values in the box. // Implement methods for creating and using the values in the box.
// NB: For simplicity and correctness, we require that T has kind Send // NB: For simplicity and correctness, we require that T has kind Send
// (owned boxes relax this restriction, and can contain managed (GC) boxes). // (owned boxes relax this restriction).
// This is because, as implemented, the garbage collector would not know
// about any shared boxes stored in the malloc'd region of memory.
impl<T: Send> Unique<T> { impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> { pub fn new(value: T) -> Unique<T> {
unsafe { unsafe {

View file

@ -3381,7 +3381,7 @@ fn main() {
``` ```
Patterns can also dereference pointers by using the `&`, `box` or `@` symbols, Patterns can also dereference pointers by using the `&`, `box` symbols,
as appropriate. For example, these two matches on `x: &int` are equivalent: as appropriate. For example, these two matches on `x: &int` are equivalent:
``` ```

View file

@ -74,7 +74,7 @@ to an `LV` of `(*a).f`.
Here is the formal grammar for the types we'll consider: Here is the formal grammar for the types we'll consider:
```text ```text
TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY | @ MQ TY TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY
MQ = mut | imm | const MQ = mut | imm | const
``` ```
@ -263,9 +263,7 @@ compatible with the aliasability of `LV`. The goal is to prevent
`&mut` borrows of aliasability data. `&mut` borrows of aliasability data.
3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed 3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed
the lifetime of the value being borrowed. This pass is also the lifetime of the value being borrowed.
responsible for inserting root annotations to keep managed values
alive.
4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the 4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the
restrictions to maintain memory safety. These are the restrictions restrictions to maintain memory safety. These are the restrictions
@ -316,17 +314,13 @@ MUTABILITY(*LV, MQ) // M-Deref-Unique
### Checking mutability of immutable pointer types ### Checking mutability of immutable pointer types
Immutable pointer types like `&T` and `@T` can only Immutable pointer types like `&T` can only
be borrowed if MQ is immutable or const: be borrowed if MQ is immutable or const:
```text ```text
MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm
TYPE(LV) = &Ty TYPE(LV) = &Ty
MQ == imm | const MQ == imm | const
MUTABILITY(*LV, MQ) // M-Deref-Managed-Imm
TYPE(LV) = @Ty
MQ == imm | const
``` ```
### Checking mutability of mutable pointer types ### Checking mutability of mutable pointer types
@ -390,11 +384,10 @@ ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut
## Checking lifetime ## Checking lifetime
These rules aim to ensure that no data is borrowed for a scope that exceeds These rules aim to ensure that no data is borrowed for a scope that exceeds
its lifetime. In addition, these rules manage the rooting of `@` values. its lifetime. These two computations wind up being intimately related.
These two computations wind up being intimately related. Formally, we define Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that
a predicate `LIFETIME(LV, LT, MQ)`, which states that "the lvalue `LV` can be "the lvalue `LV` can be safely borrowed for the lifetime `LT` with mutability
safely borrowed for the lifetime `LT` with mutability `MQ`". The Rust `MQ`". The Rust code corresponding to this predicate is the module
code corresponding to this predicate is the module
`middle::borrowck::gather_loans::lifetime`. `middle::borrowck::gather_loans::lifetime`.
### The Scope function ### The Scope function
@ -423,14 +416,6 @@ the pointer itself `LV` goes out of scope:
SCOPE(*LV) = SCOPE(LV) if LV has type Box<T> SCOPE(*LV) = SCOPE(LV) if LV has type Box<T>
``` ```
The scope of a managed referent is also the scope of the pointer. This
is a conservative approximation, since there may be other aliases for
that same managed box that would cause it to live longer:
```text
SCOPE(*LV) = SCOPE(LV) if LV has type @T
```
The scope of a borrowed referent is the scope associated with the The scope of a borrowed referent is the scope associated with the
pointer. This is a conservative approximation, since the data that pointer. This is a conservative approximation, since the data that
the pointer points at may actually live longer: the pointer points at may actually live longer:
@ -477,59 +462,6 @@ LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed
LT <= LT' LT <= LT'
``` ```
### Checking lifetime for derefs of managed, immutable pointers
Managed pointers are valid so long as the data within them is
*rooted*. There are two ways that this can be achieved. The first is
when the user guarantees such a root will exist. For this to be true,
three conditions must be met:
```text
LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Imm-User-Root
TYPE(LV) = @Ty
LT <= SCOPE(LV) // (1)
LV is immutable // (2)
LV is not moved or not movable // (3)
```
Condition (1) guarantees that the managed box will be rooted for at
least the lifetime `LT` of the borrow, presuming that no mutation or
moves occur. Conditions (2) and (3) then serve to guarantee that the
value is not mutated or moved. Note that lvalues are either
(ultimately) owned by a local variable, in which case we can check
whether that local variable is ever moved in its scope, or they are
owned by the referent of an (immutable, due to condition 2) managed or
references, in which case moves are not permitted because the
location is aliasable.
If the conditions of `L-Deref-Managed-Imm-User-Root` are not met, then
there is a second alternative. The compiler can attempt to root the
managed pointer itself. This permits great flexibility, because the
location `LV` where the managed pointer is found does not matter, but
there are some limitations. The lifetime of the borrow can only extend
to the innermost enclosing loop or function body. This guarantees that
the compiler never requires an unbounded amount of stack space to
perform the rooting; if this condition were violated, the compiler
might have to accumulate a list of rooted objects, for example if the
borrow occurred inside the body of a loop but the scope of the borrow
extended outside the loop. More formally, the requirement is that
there is no path starting from the borrow that leads back to the
borrow without crossing the exit from the scope `LT`.
The rule for compiler rooting is as follows:
```text
LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Imm-Compiler-Root
TYPE(LV) = @Ty
LT <= innermost enclosing loop/func
ROOT LV at *LV for LT
```
Here I have written `ROOT LV at *LV FOR LT` to indicate that the code
makes a note in a side-table that the box `LV` must be rooted into the
stack when `*LV` is evaluated, and that this root can be released when
the scope `LT` exits.
## Computing the restrictions ## Computing the restrictions
The final rules govern the computation of *restrictions*, meaning that The final rules govern the computation of *restrictions*, meaning that
@ -599,22 +531,18 @@ RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer
RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS
``` ```
### Restrictions for loans of immutable managed/borrowed referents ### Restrictions for loans of immutable borrowed referents
Immutable managed/borrowed referents are freely aliasable, meaning that Immutable borrowed referents are freely aliasable, meaning that
the compiler does not prevent you from copying the pointer. This the compiler does not prevent you from copying the pointer. This
implies that issuing restrictions is useless. We might prevent the implies that issuing restrictions is useless. We might prevent the
user from acting on `*LV` itself, but there could be another path user from acting on `*LV` itself, but there could be another path
`*LV1` that refers to the exact same memory, and we would not be `*LV1` that refers to the exact same memory, and we would not be
restricting that path. Therefore, the rule for `&Ty` and `@Ty` restricting that path. Therefore, the rule for `&Ty` pointers
pointers always returns an empty set of restrictions, and it only always returns an empty set of restrictions, and it only permits
permits restricting `MUTATE` and `CLAIM` actions: restricting `MUTATE` and `CLAIM` actions:
```text ```text
RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Managed
TYPE(LV) = @Ty
ACTIONS subset of [MUTATE, CLAIM]
RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed
TYPE(LV) = &LT' Ty TYPE(LV) = &LT' Ty
LT <= LT' // (1) LT <= LT' // (1)
@ -623,8 +551,8 @@ RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed
The reason that we can restrict `MUTATE` and `CLAIM` actions even The reason that we can restrict `MUTATE` and `CLAIM` actions even
without a restrictions list is that it is never legal to mutate nor to without a restrictions list is that it is never legal to mutate nor to
borrow mutably the contents of a `&Ty` or `@Ty` pointer. In other borrow mutably the contents of a `&Ty` pointer. In other words,
words, those restrictions are already inherent in the type. those restrictions are already inherent in the type.
Clause (1) in the rule for `&Ty` deserves mention. Here I Clause (1) in the rule for `&Ty` deserves mention. Here I
specify that the lifetime of the loan must be less than the lifetime specify that the lifetime of the loan must be less than the lifetime
@ -729,13 +657,12 @@ are affine.)
Freeze pointers are read-only. There may be `&mut` or `&` aliases, and Freeze pointers are read-only. There may be `&mut` or `&` aliases, and
we can not prevent *anything* but moves in that case. So the we can not prevent *anything* but moves in that case. So the
`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. `RESTRICTIONS` function is only defined if `ACTIONS` is the empty set.
Because moves from a `&const` or `@const` lvalue are never legal, it Because moves from a `&const` lvalue are never legal, it is not
is not necessary to add any restrictions at all to the final necessary to add any restrictions at all to the final result.
result.
```text ```text
RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed
TYPE(LV) = &const Ty or @const Ty TYPE(LV) = &const Ty
``` ```
### Restrictions for loans of mutable borrowed referents ### Restrictions for loans of mutable borrowed referents
@ -957,8 +884,7 @@ moves and the declaration of uninitialized variables. For each of
these points, we create a bit in the dataflow set. Assignments to a these points, we create a bit in the dataflow set. Assignments to a
variable `x` or path `a.b.c` kill the move/uninitialization bits for variable `x` or path `a.b.c` kill the move/uninitialization bits for
those paths and any subpaths (e.g., `x`, `x.y`, `a.b.c`, `*a.b.c`). those paths and any subpaths (e.g., `x`, `x.y`, `a.b.c`, `*a.b.c`).
The bits are also killed when the root variables (`x`, `a`) go out of Bits are unioned when two control-flow paths join. Thus, the
scope. Bits are unioned when two control-flow paths join. Thus, the
presence of a bit indicates that the move may have occurred without an presence of a bit indicates that the move may have occurred without an
intervening assignment to the same memory. At each use of a variable, intervening assignment to the same memory. At each use of a variable,
we examine the bits in scope, and check that none of them are we examine the bits in scope, and check that none of them are