提交 a90453a1 编写于 作者: B bors

Auto merge of #25320 - steveklabnik:rollup, r=steveklabnik

- Successful merges: #25254, #25272, #25278, #25282, #25283, #25288, #25292, #25302, #25304, #25314
- Failed merges: 
......@@ -31,23 +31,27 @@ You may also be interested in the [grammar].
## Unicode productions
A few productions in Rust's grammar permit Unicode code points outside the ASCII
range. We define these productions in terms of character properties specified
in the Unicode standard, rather than in terms of ASCII-range code points. The
section [Special Unicode Productions](#special-unicode-productions) lists these
productions.
A few productions in Rust's grammar permit Unicode code points outside the
ASCII range. We define these productions in terms of character properties
specified in the Unicode standard, rather than in terms of ASCII-range code
points. The grammar has a [Special Unicode Productions][unicodeproductions]
section that lists these productions.
[unicodeproductions]: grammar.html#special-unicode-productions
## String table productions
Some rules in the grammar — notably [unary
operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), and [keywords](#keywords) — are
operators](#binary-operator-expressions), and [keywords][keywords] — are
given in a simplified form: as a listing of a table of unquoted, printable
whitespace-separated strings. These cases form a subset of the rules regarding
the [token](#tokens) rule, and are assumed to be the result of a
lexical-analysis phase feeding the parser, driven by a DFA, operating over the
disjunction of all such string table entries.
[keywords]: grammar.html#keywords
When such a string enclosed in double-quotes (`"`) occurs inside the grammar,
it is an implicit reference to a single member of such a string table
production. See [tokens](#tokens) for more information.
......@@ -75,7 +79,7 @@ An identifier is any nonempty Unicode[^non_ascii_idents] string of the following
- The first character has property `XID_start`
- The remaining characters have property `XID_continue`
that does _not_ occur in the set of [keywords](#keywords).
that does _not_ occur in the set of [keywords][keywords].
> **Note**: `XID_start` and `XID_continue` as character properties cover the
> character ranges used to form the more familiar C and Java language-family
......@@ -401,7 +405,7 @@ Symbols are a general class of printable [token](#tokens) that play structural
roles in a variety of grammar productions. They are catalogued here for
completeness as the set of remaining miscellaneous printable tokens that do not
otherwise appear as [unary operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), or [keywords](#keywords).
operators](#binary-operator-expressions), or [keywords][keywords].
## Paths
......@@ -547,7 +551,7 @@ _name_ s that occur in its body. At the "current layer", they all must repeat
the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $(
($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not
`(a,b,c ; d,e)`. The repetition walks through the choices at that layer in
lockstep, so the former input transcribes to `( (a,d), (b,e), (c,f) )`.
lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`.
Nested repetitions are allowed.
......@@ -611,7 +615,7 @@ module needs its own source file: [module definitions](#modules) can be nested
within one file.
Each source file contains a sequence of zero or more `item` definitions, and
may optionally begin with any number of [attributes](#Items and attributes)
may optionally begin with any number of [attributes](#items-and-attributes)
that apply to the containing module, most of which influence the behavior of
the compiler. The anonymous crate module can have additional attributes that
apply to the crate as a whole.
......@@ -653,7 +657,7 @@ There are several kinds of item:
* [`use` declarations](#use-declarations)
* [modules](#modules)
* [functions](#functions)
* [type aliases](#type-aliases)
* [type definitions](grammar.html#type-definitions)
* [structures](#structures)
* [enumerations](#enumerations)
* [constant items](#constant-items)
......@@ -773,7 +777,7 @@ extern crate std as ruststd; // linking to 'std' under another name
A _use declaration_ creates one or more local name bindings synonymous with
some other [path](#paths). Usually a `use` declaration is used to shorten the
path required to refer to a module item. These declarations may appear at the
top of [modules](#modules) and [blocks](#blocks).
top of [modules](#modules) and [blocks](grammar.html#block-expressions).
> **Note**: Unlike in many languages,
> `use` declarations in Rust do *not* declare linkage dependency with external crates.
......@@ -1144,9 +1148,7 @@ let px: i32 = match p { Point(x, _) => x };
```
A _unit-like struct_ is a structure without any fields, defined by leaving off
the list of fields entirely. Such types will have a single value, just like
the [unit value `()`](#unit-and-boolean-literals) of the unit type. For
example:
the list of fields entirely. Such types will have a single value. For example:
```
struct Cookie;
......@@ -2436,11 +2438,6 @@ comma:
(0); // zero in parentheses
```
### Unit expressions
The expression `()` denotes the _unit value_, the only value of the type with
the same name.
### Structure expressions
There are several forms of structure expressions. A _structure expression_
......@@ -3281,7 +3278,7 @@ constructor or `struct` field may refer, directly or indirectly, to the
enclosing `enum` or `struct` type itself. Such recursion has restrictions:
* Recursive types must include a nominal type in the recursion
(not mere [type definitions](#type-definitions),
(not mere [type definitions](grammar.html#type-definitions),
or other structural types such as [arrays](#array,-and-slice-types) or [tuples](#tuple-types)).
* A recursive `enum` item must have at least one non-recursive constructor
(in order to give the recursion a basis case).
......
......@@ -176,7 +176,7 @@ for a full example, the core of which is reproduced here:
```ignore
declare_lint!(TEST_LINT, Warn,
"Warn about items named 'lintme'")
"Warn about items named 'lintme'");
struct Pass;
......
......@@ -127,12 +127,12 @@ fn grow(&self) -> Circle {
We just say we’re returning a `Circle`. With this method, we can grow a new
circle to any arbitrary size.
# Static methods
# Associated functions
You can also define static methods that do not take a `self` parameter. Here’s a
pattern that’s very common in Rust code:
You can also define associated functions that do not take a `self` parameter.
Here’s a pattern that’s very common in Rust code:
```
```rust
struct Circle {
x: f64,
y: f64,
......
% The Stack and the Heap
Coming Soon
As a systems language, Rust operates at a low level. If you’re coming from a
high-level language, there are some aspects of systems programming that you may
not be familiar with. The most important one is how memory works, with a stack
and a heap. If you’re familiar with how C-like languages use stack allocation,
this chapter will be a refresher. If you’re not, you’ll learn about this more
general concept, but with a Rust-y focus.
# Memory management
These two terms are about memory management. The stack and the heap are
abstractions that help you determine when to allocate and deallocate memory.
Here’s a high-level comparison:
The stack is very fast, and is where memory is allocated in Rust by default.
But the allocation is local to a function call, and is limited in size. The
heap, on the other hand, is slower, and is explicitly allocated by your
program. But it’s effectively unlimited in size, and is globally accessible.
# The Stack
Let’s talk about this Rust program:
```rust
fn main() {
let x = 42;
}
```
This program has one variable binding, `x`. This memory needs to be allocated
from somewhere. Rust ‘stack allocates’ by default, which means that basic
values ‘go on the stack’. What does that mean?
Well, when a function gets called, some memory gets allocated for all of its
local variables and some other information. This is called a ‘stack frame’, and
for the purpose of this tutorial, we’re going to ignore the extra information
and just consider the local variables we’re allocating. So in this case, when
`main()` is run, we’ll allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see, we didn’t have to write
any special Rust code or anything.
When the function is over, its stack frame gets deallocated. This happens
automatically, we didn’t have to do anything special here.
That’s all there is for this simple program. The key thing to understand here
is that stack allocation is very, very fast. Since we know all the local
variables we have ahead of time, we can grab the memory all at once. And since
we’ll throw them all away at the same time as well, we can get rid of it very
fast too.
The downside is that we can’t keep values around if we need them for longer
than a single function. We also haven’t talked about what that name, ‘stack’
means. To do that, we need a slightly more complicated example:
```rust
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo();
}
```
This program has three variables total: two in `foo()`, one in `main()`. Just
as before, when `main()` is called, a single integer is allocated for its stack
frame. But before we can show what happens when `foo()` is called, we need to
visualize what’s going on with memory. Your operating system presents a view of
memory to your program that’s pretty simple: a huge list of addresses, from 0
to a large number, representing how much RAM your computer has. For example, if
you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,824`. That
number comes from 2<sup>30</sup>, the number of bytes in a gigabyte.
This memory is kind of like a giant array: addresses start at zero and go
up to the final number. So here’s a diagram of our first stack frame:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
We’ve got `x` located at address `0`, with the value `42`.
When `foo()` is called, a new stack frame is allocated:
| Address | Name | Value |
+---------+------+-------+
| 2 | z | 100 |
| 1 | y | 5 |
| 0 | x | 42 |
Because `0` was taken by the first frame, `1` and `2` are used for `foo()`’s
stack frame. It grows upward, the more functions we call.
There’s some important things we have to take note of here. The numbers 0, 1,
and 2 are all solely for illustrative purposes, and bear no relationship to the
actual numbers the computer will actually use. In particular, the series of
addresses are in reality going to be separated by some number of bytes that
separate each address, and that separation may even exceed the size of the
value being stored.
After `foo()` is over, its frame is deallocated:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
And then, after `main()`, even this last value goes away. Easy!
It’s called a ‘stack’ because it works like a stack of dinner plates: the first
plate you put down is the last plate to pick back up. Stacks are sometimes
called ‘last in, first out queues’ for this reason, as the last value you put
on the stack is the first one you retrieve from it.
Let’s try a three-deep example:
```rust
fn bar() {
let i = 6;
}
fn foo() {
let a = 5;
let b = 100;
let c = 1;
bar();
}
fn main() {
let x = 42;
foo();
}
```
Okay, first, we call `main()`:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
Next up, `main()` calls `foo()`:
| Address | Name | Value |
+---------+------+-------+
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` calls `bar()`:
| Address | Name | Value |
+---------+------+-------+
| 4 | i | 6 |
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
Whew! Our stack is growing tall.
After `bar()` is over, its frame is deallocated, leaving just `foo()` and
`main()`:
| Address | Name | Value |
+---------+------+-------+
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` ends, leaving just `main()`
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
And then we’re done. Getting the hang of it? It’s like piling up dishes: you
add to the top, you take away from the top.
# The Heap
Now, this works pretty well, but not everything can work like this. Sometimes,
you need to pass some memory between different functions, or keep it alive for
longer than a single function’s execution. For this, we can use the heap.
In Rust, you can allocate memory on the heap with the [`Box<T>` type][box].
Here’s an example:
```rust
fn main() {
let x = Box::new(5);
let y = 42;
}
```
[box]: ../std/boxed/index.html
Here’s what happens in memory when `main()` is called:
| Address | Name | Value |
+---------+------+--------+
| 1 | y | 42 |
| 0 | x | ?????? |
We allocate space for two variables on the stack. `y` is `42`, as it always has
been, but what about `x`? Well, `x` is a `Box<i32>`, and boxes allocate memory
on the heap. The actual value of the box is a structure which has a pointer to
‘the heap’. When we start executing the function, and `Box::new()` is called,
it allocates some memory for the heap, and puts `5` there. The memory now looks
like this:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 5 |
| ... | ... | ... |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
our stack grows from zero, the easiest place to allocate memory is from the
other end. So our first value is at the highest place in memory. And the value
of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve
allocated on the heap, so the value of `x` is 2<sup>30</sup>, the memory
location we’ve asked for.
[rawpointer]: raw-pointers.html
We haven’t really talked too much about what it actually means to allocate and
deallocate memory in these contexts. Getting into very deep detail is out of
the scope of this tutorial, but what’s important to point out here is that
the heap isn’t just a stack that grows from the opposite end. We’ll have an
example of this later in the book, but because the heap can be allocated and
freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory
layout of a program which has been running for a while now:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 5 |
| (2<sup>30</sup>) - 1 | | |
| (2<sup>30</sup>) - 2 | | |
| (2<sup>30</sup>) - 3 | | 42 |
| ... | ... | ... |
| 3 | y | (2<sup>30</sup>) - 3 |
| 2 | y | 42 |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
In this case, we’ve allocated four things on the heap, but deallocated two of
them. There’s a gap between 2<sup>30</sup> and (2<sup>30</sup>) - 3 which isn’t
currently being used. The specific details of how and why this happens depends
on what kind of strategy you use to manage the heap. Different programs can use
different ‘memory allocators’, which are libraries that manage this for you.
Rust programs use [jemalloc][jemalloc] for this purpose.
[jemalloc]: http://www.canonware.com/jemalloc/
Anyway, back to our example. Since this memory is on the heap, it can stay
alive longer than the function which allocates the box. In this case, however,
it doesn’t.[^moving] When the function is over, we need to free the stack frame
for `main()`. `Box<T>`, though, has a trick up its sleve: [Drop][drop]. The
implementation of `Drop` for `Box` deallocates the memory that was allocated
when it was created. Great! So when `x` goes away, it first frees the memory
allocated on the heap:
| Address | Name | Value |
+---------+------+--------+
| 1 | y | 42 |
| 0 | x | ?????? |
[drop]: drop.html
[moving]: We can make the memory live longer by transferring ownership,
sometimes called ‘moving out of the box’. More complex examples will
be covered later.
And then the stack frame goes away, freeing all of our memory.
# Arguments and borrowing
We’ve got some basic examples with the stack and the heap going, but what about
function arguments and borrowing? Here’s a small Rust program:
```rust
fn foo(i: &i32) {
let z = 42;
}
fn main() {
let x = 5;
let y = &x;
foo(y);
}
```
When we enter `main()`, memory looks like this:
| Address | Name | Value |
+---------+------+-------+
| 1 | y | 0 |
| 0 | x | 5 |
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
memory location that `x` lives at, which in this case is `0`.
What about when we call `foo()`, passing `y` as an argument?
| Address | Name | Value |
+---------+------+-------+
| 3 | z | 42 |
| 2 | i | 0 |
| 1 | y | 0 |
| 0 | x | 5 |
Stack frames aren’t just for local bindings, they’re for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is
`i`’s.
This is one reason why borrowing a variable doesn’t deallocate any memory: the
value of a reference is just a pointer to a memory location. If we got rid of
the underlying memory, things wouldn’t work very well.
# A complex example
Okay, let’s go through this complex program step-by-step:
```rust
fn foo(x: &i32) {
let y = 10;
let z = &y;
baz(z);
bar(x, z);
}
fn bar(a: &i32, b: &i32) {
let c = 5;
let d = Box::new(5);
let e = &d;
baz(e);
}
fn baz(f: &i32) {
let g = 100;
}
fn main() {
let h = 3;
let i = Box::new(20);
let j = &h;
foo(j);
}
```
First, we call `main()`:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
value pointing there.
Next, at the end of `main()`, `foo()` gets called:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
as `j`, since that’s what we passed it in. It’s a pointer to the `0` address,
since `j` points at `h`.
Next, `foo()` calls `baz()`, passing `z`:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 7 | g | 100 |
| 6 | f | 4 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
over, we get rid of its stack frame:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, `foo()` calls `bar()` with `x` and `z`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We end up allocating another value on the heap, and so we have to subtract one
from 2<sup>30</sup>. It’s easier to just write that than `1,073,741,823`. In any
case, we set up the variables as usual.
At the end of `bar()`, it calls `baz()`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 12 | g | 100 |
| 11 | f | 4 |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
With this, we’re at our deepest point! Whew! Congrats for following along this
far.
After `baz()` is over, we get rid of `f` and `g`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
what it points to: (2<sup>30</sup>) - 1.
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And after that, `foo()` returns:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
it will clean up the last of the heap too.
# What do other languages do?
Most languages with a garbage collector heap-allocate by default. This means
that every value is boxed. There are a number of reasons why this is done, but
they’re out of scope for this tutorial. There are some possible optimizations
that don’t make it true 100% of the time, too. Rather than relying on the stack
and `Drop` to clean up memory, the garbage collector deals with the heap
instead.
# Which to use?
So if the stack is faster and easier to manage, why do we need the heap? A big
reason is that Stack-allocation alone means you only have LIFO semantics for
reclaiming storage. Heap-allocation is strictly more general, allowing storage
to be taken from and returned to the pool in arbitrary order, but at a
complexity cost.
Generally, you should prefer stack allocation, and so, Rust stack-allocates by
default. The LIFO model of the stack is simpler, at a fundamental level. This
has two big impacts: runtime efficiency and semantic impact.
## Runtime Efficiency.
Managing the memory for the stack is trivial: The machine just
increments or decrements a single value, the so-called “stack pointer”.
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
arbitrary points, and each block of heap-allocated memory can be of arbitrary
size, the memory manager must generally work much harder to identify memory for
reuse.
If you’d like to dive into this topic in greater detail, [this paper][wilson]
is a great introduction.
[wilson]: http://www.cs.northwestern.edu/~pdinda/icsclass/doc/dsa.pdf
## Semantic impact
Stack-allocation impacts the Rust language itself, and thus the developer’s
mental model. The LIFO semantics is what drives how the Rust language handles
automatic memory management. Even the deallocation of a uniquely-owned
heap-allocated box can be driven by the stack-based LIFO semantics, as
discussed throughout this chapter. The flexibility (i.e. expressiveness) of non
LIFO-semantics means that in general the compiler cannot automatically infer at
compile-time where memory should be freed; it has to rely on dynamic protocols,
potentially from outside the language itself, to drive deallocation (reference
counting, as used by `Rc<T>` and `Arc<T>`, is one example of this).
When taken to the extreme, the increased expressive power of heap allocation
comes at the cost of either significant runtime support (e.g. in the form of a
garbage collector) or significant programmer effort (in the form of explicit
memory management calls that require verification not provided by the Rust
compiler).
......@@ -8,6 +8,15 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::{isize, usize};
#[inline(always)]
fn check_size_and_alignment(size: usize, align: usize) {
debug_assert!(size != 0);
debug_assert!(size <= isize::MAX as usize, "Tried to allocate too much: {} bytes", size);
debug_assert!(usize::is_power_of_two(align), "Invalid alignment of allocation: {}", align);
}
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
/// Return a pointer to `size` bytes of memory aligned to `align`.
......@@ -19,6 +28,7 @@
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
check_size_and_alignment(size, align);
imp::allocate(size, align)
}
......@@ -38,6 +48,7 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
check_size_and_alignment(size, align);
imp::reallocate(ptr, old_size, size, align)
}
......@@ -56,6 +67,7 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usiz
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
align: usize) -> usize {
check_size_and_alignment(size, align);
imp::reallocate_inplace(ptr, old_size, size, align)
}
......
......@@ -1537,7 +1537,7 @@ pub fn shrink_to_fit(&mut self) {
bit_vec.nbits = trunc_len * u32::BITS;
}
/// Iterator over each u32 stored in the `BitSet`.
/// Iterator over each usize stored in the `BitSet`.
///
/// # Examples
///
......@@ -1558,7 +1558,7 @@ pub fn iter(&self) -> bit_set::Iter {
SetIter {set: self, next_idx: 0}
}
/// Iterator over each u32 stored in `self` union `other`.
/// Iterator over each usize stored in `self` union `other`.
/// See [union_with](#method.union_with) for an efficient in-place version.
///
/// # Examples
......@@ -1658,7 +1658,7 @@ fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 }
})
}
/// Iterator over each u32 stored in the symmetric difference of `self` and `other`.
/// Iterator over each usize stored in the symmetric difference of `self` and `other`.
/// See [symmetric_difference_with](#method.symmetric_difference_with) for
/// an efficient in-place version.
///
......
......@@ -745,6 +745,7 @@ fn baz() {
For example:
```
let x: i32 = "I am not a number!";
// ~~~ ~~~~~~~~~~~~~~~~~~~~
// | |
......@@ -752,6 +753,7 @@ fn baz() {
// | compiler infers type `&str`
// |
// type `i32` assigned to variable `x`
```
"##,
E0309: r##"
......@@ -760,6 +762,7 @@ fn baz() {
must be as long as the data needs to be alive, and missing the constraint that
denotes this will cause this error.
```
// This won't compile because T is not constrained, meaning the data
// stored in it is not guaranteed to last as long as the reference
struct Foo<'a, T> {
......@@ -770,6 +773,7 @@ struct Foo<'a, T> {
struct Foo<'a, T: 'a> {
foo: &'a T
}
```
"##,
E0310: r##"
......@@ -778,6 +782,7 @@ struct Foo<'a, T: 'a> {
must be as long as the data needs to be alive, and missing the constraint that
denotes this will cause this error.
```
// This won't compile because T is not constrained to the static lifetime
// the reference needs
struct Foo<T> {
......@@ -788,6 +793,7 @@ struct Foo<T> {
struct Foo<T: 'static> {
foo: &'static T
}
```
"##
}
......
......@@ -1603,7 +1603,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
Some(i as usize)),
_ => {
span_err!(tcx.sess, ast_ty.span, E0249,
"expected constant expr for array length");
"expected constant integer expression \
for array length");
this.tcx().types.err
}
}
......
......@@ -150,6 +150,148 @@ enum Empty {}
```
fn(isize, *const *const u8) -> isize
```
"##,
E0184: r##"
Explicitly implementing both Drop and Copy for a type is currently disallowed.
This feature can make some sense in theory, but the current implementation is
incorrect and can lead to memory unsafety (see [issue #20126][iss20126]), so
it has been disabled for now.
[iss20126]: https://github.com/rust-lang/rust/issues/20126
"##,
E0204: r##"
An attempt to implement the `Copy` trait for a struct failed because one of the
fields does not implement `Copy`. To fix this, you must implement `Copy` for the
mentioned field. Note that this may not be possible, as in the example of
```
struct Foo {
foo : Vec<u32>,
}
impl Copy for Foo { }
```
This fails because `Vec<T>` does not implement `Copy` for any `T`.
Here's another example that will fail:
```
#[derive(Copy)]
struct Foo<'a> {
ty: &'a mut bool,
}
```
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`).
"##,
E0205: r##"
An attempt to implement the `Copy` trait for an enum failed because one of the
variants does not implement `Copy`. To fix this, you must implement `Copy` for
the mentioned variant. Note that this may not be possible, as in the example of
```
enum Foo {
Bar(Vec<u32>),
Baz,
}
impl Copy for Foo { }
```
This fails because `Vec<T>` does not implement `Copy` for any `T`.
Here's another example that will fail:
```
#[derive(Copy)]
enum Foo<'a> {
Bar(&'a mut bool),
Baz
}
```
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`).
"##,
E0206: r##"
You can only implement `Copy` for a struct or enum. Both of the following
examples will fail, because neither `i32` (primitive type) nor `&'static Bar`
(reference to `Bar`) is a struct or enum:
```
type Foo = i32;
impl Copy for Foo { } // error
#[derive(Copy, Clone)]
struct Bar;
impl Copy for &'static Bar { } // error
```
"##,
E0243: r##"
This error indicates that not enough type parameters were found in a type or
trait.
For example, the `Foo` struct below is defined to be generic in `T`, but the
type parameter is missing in the definition of `Bar`:
```
struct Foo<T> { x: T }
struct Bar { x: Foo }
```
"##,
E0244: r##"
This error indicates that too many type parameters were found in a type or
trait.
For example, the `Foo` struct below has no type parameters, but is supplied
with two in the definition of `Bar`:
```
struct Foo { x: bool }
struct Bar<S, T> { x: Foo<S, T> }
```
"##,
E0249: r##"
This error indicates a constant expression for the array length was found, but
it was not an integer (signed or unsigned) expression.
Some examples of code that produces this error are:
```
const A: [u32; "hello"] = []; // error
const B: [u32; true] = []; // error
const C: [u32; 0.0] = []; // error
"##,
E0250: r##"
This means there was an error while evaluating the expression for the length of
a fixed-size array type.
Some examples of code that produces this error are:
```
// divide by zero in the length expression
const A: [u32; 1/0] = [];
// Rust currently will not evaluate the function `foo` at compile time
fn foo() -> usize { 12 }
const B: [u32; foo()] = [];
// it is an error to try to add `u8` and `f64`
use std::{f64, u8};
const C: [u32; u8::MAX + f64::EPSILON] = [];
```
"##
}
......@@ -164,18 +306,18 @@ enum Empty {}
E0030,
E0031,
E0033,
E0034,
E0035,
E0036,
E0038,
E0034, // multiple applicable methods in scope
E0035, // does not take type parameters
E0036, // incorrect number of type parameters given for this method
E0038, // cannot convert to a trait object because trait is not object-safe
E0040, // explicit use of destructor method
E0044,
E0045,
E0044, // foreign items may not have type parameters
E0045, // variadic function must have C calling convention
E0049,
E0050,
E0053,
E0055,
E0057,
E0055, // method has an incompatible type for trait
E0057, // method has an incompatible type for trait
E0059,
E0060,
E0061,
......@@ -232,7 +374,6 @@ enum Empty {}
E0178,
E0182,
E0183,
E0184,
E0185,
E0186,
E0187, // can't infer the kind of the closure
......@@ -254,12 +395,6 @@ enum Empty {}
E0202, // associated items are not allowed in inherent impls
E0203, // type parameter has more than one relaxed default bound,
// and only one is supported
E0204, // trait `Copy` may not be implemented for this type; field
// does not implement `Copy`
E0205, // trait `Copy` may not be implemented for this type; variant
// does not implement `copy`
E0206, // trait `Copy` may not be implemented for this type; type is
// not a structure or enumeration
E0207, // type parameter is not constrained by the impl trait, self type, or predicate
E0208,
E0209, // builtin traits can only be implemented on structs or enums
......@@ -296,14 +431,10 @@ enum Empty {}
E0240,
E0241,
E0242, // internal error looking up a definition
E0243, // wrong number of type arguments
E0244, // wrong number of type arguments
E0245, // not a trait
E0246, // illegal recursive type
E0247, // found module name used as a type
E0248, // found value name used as a type
E0249, // expected constant expr for array length
E0250, // expected constant expr for array length
E0318, // can't create default impls for traits outside their crates
E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
......
......@@ -1199,7 +1199,7 @@ fn into(self) -> OsString {
/// absolute, and so on. More details about the overall approach can be found in
/// the module documentation.
///
/// This is an *unsized* type, meaning that it must always be used with behind a
/// This is an *unsized* type, meaning that it must always be used behind a
/// pointer like `&` or `Box`.
///
/// # Examples
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册