Correct spelling in docs
This commit is contained in:
parent
ec4362da56
commit
1162b3752c
43 changed files with 82 additions and 82 deletions
|
|
@ -76,7 +76,7 @@ Cleanup through RAII-style destructors is more likely to work than in catch bloc
|
|||
|
||||
## Why aren't modules type-parametric?
|
||||
|
||||
We want to maintain the option to parametrize at runtime. We may eventually change this limitation, but initially this is how type parameters were implemented.
|
||||
We want to maintain the option to parameterize at runtime. We may eventually change this limitation, but initially this is how type parameters were implemented.
|
||||
|
||||
## Why aren't values type-parametric? Why only items?
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ For numeric casts, there are quite a few cases to consider:
|
|||
* zero-extend if the source is unsigned
|
||||
* sign-extend if the source is signed
|
||||
* casting from a float to an integer will round the float towards zero
|
||||
* **[NOTE: currently this will cause Undefined Behaviour if the rounded
|
||||
* **[NOTE: currently this will cause Undefined Behavior if the rounded
|
||||
value cannot be represented by the target integer type][float-int]**.
|
||||
This includes Inf and NaN. This is a bug and will be fixed.
|
||||
* casting from an integer to float will produce the floating point
|
||||
|
|
@ -61,7 +61,7 @@ For numeric casts, there are quite a few cases to consider:
|
|||
* casting from an f32 to an f64 is perfect and lossless
|
||||
* casting from an f64 to an f32 will produce the closest possible value
|
||||
(rounding strategy unspecified)
|
||||
* **[NOTE: currently this will cause Undefined Behaviour if the value
|
||||
* **[NOTE: currently this will cause Undefined Behavior if the value
|
||||
is finite but larger or smaller than the largest or smallest finite
|
||||
value representable by f32][float-float]**. This is a bug and will
|
||||
be fixed.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ interacted with the *outlives* relationship in an inclusive manner. That is,
|
|||
when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as
|
||||
`'b`. At first glance, this seems to be a meaningless distinction. Nothing ever
|
||||
gets dropped at the same time as another, right? This is why we used the
|
||||
following desugarring of `let` statements:
|
||||
following desugaring of `let` statements:
|
||||
|
||||
```rust,ignore
|
||||
let x;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ information that "completes" them (more on this below).
|
|||
There are two major DSTs exposed by the language: trait objects, and slices.
|
||||
|
||||
A trait object represents some type that implements the traits it specifies.
|
||||
The exact original type is *erased* in favour of runtime reflection
|
||||
The exact original type is *erased* in favor of runtime reflection
|
||||
with a vtable containing all the information necessary to use the type.
|
||||
This is the information that completes a trait object: a pointer to its vtable.
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ But neither of these tricks work today, so all Void types get you is
|
|||
the ability to be confident that certain situations are statically impossible.
|
||||
|
||||
One final subtle detail about empty types is that raw pointers to them are
|
||||
actually valid to construct, but dereferencing them is Undefined Behaviour
|
||||
actually valid to construct, but dereferencing them is Undefined Behavior
|
||||
because that doesn't actually make sense. That is, you could model C's `void *`
|
||||
type with `*const Void`, but this doesn't necessarily gain anything over using
|
||||
e.g. `*const ()`, which *is* safe to randomly dereference.
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ let mut vec = vec![Box::new(0); 4];
|
|||
println!("{}", vec[0]);
|
||||
```
|
||||
|
||||
This is pretty clearly Not Good. Unfortunately, we're kind've stuck between a
|
||||
This is pretty clearly Not Good. Unfortunately, we're kind of stuck between a
|
||||
rock and a hard place: maintaining consistent state at every step has an
|
||||
enormous cost (and would negate any benefits of the API). Failing to maintain
|
||||
consistent state gives us Undefined Behavior in safe code (making the API
|
||||
|
|
@ -248,4 +248,4 @@ let mut data = Box::new(0);
|
|||
```
|
||||
|
||||
Dang. Here the destructor running was pretty fundamental to the API, and it had
|
||||
to be scrapped in favour of a completely different design.
|
||||
to be scrapped in favor of a completely different design.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ do some really crazy unsafe things.
|
|||
|
||||
Safe Rust is the *true* Rust programming language. If all you do is write Safe
|
||||
Rust, you will never have to worry about type-safety or memory-safety. You will
|
||||
never endure a null or dangling pointer, or any of that Undefined Behaviour
|
||||
never endure a null or dangling pointer, or any of that Undefined Behavior
|
||||
nonsense.
|
||||
|
||||
*That's totally awesome.*
|
||||
|
|
@ -52,11 +52,11 @@ The only things that are different in Unsafe Rust are that you can:
|
|||
* Mutate statics
|
||||
|
||||
That's it. The reason these operations are relegated to Unsafe is that misusing
|
||||
any of these things will cause the ever dreaded Undefined Behaviour. Invoking
|
||||
Undefined Behaviour gives the compiler full rights to do arbitrarily bad things
|
||||
to your program. You definitely *should not* invoke Undefined Behaviour.
|
||||
any of these things will cause the ever dreaded Undefined Behavior. Invoking
|
||||
Undefined Behavior gives the compiler full rights to do arbitrarily bad things
|
||||
to your program. You definitely *should not* invoke Undefined Behavior.
|
||||
|
||||
Unlike C, Undefined Behaviour is pretty limited in scope in Rust. All the core
|
||||
Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the core
|
||||
language cares about is preventing the following things:
|
||||
|
||||
* Dereferencing null or dangling pointers
|
||||
|
|
@ -71,9 +71,9 @@ language cares about is preventing the following things:
|
|||
* Unwinding into another language
|
||||
* Causing a [data race][race]
|
||||
|
||||
That's it. That's all the causes of Undefined Behaviour baked into Rust. Of
|
||||
That's it. That's all the causes of Undefined Behavior baked into Rust. Of
|
||||
course, unsafe functions and traits are free to declare arbitrary other
|
||||
constraints that a program must maintain to avoid Undefined Behaviour. However,
|
||||
constraints that a program must maintain to avoid Undefined Behavior. However,
|
||||
generally violations of these constraints will just transitively lead to one of
|
||||
the above problems. Some additional constraints may also derive from compiler
|
||||
intrinsics that make special assumptions about how code can be optimized.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Safe Rust guarantees an absence of data races, which are defined as:
|
|||
* one of them is a write
|
||||
* one of them is unsynchronized
|
||||
|
||||
A data race has Undefined Behaviour, and is therefore impossible to perform
|
||||
A data race has Undefined Behavior, and is therefore impossible to perform
|
||||
in Safe Rust. Data races are *mostly* prevented through rust's ownership system:
|
||||
it's impossible to alias a mutable reference, so it's impossible to perform a
|
||||
data race. Interior mutability makes this more complicated, which is largely why
|
||||
|
|
@ -53,7 +53,7 @@ thread::spawn(move || {
|
|||
// bounds checked, and there's no chance of the value getting changed
|
||||
// in the middle. However our program may panic if the thread we spawned
|
||||
// managed to increment before this ran. A race condition because correct
|
||||
// program execution (panicing is rarely correct) depends on order of
|
||||
// program execution (panicking is rarely correct) depends on order of
|
||||
// thread execution.
|
||||
println!("{}", data[idx.load(Ordering::SeqCst)]);
|
||||
```
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Some examples of unsafe functions:
|
|||
|
||||
* `slice::get_unchecked` will perform unchecked indexing, allowing memory
|
||||
safety to be freely violated.
|
||||
* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is
|
||||
* `ptr::offset` is an intrinsic that invokes Undefined Behavior if it is
|
||||
not "in bounds" as defined by LLVM.
|
||||
* `mem::transmute` reinterprets some value as having the given type,
|
||||
bypassing type safety in arbitrary ways. (see [conversions] for details)
|
||||
|
|
@ -59,9 +59,9 @@ As of Rust 1.0 there are exactly two unsafe traits:
|
|||
The need for unsafe traits boils down to the fundamental property of safe code:
|
||||
|
||||
**No matter how completely awful Safe code is, it can't cause Undefined
|
||||
Behaviour.**
|
||||
Behavior.**
|
||||
|
||||
This means that Unsafe Rust, **the royal vanguard of Undefined Behaviour**, has to be
|
||||
This means that Unsafe Rust, **the royal vanguard of Undefined Behavior**, has to be
|
||||
*super paranoid* about generic safe code. To be clear, Unsafe Rust is totally free to trust
|
||||
specific safe code. Anything else would degenerate into infinite spirals of
|
||||
paranoid despair. In particular it's generally regarded as ok to trust the standard library
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ implement, and other unsafe code can assume that they are correctly
|
|||
implemented. Since they're *marker traits* (they have no associated items like
|
||||
methods), correctly implemented simply means that they have the intrinsic
|
||||
properties an implementor should have. Incorrectly implementing Send or Sync can
|
||||
cause Undefined Behaviour.
|
||||
cause Undefined Behavior.
|
||||
|
||||
Send and Sync are also automatically derived traits. This means that, unlike
|
||||
every other trait, if a type is composed entirely of Send or Sync types, then it
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ horribly unsafe thing you can do in Rust. The railguards here are dental floss.
|
|||
|
||||
`mem::transmute<T, U>` takes a value of type `T` and reinterprets it to have
|
||||
type `U`. The only restriction is that the `T` and `U` are verified to have the
|
||||
same size. The ways to cause Undefined Behaviour with this are mind boggling.
|
||||
same size. The ways to cause Undefined Behavior with this are mind boggling.
|
||||
|
||||
* First and foremost, creating an instance of *any* type with an invalid state
|
||||
is going to cause arbitrary chaos that can't really be predicted.
|
||||
|
|
@ -26,7 +26,7 @@ same size. The ways to cause Undefined Behaviour with this are mind boggling.
|
|||
`mem::transmute_copy<T, U>` somehow manages to be *even more* wildly unsafe than
|
||||
this. It copies `size_of<U>` bytes out of an `&T` and interprets them as a `U`.
|
||||
The size check that `mem::transmute` has is gone (as it may be valid to copy
|
||||
out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`.
|
||||
out a prefix), though it is Undefined Behavior for `U` to be larger than `T`.
|
||||
|
||||
Also of course you can get most of the functionality of these functions using
|
||||
pointer casts.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Unsafe code can often end up producing references or lifetimes out of thin air.
|
||||
Such lifetimes come into the world as *unbounded*. The most common source of this
|
||||
is derefencing a raw pointer, which produces a reference with an unbounded lifetime.
|
||||
is dereferencing a raw pointer, which produces a reference with an unbounded lifetime.
|
||||
Such a lifetime becomes as big as context demands. This is in fact more powerful
|
||||
than simply becoming `'static`, because for instance `&'static &'a T`
|
||||
will fail to typecheck, but the unbound lifetime will perfectly mold into
|
||||
|
|
@ -10,7 +10,7 @@ will fail to typecheck, but the unbound lifetime will perfectly mold into
|
|||
lifetime can be regarded as `'static`.
|
||||
|
||||
Almost no reference is `'static`, so this is probably wrong. `transmute` and
|
||||
`transmute_copy` are the two other primary offenders. One should endeavour to
|
||||
`transmute_copy` are the two other primary offenders. One should endeavor to
|
||||
bound an unbounded lifetime as quick as possible, especially across function
|
||||
boundaries.
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ dropping the old value: `write`, `copy`, and `copy_nonoverlapping`.
|
|||
(this is equivalent to memcpy -- note that the argument order is reversed!)
|
||||
|
||||
It should go without saying that these functions, if misused, will cause serious
|
||||
havoc or just straight up Undefined Behaviour. The only things that these
|
||||
havoc or just straight up Undefined Behavior. The only things that these
|
||||
functions *themselves* require is that the locations you want to read and write
|
||||
are allocated. However the ways writing arbitrary bits to arbitrary
|
||||
locations of memory can break things are basically uncountable!
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ All runtime-allocated memory in a Rust program begins its life as
|
|||
*uninitialized*. In this state the value of the memory is an indeterminate pile
|
||||
of bits that may or may not even reflect a valid state for the type that is
|
||||
supposed to inhabit that location of memory. Attempting to interpret this memory
|
||||
as a value of *any* type will cause Undefined Behaviour. Do Not Do This.
|
||||
as a value of *any* type will cause Undefined Behavior. Do Not Do This.
|
||||
|
||||
Rust provides mechanisms to work with uninitialized memory in checked (safe) and
|
||||
unchecked (unsafe) ways.
|
||||
unchecked (unsafe) ways.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ should only panic for programming errors or *extreme* problems.
|
|||
|
||||
Rust's unwinding strategy is not specified to be fundamentally compatible
|
||||
with any other language's unwinding. As such, unwinding into Rust from another
|
||||
language, or unwinding into another language from Rust is Undefined Behaviour.
|
||||
language, or unwinding into another language from Rust is Undefined Behavior.
|
||||
You must *absolutely* catch any panics at the FFI boundary! What you do at that
|
||||
point is up to you, but *something* must be done. If you fail to do this,
|
||||
at best, your application will crash and burn. At worst, your application *won't*
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ pub struct Vec<T> {
|
|||
If you don't care about the null-pointer optimization, then you can use the
|
||||
stable code. However we will be designing the rest of the code around enabling
|
||||
the optimization. In particular, `Unique::new` is unsafe to call, because
|
||||
putting `null` inside of it is Undefined Behaviour. Our stable Unique doesn't
|
||||
putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't
|
||||
need `new` to be unsafe because it doesn't make any interesting guarantees about
|
||||
its contents.
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Easy! How about `pop`? Although this time the index we want to access is
|
|||
initialized, Rust won't just let us dereference the location of memory to move
|
||||
the value out, because that would leave the memory uninitialized! For this we
|
||||
need `ptr::read`, which just copies out the bits from the target address and
|
||||
intrprets it as a value of type T. This will leave the memory at this address
|
||||
interprets it as a value of type T. This will leave the memory at this address
|
||||
logically uninitialized, even though there is in fact a perfectly good instance
|
||||
of T there.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
% Handling Zero-Sized Types
|
||||
|
||||
It's time. We're going to fight the spectre that is zero-sized types. Safe Rust
|
||||
It's time. We're going to fight the specter that is zero-sized types. Safe Rust
|
||||
*never* needs to care about this, but Vec is very intensive on raw pointers and
|
||||
raw allocations, which are exactly the two things that care about
|
||||
zero-sized types. We need to be careful of two things:
|
||||
|
|
|
|||
|
|
@ -3706,7 +3706,7 @@ repeated sub-expression is a coercion site for coercion to type `U`.
|
|||
Each sub-expression is a coercion site to the respective type, e.g. the
|
||||
zeroth sub-expression is a coercion site to type `U_0`.
|
||||
|
||||
* Parenthesised sub-expressions (`(e)`): if the expression has type `U`, then
|
||||
* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then
|
||||
the sub-expression is a coercion site to `U`.
|
||||
|
||||
* Blocks: if a block has type `U`, then the last expression in the block (if
|
||||
|
|
@ -4072,7 +4072,7 @@ that have since been removed):
|
|||
|
||||
* SML, OCaml: algebraic data types, pattern matching, type inference,
|
||||
semicolon statement separation
|
||||
* C++: references, RAII, smart pointers, move semantics, monomorphisation,
|
||||
* C++: references, RAII, smart pointers, move semantics, monomorphization,
|
||||
memory model
|
||||
* ML Kit, Cyclone: region based memory management
|
||||
* Haskell (GHC): typeclasses, type families
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ Organize module headers as follows:
|
|||
Avoid using `#[path="..."]` directives; make the file system and
|
||||
module hierarchy match, instead.
|
||||
|
||||
### Use the module hirearchy to organize APIs into coherent sections. [FIXME]
|
||||
### Use the module hierarchy to organize APIs into coherent sections. [FIXME]
|
||||
|
||||
> **[FIXME]** Flesh this out with examples; explain what a "coherent
|
||||
> section" is with examples.
|
||||
>
|
||||
> The module hirearchy defines both the public and internal API of your module.
|
||||
> The module hierarchy defines both the public and internal API of your module.
|
||||
> Breaking related functionality into submodules makes it understandable to both
|
||||
> users and contributors to the module.
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ io/mod.rs
|
|||
```
|
||||
|
||||
While it is possible to define all of `io` within a single directory,
|
||||
mirroring the module hirearchy in the directory structure makes
|
||||
mirroring the module hierarchy in the directory structure makes
|
||||
submodules of `io::net` easier to find.
|
||||
|
||||
### Consider top-level definitions or reexports. [FIXME: needs RFC]
|
||||
|
|
@ -104,13 +104,13 @@ while
|
|||
[`TcpStream`](https://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
|
||||
is defined in `io/net/tcp.rs` and reexported in the `io` module.
|
||||
|
||||
### Use internal module hirearchies for organization. [FIXME: needs RFC]
|
||||
### Use internal module hierarchies for organization. [FIXME: needs RFC]
|
||||
|
||||
> **[FIXME]**
|
||||
> - Referencing internal modules from the standard library is subject to
|
||||
> becoming outdated.
|
||||
|
||||
Internal module hirearchies (i.e., private submodules) may be used to
|
||||
Internal module hierarchies (i.e., private submodules) may be used to
|
||||
hide implementation details that are not part of the module's API.
|
||||
|
||||
For example, in [`std::io`](https://doc.rust-lang.org/std/io/), `mod mem`
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
> **[FIXME]** We probably want to discourage this, at least when used in a way
|
||||
> that is publicly exposed.
|
||||
|
||||
Traits that provide default implmentations for function can provide code reuse
|
||||
Traits that provide default implementations for function can provide code reuse
|
||||
across types. For example, a `print` method can be defined across multiple
|
||||
types as follows:
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Hoare in 1985.
|
|||
> dining room, furnished with a circular table, surrounded by five chairs, each
|
||||
> labelled by the name of the philosopher who was to sit in it. They sat
|
||||
> anticlockwise around the table. To the left of each philosopher there was
|
||||
> laid a golden fork, and in the centre stood a large bowl of spaghetti, which
|
||||
> laid a golden fork, and in the center stood a large bowl of spaghetti, which
|
||||
> was constantly replenished. A philosopher was expected to spend most of
|
||||
> their time thinking; but when they felt hungry, they went to the dining
|
||||
> room, sat down in their own chair, picked up their own fork on their left,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
* `pub`: denotes public visibility in `struct` fields, `impl` blocks, and modules. See [Crates and Modules (Exporting a Public Interface)].
|
||||
* `ref`: by-reference binding. See [Patterns (`ref` and `ref mut`)].
|
||||
* `return`: return from function. See [Functions (Early Returns)].
|
||||
* `Self`: implementer type alias. See [Traits].
|
||||
* `Self`: implementor type alias. See [Traits].
|
||||
* `self`: method subject. See [Method Syntax (Method Calls)].
|
||||
* `static`: global variable. See [`const` and `static` (`static`)].
|
||||
* `struct`: structure definition. See [Structs].
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
* `/` (`expr / expr`): arithmetic division. Overloadable (`Div`).
|
||||
* `/=` (`var /= expr`): arithmetic division & assignment.
|
||||
* `:` (`pat: type`, `ident: type`): constraints. See [Variable Bindings], [Functions], [Structs], [Traits].
|
||||
* `:` (`ident: expr`): struct field initialiser. See [Structs].
|
||||
* `:` (`ident: expr`): struct field initializer. See [Structs].
|
||||
* `:` (`'a: loop {…}`): loop label. See [Loops (Loops Labels)].
|
||||
* `;`: statement and item terminator.
|
||||
* `;` (`[…; len]`): part of fixed-size array syntax. See [Primitive Types (Arrays)].
|
||||
|
|
@ -153,12 +153,12 @@
|
|||
<!-- Various things involving parens and tuples -->
|
||||
|
||||
* `()`: empty tuple (*a.k.a.* unit), both literal and type.
|
||||
* `(expr)`: parenthesised expression.
|
||||
* `(expr)`: parenthesized expression.
|
||||
* `(expr,)`: single-element tuple expression. See [Primitive Types (Tuples)].
|
||||
* `(type,)`: single-element tuple type. See [Primitive Types (Tuples)].
|
||||
* `(expr, …)`: tuple expression. See [Primitive Types (Tuples)].
|
||||
* `(type, …)`: tuple type. See [Primitive Types (Tuples)].
|
||||
* `expr(expr, …)`: function call expression. Also used to initialise tuple `struct`s and tuple `enum` variants. See [Functions].
|
||||
* `expr(expr, …)`: function call expression. Also used to initialize tuple `struct`s and tuple `enum` variants. See [Functions].
|
||||
* `ident!(…)`, `ident!{…}`, `ident![…]`: macro invocation. See [Macros].
|
||||
* `expr.0`, `expr.1`, …: tuple indexing. See [Primitive Types (Tuple Indexing)].
|
||||
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ Could not compile `hello`.
|
|||
To learn more, run the command again with --verbose.
|
||||
```
|
||||
|
||||
Additionaly, variable bindings can be shadowed. This means that a later
|
||||
Additionally, variable bindings can be shadowed. This means that a later
|
||||
variable binding with the same name as another binding, that's currently in
|
||||
scope, will override the previous binding.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue