Skip to content

File tree

26 files changed

+401
-124
lines changed

26 files changed

+401
-124
lines changed
 

‎.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ matrix:
1212
fast_finish: true
1313
include:
1414
# Images used in testing PR and try-build should be run first.
15-
- env: IMAGE=x86_64-gnu-llvm-3.7 RUST_BACKTRACE=1
15+
- env: IMAGE=x86_64-gnu-llvm-3.9 RUST_BACKTRACE=1
1616
if: type = pull_request OR branch = auto
1717

1818
- env: IMAGE=dist-x86_64-linux DEPLOY=1

‎CONTRIBUTING.md

+110
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,116 @@ In order to prepare your PR, you can run the build locally by doing
365365
there, you may wish to set `submodules = false` in the `config.toml`
366366
to prevent `x.py` from resetting to the original branch.
367367

368+
#### Breaking Tools Built With The Compiler
369+
[breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler
370+
371+
Rust's build system builds a number of tools that make use of the
372+
internals of the compiler. This includes clippy,
373+
[RLS](https://github.com/rust-lang-nursery/rls) and
374+
[rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools
375+
break because of your changes, you may run into a sort of "chicken and egg"
376+
problem. These tools rely on the latest compiler to be built so you can't update
377+
them to reflect your changes to the compiler until those changes are merged into
378+
the compiler. At the same time, you can't get your changes merged into the compiler
379+
because the rust-lang/rust build won't pass until those tools build and pass their
380+
tests.
381+
382+
That means that, in the default state, you can't update the compiler without first
383+
fixing rustfmt, rls and the other tools that the compiler builds.
384+
385+
Luckily, a feature was [added to Rust's build](https://github.com/rust-lang/rust/pull/45243)
386+
to make all of this easy to handle. The idea is that you mark the tools as "broken",
387+
so that the rust-lang/rust build passes without trying to build them, then land the change
388+
in the compiler, wait for a nightly, and go update the tools that you broke. Once you're done
389+
and the tools are working again, you go back in the compiler and change the tools back
390+
from "broken".
391+
392+
This should avoid a bunch of synchronization dances and is also much easier on contributors as
393+
there's no need to block on rls/rustfmt/other tools changes going upstream.
394+
395+
Here are those same steps in detail:
396+
397+
1. (optional) First, if it doesn't exist already, create a `config.toml` by copying
398+
`config.toml.example` in the root directory of the Rust repository.
399+
Set `submodules = false` in the `[build]` section. This will prevent `x.py`
400+
from resetting to the original branch after you make your changes. If you
401+
need to [update any submodules to their latest versions][updating-submodules],
402+
see the section of this file about that for more information.
403+
2. (optional) Run `./x.py test src/tools/rustfmt` (substituting the submodule
404+
that broke for `rustfmt`). Fix any errors in the submodule (and possibly others).
405+
3. (optional) Make commits for your changes and send them to upstream repositories as a PR.
406+
4. (optional) Maintainers of these submodules will **not** merge the PR. The PR can't be
407+
merged because CI will be broken. You'll want to write a message on the PR referencing
408+
your change, and how the PR should be merged once your change makes it into a nightly.
409+
5. Update `src/tools/toolstate.toml` to indicate that the tool in question is "broken",
410+
that will disable building it on CI. See the documentation in that file for the exact
411+
configuration values you can use.
412+
6. Commit the changes to `src/tools/toolstate.toml`, **do not update submodules in your commit**,
413+
and then update the PR you have for rust-lang/rust.
414+
7. Wait for your PR to merge.
415+
8. Wait for a nightly
416+
9. (optional) Help land your PR on the upstream repository now that your changes are in nightly.
417+
10. (optional) Send a PR to rust-lang/rust updating the submodule, reverting `src/tools/toolstate.toml` back to a "building" or "testing" state.
418+
419+
#### Updating submodules
420+
[updating-submodules]: #updating-submodules
421+
422+
These instructions are specific to updating `rustfmt`, however they may apply
423+
to the other submodules as well. Please help by improving these instructions
424+
if you find any discrepencies or special cases that need to be addressed.
425+
426+
To update the `rustfmt` submodule, start by running the appropriate
427+
[`git submodule` command](https://git-scm.com/book/en/v2/Git-Tools-Submodules).
428+
For example, to update to the latest commit on the remote master branch,
429+
you may want to run:
430+
```
431+
git submodule update --remote src/tools/rustfmt
432+
```
433+
If you run `./x.py build` now, and you are lucky, it may just work. If you see
434+
an error message about patches that did not resolve to any crates, you will need
435+
to complete a few more steps which are outlined with their rationale below.
436+
437+
*(This error may change in the future to include more information.)*
438+
```
439+
error: failed to resolve patches for `https://github.com/rust-lang-nursery/rustfmt`
440+
441+
Caused by:
442+
patch for `rustfmt-nightly` in `https://github.com/rust-lang-nursery/rustfmt` did not resolve to any crates
443+
failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml
444+
```
445+
446+
If you haven't used the `[patch]`
447+
section of `Cargo.toml` before, there is [some relevant documentation about it
448+
in the cargo docs](http://doc.crates.io/manifest.html#the-patch-section). In
449+
addition to that, you should read the
450+
[Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#overriding-dependencies)
451+
section of the documentation as well.
452+
453+
Specifically, the following [section in Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#testing-a-bugfix) reveals what the problem is:
454+
455+
> Next up we need to ensure that our lock file is updated to use this new version of uuid so our project uses the locally checked out copy instead of one from crates.io. The way [patch] works is that it'll load the dependency at ../path/to/uuid and then whenever crates.io is queried for versions of uuid it'll also return the local version.
456+
>
457+
> This means that the version number of the local checkout is significant and will affect whether the patch is used. Our manifest declared uuid = "1.0" which means we'll only resolve to >= 1.0.0, < 2.0.0, and Cargo's greedy resolution algorithm also means that we'll resolve to the maximum version within that range. Typically this doesn't matter as the version of the git repository will already be greater or match the maximum version published on crates.io, but it's important to keep this in mind!
458+
459+
This says that when we updated the submodule, the version number in our
460+
`src/tools/rustfmt/Cargo.toml` changed. The new version is different from
461+
the version in `Cargo.lock`, so the build can no longer continue.
462+
463+
To resolve this, we need to update `Cargo.lock`. Luckily, cargo provides a
464+
command to do this easily.
465+
466+
First, go into the `src/` directory since that is where `Cargo.toml` is in
467+
the rust repository. Then run, `cargo update -p rustfmt-nightly` to solve
468+
the problem.
469+
470+
```
471+
$ cd src
472+
$ cargo update -p rustfmt-nightly
473+
```
474+
475+
This should change the version listed in `src/Cargo.lock` to the new version you updated
476+
the submodule to. Running `./x.py build` should work now.
477+
368478
## Writing Documentation
369479
[writing-documentation]: #writing-documentation
370480

‎config.toml.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
# If an external LLVM root is specified, we automatically check the version by
3636
# default to make sure it's within the range that we're expecting, but setting
3737
# this flag will indicate that this version check should not be done.
38-
#version-check = false
38+
#version-check = true
3939

4040
# Link libstdc++ statically into the librustc_llvm instead of relying on a
4141
# dynamic version to be available.

‎src/bootstrap/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ impl Config {
299299
let mut config = Config::default();
300300
config.llvm_enabled = true;
301301
config.llvm_optimize = true;
302+
config.llvm_version_check = true;
302303
config.use_jemalloc = true;
303304
config.backtrace = true;
304305
config.rust_optimize = true;

‎src/bootstrap/native.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,14 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
259259

260260
let mut cmd = Command::new(llvm_config);
261261
let version = output(cmd.arg("--version"));
262-
if version.starts_with("3.5") || version.starts_with("3.6") ||
263-
version.starts_with("3.7") {
264-
return
262+
let mut parts = version.split('.').take(2)
263+
.filter_map(|s| s.parse::<u32>().ok());
264+
if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
265+
if major > 3 || (major == 3 && minor >= 9) {
266+
return
267+
}
265268
}
266-
panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
269+
panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
267270
}
268271

269272
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]

‎src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile ‎src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
1111
cmake \
1212
sudo \
1313
gdb \
14-
llvm-3.7-tools \
14+
llvm-3.9-tools \
1515
libedit-dev \
1616
zlib1g-dev \
1717
xz-utils
1818

1919
COPY scripts/sccache.sh /scripts/
2020
RUN sh /scripts/sccache.sh
2121

22+
# using llvm-link-shared due to libffi issues -- see #34486
2223
ENV RUST_CONFIGURE_ARGS \
2324
--build=x86_64-unknown-linux-gnu \
24-
--llvm-root=/usr/lib/llvm-3.7
25+
--llvm-root=/usr/lib/llvm-3.9 \
26+
--enable-llvm-link-shared
2527
ENV RUST_CHECK_TARGET check

‎src/doc/unstable-book/src/language-features/lang-items.md

+92
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,95 @@ A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_
227227
flag is set in the options of the compilation target. It allows customizing the
228228
process of resuming unwind at the end of the landing pads. The language item's name
229229
is `eh_unwind_resume`.
230+
231+
## List of all language items
232+
233+
This is a list of all language items in Rust along with where they are located in
234+
the source code.
235+
236+
- Primitives
237+
- `i8`: `libcore/num/mod.rs`
238+
- `i16`: `libcore/num/mod.rs`
239+
- `i32`: `libcore/num/mod.rs`
240+
- `i64`: `libcore/num/mod.rs`
241+
- `i128`: `libcore/num/mod.rs`
242+
- `isize`: `libcore/num/mod.rs`
243+
- `u8`: `libcore/num/mod.rs`
244+
- `u16`: `libcore/num/mod.rs`
245+
- `u32`: `libcore/num/mod.rs`
246+
- `u64`: `libcore/num/mod.rs`
247+
- `u128`: `libcore/num/mod.rs`
248+
- `usize`: `libcore/num/mod.rs`
249+
- `f32`: `libstd/f32.rs`
250+
- `f64`: `libstd/f64.rs`
251+
- `char`: `libstd_unicode/char.rs`
252+
- `slice`: `liballoc/slice.rs`
253+
- `str`: `liballoc/str.rs`
254+
- `const_ptr`: `libcore/ptr.rs`
255+
- `mut_ptr`: `libcore/ptr.rs`
256+
- `unsafe_cell`: `libcore/cell.rs`
257+
- Runtime
258+
- `start`: `libstd/rt.rs`
259+
- `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
260+
- `eh_personality`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU)
261+
- `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
262+
- `eh_unwind_resume`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU)
263+
- `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC)
264+
- `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH)
265+
- `panic`: `libcore/panicking.rs`
266+
- `panic_bounds_check`: `libcore/panicking.rs`
267+
- `panic_fmt`: `libcore/panicking.rs`
268+
- `panic_fmt`: `libstd/panicking.rs`
269+
- Allocations
270+
- `owned_box`: `liballoc/boxed.rs`
271+
- `exchange_malloc`: `liballoc/heap.rs`
272+
- `box_free`: `liballoc/heap.rs`
273+
- Operands
274+
- `not`: `libcore/ops/bit.rs`
275+
- `bitand`: `libcore/ops/bit.rs`
276+
- `bitor`: `libcore/ops/bit.rs`
277+
- `bitxor`: `libcore/ops/bit.rs`
278+
- `shl`: `libcore/ops/bit.rs`
279+
- `shr`: `libcore/ops/bit.rs`
280+
- `bitand_assign`: `libcore/ops/bit.rs`
281+
- `bitor_assign`: `libcore/ops/bit.rs`
282+
- `bitxor_assign`: `libcore/ops/bit.rs`
283+
- `shl_assign`: `libcore/ops/bit.rs`
284+
- `shr_assign`: `libcore/ops/bit.rs`
285+
- `deref`: `libcore/ops/deref.rs`
286+
- `deref_mut`: `libcore/ops/deref.rs`
287+
- `index`: `libcore/ops/index.rs`
288+
- `index_mut`: `libcore/ops/index.rs`
289+
- `add`: `libcore/ops/arith.rs`
290+
- `sub`: `libcore/ops/arith.rs`
291+
- `mul`: `libcore/ops/arith.rs`
292+
- `div`: `libcore/ops/arith.rs`
293+
- `rem`: `libcore/ops/arith.rs`
294+
- `neg`: `libcore/ops/arith.rs`
295+
- `add_assign`: `libcore/ops/arith.rs`
296+
- `sub_assign`: `libcore/ops/arith.rs`
297+
- `mul_assign`: `libcore/ops/arith.rs`
298+
- `div_assign`: `libcore/ops/arith.rs`
299+
- `rem_assign`: `libcore/ops/arith.rs`
300+
- `eq`: `libcore/cmp.rs`
301+
- `ord`: `libcore/cmp.rs`
302+
- Functions
303+
- `fn`: `libcore/ops/function.rs`
304+
- `fn_mut`: `libcore/ops/function.rs`
305+
- `fn_once`: `libcore/ops/function.rs`
306+
- `generator_state`: `libcore/ops/generator.rs`
307+
- `generator`: `libcore/ops/generator.rs`
308+
- Other
309+
- `coerce_unsized`: `libcore/ops/unsize.rs`
310+
- `drop`: `libcore/ops/drop.rs`
311+
- `drop_in_place`: `libcore/ptr.rs`
312+
- `clone`: `libcore/clone.rs`
313+
- `copy`: `libcore/marker.rs`
314+
- `send`: `libcore/marker.rs`
315+
- `sized`: `libcore/marker.rs`
316+
- `unsize`: `libcore/marker.rs`
317+
- `sync`: `libcore/marker.rs`
318+
- `phantom_data`: `libcore/marker.rs`
319+
- `freeze`: `libcore/marker.rs`
320+
- `debug_trait`: `libcore/fmt/mod.rs`
321+
- `non_zero`: `libcore/nonzero.rs`

‎src/doc/unstable-book/src/library-features/alloc-jemalloc.md

+2-51
Original file line numberDiff line numberDiff line change
@@ -8,55 +8,6 @@ See also [`alloc_system`](library-features/alloc-system.html).
88

99
------------------------
1010

11-
The compiler currently ships two default allocators: `alloc_system` and
12-
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
13-
are normal Rust crates and contain an implementation of the routines to
14-
allocate and deallocate memory. The standard library is not compiled assuming
15-
either one, and the compiler will decide which allocator is in use at
16-
compile-time depending on the type of output artifact being produced.
17-
18-
Binaries generated by the compiler will use `alloc_jemalloc` by default (where
19-
available). In this situation the compiler "controls the world" in the sense of
20-
it has power over the final link. Primarily this means that the allocator
21-
decision can be left up the compiler.
22-
23-
Dynamic and static libraries, however, will use `alloc_system` by default. Here
24-
Rust is typically a 'guest' in another application or another world where it
25-
cannot authoritatively decide what allocator is in use. As a result it resorts
26-
back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
27-
memory.
28-
29-
# Switching Allocators
30-
31-
Although the compiler's default choices may work most of the time, it's often
32-
necessary to tweak certain aspects. Overriding the compiler's decision about
33-
which allocator is in use is done simply by linking to the desired allocator:
34-
35-
```rust,no_run
36-
#![feature(alloc_system)]
37-
38-
extern crate alloc_system;
39-
40-
fn main() {
41-
let a = Box::new(4); // Allocates from the system allocator.
42-
println!("{}", a);
43-
}
44-
```
45-
46-
In this example the binary generated will not link to jemalloc by default but
47-
instead use the system allocator. Conversely to generate a dynamic library which
48-
uses jemalloc by default one would write:
49-
50-
```rust,ignore
51-
#![feature(alloc_jemalloc)]
52-
#![crate_type = "dylib"]
53-
54-
extern crate alloc_jemalloc;
55-
56-
pub fn foo() {
57-
let a = Box::new(4); // Allocates from jemalloc.
58-
println!("{}", a);
59-
}
60-
# fn main() {}
61-
```
11+
This feature has been replaced by [the `jemallocator` crate on crates.io.][jemallocator].
6212

13+
[jemallocator]: https://crates.io/crates/jemallocator

‎src/doc/unstable-book/src/library-features/alloc-system.md

+23-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# `alloc_system`
22

3-
The tracking issue for this feature is: [#33082]
3+
The tracking issue for this feature is: [#32838]
44

5-
[#33082]: https://github.com/rust-lang/rust/issues/33082
5+
[#32838]: https://github.com/rust-lang/rust/issues/32838
66

7-
See also [`alloc_jemalloc`](library-features/alloc-jemalloc.html).
7+
See also [`global_allocator`](language-features/global-allocator.html).
88

99
------------------------
1010

@@ -30,13 +30,18 @@ memory.
3030

3131
Although the compiler's default choices may work most of the time, it's often
3232
necessary to tweak certain aspects. Overriding the compiler's decision about
33-
which allocator is in use is done simply by linking to the desired allocator:
33+
which allocator is in use is done through the `#[global_allocator]` attribute:
3434

3535
```rust,no_run
36-
#![feature(alloc_system)]
36+
#![feature(alloc_system, global_allocator, allocator_api)]
3737
3838
extern crate alloc_system;
3939
40+
use alloc_system::System;
41+
42+
#[global_allocator]
43+
static A: System = System;
44+
4045
fn main() {
4146
let a = Box::new(4); // Allocates from the system allocator.
4247
println!("{}", a);
@@ -47,16 +52,26 @@ In this example the binary generated will not link to jemalloc by default but
4752
instead use the system allocator. Conversely to generate a dynamic library which
4853
uses jemalloc by default one would write:
4954

55+
(The `alloc_jemalloc` crate cannot be used to control the global allocator,
56+
crate.io’s `jemallocator` crate provides equivalent functionality.)
57+
58+
```toml
59+
# Cargo.toml
60+
[dependencies]
61+
jemallocator = "0.1"
62+
```
5063
```rust,ignore
51-
#![feature(alloc_jemalloc)]
64+
#![feature(global_allocator)]
5265
#![crate_type = "dylib"]
5366
54-
extern crate alloc_jemalloc;
67+
extern crate jemallocator;
68+
69+
#[global_allocator]
70+
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
5571
5672
pub fn foo() {
5773
let a = Box::new(4); // Allocates from jemalloc.
5874
println!("{}", a);
5975
}
6076
# fn main() {}
6177
```
62-

‎src/liballoc_system/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#![unstable(feature = "alloc_system",
1515
reason = "this library is unlikely to be stabilized in its current \
1616
form or name",
17-
issue = "27783")]
17+
issue = "32838")]
1818
#![feature(global_allocator)]
1919
#![feature(allocator_api)]
2020
#![feature(alloc)]

‎src/librustc/ich/impls_ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
518518
FnPtrAddrCast
519519
});
520520

521-
impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { idx });
521+
impl_stable_hash_for!(tuple_struct ::middle::region::FirstStatementIndex { idx });
522522
impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
523523

524524
impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope {

‎src/librustc/middle/region.rs

+6-21
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,11 @@ pub struct BlockRemainder {
156156
pub first_statement_index: FirstStatementIndex,
157157
}
158158

159-
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
160-
RustcDecodable, Copy)]
161-
pub struct FirstStatementIndex { pub idx: u32 }
162-
163-
impl Idx for FirstStatementIndex {
164-
fn new(idx: usize) -> Self {
165-
assert!(idx <= SCOPE_DATA_REMAINDER_MAX as usize);
166-
FirstStatementIndex { idx: idx as u32 }
167-
}
168-
169-
fn index(self) -> usize {
170-
self.idx as usize
171-
}
172-
}
173-
174-
impl fmt::Debug for FirstStatementIndex {
175-
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
176-
fmt::Debug::fmt(&self.index(), formatter)
177-
}
178-
}
159+
newtype_index!(FirstStatementIndex
160+
{
161+
DEBUG_NAME = "",
162+
MAX = SCOPE_DATA_REMAINDER_MAX,
163+
});
179164

180165
impl From<ScopeData> for Scope {
181166
#[inline]
@@ -208,7 +193,7 @@ impl Scope {
208193
SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id),
209194
idx => ScopeData::Remainder(BlockRemainder {
210195
block: self.id,
211-
first_statement_index: FirstStatementIndex { idx }
196+
first_statement_index: FirstStatementIndex::new(idx as usize)
212197
})
213198
}
214199
}

‎src/librustc_data_structures/indexed_vec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ macro_rules! newtype_index {
6565
(@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]) => (
6666
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
6767
RustcEncodable, RustcDecodable)]
68-
pub struct $type(u32);
68+
pub struct $type(pub u32);
6969

7070
impl Idx for $type {
7171
fn new(value: usize) -> Self {
@@ -99,7 +99,7 @@ macro_rules! newtype_index {
9999
// Replace existing default for max
100100
(@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr]
101101
MAX = $max:expr, $($tokens:tt)*) => (
102-
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $(tokens)*);
102+
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
103103
);
104104

105105
// Replace existing default for debug_name

‎src/librustc_mir/diagnostics.rs

+57-9
Original file line numberDiff line numberDiff line change
@@ -320,20 +320,68 @@ Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
320320
of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
321321
of workarounds like `Rc`, a value cannot be owned by more than one variable.
322322
323-
If we own the type, the easiest way to address this problem is to implement
324-
`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
325-
information in `x`, while leaving the original version owned by `x`. Subsequent
326-
changes to `x` will not be reflected when accessing `y`.
323+
Sometimes we don't need to move the value. Using a reference, we can let another
324+
function borrow the value without changing its ownership. In the example below,
325+
we don't actually have to move our string to `calculate_length`, we can give it
326+
a reference to it with `&` instead.
327+
328+
```
329+
fn main() {
330+
let s1 = String::from("hello");
331+
332+
let len = calculate_length(&s1);
333+
334+
println!("The length of '{}' is {}.", s1, len);
335+
}
336+
337+
fn calculate_length(s: &String) -> usize {
338+
s.len()
339+
}
340+
```
341+
342+
A mutable reference can be created with `&mut`.
343+
344+
Sometimes we don't want a reference, but a duplicate. All types marked `Clone`
345+
can be duplicated by calling `.clone()`. Subsequent changes to a clone do not
346+
affect the original variable.
347+
348+
Most types in the standard library are marked `Clone`. The example below
349+
demonstrates using `clone()` on a string. `s1` is first set to "many", and then
350+
copied to `s2`. Then the first character of `s1` is removed, without affecting
351+
`s2`. "any many" is printed to the console.
352+
353+
```
354+
fn main() {
355+
let mut s1 = String::from("many");
356+
let s2 = s1.clone();
357+
s1.remove(0);
358+
println!("{} {}", s1, s2);
359+
}
360+
```
361+
362+
If we control the definition of a type, we can implement `Clone` on it ourselves
363+
with `#[derive(Clone)]`.
364+
365+
Some types have no ownership semantics at all and are trivial to duplicate. An
366+
example is `i32` and the other number types. We don't have to call `.clone()` to
367+
clone them, because they are marked `Copy` in addition to `Clone`. Implicit
368+
cloning is more convienient in this case. We can mark our own types `Copy` if
369+
all their members also are marked `Copy`.
370+
371+
In the example below, we implement a `Point` type. Because it only stores two
372+
integers, we opt-out of ownership semantics with `Copy`. Then we can
373+
`let p2 = p1` without `p1` being moved.
327374
328375
```
329376
#[derive(Copy, Clone)]
330-
struct MyStruct { s: u32 }
377+
struct Point { x: i32, y: i32 }
331378
332379
fn main() {
333-
let mut x = MyStruct{ s: 5u32 };
334-
let y = x;
335-
x.s = 6;
336-
println!("{}", x.s);
380+
let mut p1 = Point{ x: -1, y: 2 };
381+
let p2 = p1;
382+
p1.x = 1;
383+
println!("p1: {}, {}", p1.x, p1.y);
384+
println!("p2: {}, {}", p2.x, p2.y);
337385
}
338386
```
339387

‎src/librustdoc/clean/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ impl Clean<ExternalCrate> for CrateNum {
238238
if prim.is_some() {
239239
break;
240240
}
241+
// FIXME: should warn on unknown primitives?
241242
}
242243
}
243244
}
@@ -1627,6 +1628,7 @@ pub enum PrimitiveType {
16271628
Slice,
16281629
Array,
16291630
Tuple,
1631+
Unit,
16301632
RawPointer,
16311633
Reference,
16321634
Fn,
@@ -1662,7 +1664,11 @@ impl Type {
16621664
Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
16631665
Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
16641666
Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
1665-
Tuple(..) => Some(PrimitiveType::Tuple),
1667+
Tuple(ref tys) => if tys.is_empty() {
1668+
Some(PrimitiveType::Unit)
1669+
} else {
1670+
Some(PrimitiveType::Tuple)
1671+
},
16661672
RawPointer(..) => Some(PrimitiveType::RawPointer),
16671673
BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
16681674
BareFunction(..) => Some(PrimitiveType::Fn),
@@ -1708,7 +1714,11 @@ impl GetDefId for Type {
17081714
BorrowedRef { type_: box Generic(..), .. } =>
17091715
Primitive(PrimitiveType::Reference).def_id(),
17101716
BorrowedRef { ref type_, .. } => type_.def_id(),
1711-
Tuple(..) => Primitive(PrimitiveType::Tuple).def_id(),
1717+
Tuple(ref tys) => if tys.is_empty() {
1718+
Primitive(PrimitiveType::Unit).def_id()
1719+
} else {
1720+
Primitive(PrimitiveType::Tuple).def_id()
1721+
},
17121722
BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
17131723
Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
17141724
Array(..) => Primitive(PrimitiveType::Array).def_id(),
@@ -1742,6 +1752,7 @@ impl PrimitiveType {
17421752
"array" => Some(PrimitiveType::Array),
17431753
"slice" => Some(PrimitiveType::Slice),
17441754
"tuple" => Some(PrimitiveType::Tuple),
1755+
"unit" => Some(PrimitiveType::Unit),
17451756
"pointer" => Some(PrimitiveType::RawPointer),
17461757
"reference" => Some(PrimitiveType::Reference),
17471758
"fn" => Some(PrimitiveType::Fn),
@@ -1772,6 +1783,7 @@ impl PrimitiveType {
17721783
Array => "array",
17731784
Slice => "slice",
17741785
Tuple => "tuple",
1786+
Unit => "unit",
17751787
RawPointer => "pointer",
17761788
Reference => "reference",
17771789
Fn => "fn",
@@ -2693,6 +2705,7 @@ fn build_deref_target_impls(cx: &DocContext,
26932705
Slice => tcx.lang_items().slice_impl(),
26942706
Array => tcx.lang_items().slice_impl(),
26952707
Tuple => None,
2708+
Unit => None,
26962709
RawPointer => tcx.lang_items().const_ptr_impl(),
26972710
Reference => None,
26982711
Fn => None,

‎src/librustdoc/html/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
614614
}
615615
clean::Tuple(ref typs) => {
616616
match &typs[..] {
617-
&[] => primitive_link(f, PrimitiveType::Tuple, "()"),
617+
&[] => primitive_link(f, PrimitiveType::Unit, "()"),
618618
&[ref one] => {
619619
primitive_link(f, PrimitiveType::Tuple, "(")?;
620620
//carry f.alternate() into this display w/o branching manually

‎src/librustdoc/html/static/main.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939
"associatedconstant",
4040
"union"];
4141

42+
// On the search screen, so you remain on the last tab you opened.
43+
//
44+
// 0 for "Types/modules"
45+
// 1 for "As parameters"
46+
// 2 for "As return value"
47+
var currentTab = 0;
48+
4249
function hasClass(elem, className) {
4350
if (elem && className && elem.className) {
4451
var elemClass = elem.className;
@@ -758,7 +765,7 @@
758765

759766
var output = '';
760767
if (array.length > 0) {
761-
output = `<table class="search-results"${extraStyle}>`;
768+
output = '<table class="search-results"' + extraStyle + '>';
762769
var shown = [];
763770

764771
array.forEach(function(item) {
@@ -812,24 +819,32 @@
812819
});
813820
output += '</table>';
814821
} else {
815-
output = `<div class="search-failed"${extraStyle}>No results :(<br/>` +
822+
output = '<div class="search-failed"' + extraStyle + '>No results :(<br/>' +
816823
'Try on <a href="https://duckduckgo.com/?q=' +
817824
encodeURIComponent('rust ' + query.query) +
818825
'">DuckDuckGo</a>?</div>';
819826
}
820827
return output;
821828
}
822829

830+
function makeTabHeader(tabNb, text) {
831+
if (currentTab === tabNb) {
832+
return '<div class="selected">' + text + '</div>';
833+
}
834+
return '<div>' + text + '</div>';
835+
}
836+
823837
function showResults(results) {
824838
var output, query = getQuery();
825839

826840
currentResults = query.id;
827841
output = '<h1>Results for ' + escape(query.query) +
828842
(query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
829843
'<div id="titles">' +
830-
'<div class="selected">Types/modules</div>' +
831-
'<div>As parameters</div>' +
832-
'<div>As return value</div></div><div id="results">';
844+
makeTabHeader(0, "Types/modules") +
845+
makeTabHeader(1, "As parameters") +
846+
makeTabHeader(2, "As return value") +
847+
'</div><div id="results">';
833848

834849
output += addTab(results['others'], query);
835850
output += addTab(results['in_args'], query, false);
@@ -1405,6 +1420,9 @@
14051420

14061421
// In the search display, allows to switch between tabs.
14071422
function printTab(nb) {
1423+
if (nb === 0 || nb === 1 || nb === 2) {
1424+
currentTab = nb;
1425+
}
14081426
var nb_copy = nb;
14091427
onEach(document.getElementById('titles').childNodes, function(elem) {
14101428
if (nb_copy === 0) {

‎src/librustdoc/lib.rs

+41
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ pub fn opts() -> Vec<RustcOptGroup> {
170170
stable("no-default", |o| {
171171
o.optflag("", "no-defaults", "don't run the default passes")
172172
}),
173+
stable("document-private-items", |o| {
174+
o.optflag("", "document-private-items", "document private items")
175+
}),
173176
stable("test", |o| o.optflag("", "test", "run code examples as tests")),
174177
stable("test-args", |o| {
175178
o.optmulti("", "test-args", "arguments to pass to the test runner",
@@ -275,6 +278,9 @@ pub fn main_args(args: &[String]) -> isize {
275278
// Check for unstable options.
276279
nightly_options::check_nightly_options(&matches, &opts());
277280

281+
// check for deprecated options
282+
check_deprecated_options(&matches);
283+
278284
if matches.opt_present("h") || matches.opt_present("help") {
279285
usage("rustdoc");
280286
return 0;
@@ -458,6 +464,18 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
458464
let mut passes = matches.opt_strs("passes");
459465
let mut plugins = matches.opt_strs("plugins");
460466

467+
// We hardcode in the passes here, as this is a new flag and we
468+
// are generally deprecating passes.
469+
if matches.opt_present("document-private-items") {
470+
default_passes = false;
471+
472+
passes = vec![
473+
String::from("strip-hidden"),
474+
String::from("collapse-docs"),
475+
String::from("unindent-comments"),
476+
];
477+
}
478+
461479
// First, parse the crate and extract all relevant information.
462480
let mut paths = SearchPaths::new();
463481
for s in &matches.opt_strs("L") {
@@ -550,3 +568,26 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
550568
});
551569
rx.recv().unwrap()
552570
}
571+
572+
/// Prints deprecation warnings for deprecated options
573+
fn check_deprecated_options(matches: &getopts::Matches) {
574+
let deprecated_flags = [
575+
"input-format",
576+
"output-format",
577+
"plugin-path",
578+
"plugins",
579+
"no-defaults",
580+
"passes",
581+
];
582+
583+
for flag in deprecated_flags.into_iter() {
584+
if matches.opt_present(flag) {
585+
eprintln!("WARNING: the '{}' flag is considered deprecated", flag);
586+
eprintln!("WARNING: please see https://github.com/rust-lang/rust/issues/44136");
587+
}
588+
}
589+
590+
if matches.opt_present("no-defaults") {
591+
eprintln!("WARNING: (you may want to use --document-private-items)");
592+
}
593+
}

‎src/libstd/thread/local.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,10 @@ impl<T: 'static> LocalKey<T> {
325325
///
326326
/// Once the initialization expression succeeds, the key transitions to the
327327
/// `Valid` state which will guarantee that future calls to [`with`] will
328-
/// succeed within the thread.
328+
/// succeed within the thread. Some keys might skip the `Uninitialized`
329+
/// state altogether and start in the `Valid` state as an optimization
330+
/// (e.g. keys initialized with a constant expression), but no guarantees
331+
/// are made.
329332
///
330333
/// When a thread exits, each key will be destroyed in turn, and as keys are
331334
/// destroyed they will enter the `Destroyed` state just before the

‎src/test/codegen/abi-x86-interrupt.rs

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
// ignore-arm
1616
// ignore-aarch64
17-
// min-llvm-version 3.8
1817

1918
// compile-flags: -C no-prepopulate-passes
2019

‎src/test/codegen/mainsubprogram.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// The minimum LLVM version is set to 3.8, but really this test
12-
// depends on a patch that is was committed to upstream LLVM before
13-
// 4.0; and also backported to the Rust LLVM fork.
11+
// This test depends on a patch that was committed to upstream LLVM
12+
// before 4.0, formerly backported to the Rust LLVM fork.
1413

1514
// ignore-tidy-linelength
1615
// ignore-windows
1716
// ignore-macos
18-
// min-llvm-version 3.8
17+
// min-llvm-version 4.0
1918

2019
// compile-flags: -g -C no-prepopulate-passes
2120

‎src/test/codegen/mainsubprogramstart.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// The minimum LLVM version is set to 3.8, but really this test
12-
// depends on a patch that is was committed to upstream LLVM before
13-
// 4.0; and also backported to the Rust LLVM fork.
11+
// This test depends on a patch that was committed to upstream LLVM
12+
// before 4.0, formerly backported to the Rust LLVM fork.
1413

1514
// ignore-tidy-linelength
1615
// ignore-windows
1716
// ignore-macos
18-
// min-llvm-version 3.8
17+
// min-llvm-version 4.0
1918

2019
// compile-flags: -g -C no-prepopulate-passes
2120

‎src/test/run-pass/issue-36023.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// min-llvm-version 3.9
12-
1311
use std::ops::Deref;
1412

1513
fn main() {

‎src/test/rustdoc/empty-mod-private.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
// ignore-tidy-linelength
12-
// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
12+
// compile-flags: --document-private-items
1313

1414
// @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo'
1515
// @has 'empty_mod_private/sidebar-items.js' 'foo'

‎src/test/rustdoc/issue-15347.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags:--no-defaults --passes collapse-docs --passes unindent-comments
11+
// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments
1212

1313
// @has issue_15347/fn.foo.html
1414
#[doc(hidden)]

‎src/test/rustdoc/pub-method.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
// ignore-tidy-linelength
12-
// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
12+
// compile-flags: --document-private-items
1313

1414
#![crate_name = "foo"]
1515

0 commit comments

Comments
 (0)
Please sign in to comment.