Merge remote-tracking branch 'rust-lang/master' into hermit

This commit is contained in:
Stefan Lankes 2019-11-13 00:24:37 +01:00
commit 8871731914
1546 changed files with 11671 additions and 9924 deletions

View file

@ -105,7 +105,7 @@ contributions to the compiler and the standard library. It also lists some
really useful commands to the build system (`./x.py`), which could save you a
lot of time.
[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html
[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html
## Pull Requests
[pull-requests]: #pull-requests

View file

@ -68,7 +68,7 @@ name = "arena"
version = "0.0.0"
dependencies = [
"rustc_data_structures",
"smallvec",
"smallvec 1.0.0",
]
[[package]]
@ -208,6 +208,7 @@ name = "build-manifest"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"toml",
]
@ -486,7 +487,7 @@ dependencies = [
"regex-syntax",
"semver",
"serde",
"smallvec",
"smallvec 1.0.0",
"toml",
"unicode-normalization",
"url 2.1.0",
@ -654,7 +655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
dependencies = [
"crossbeam-utils 0.6.5",
"smallvec",
"smallvec 0.6.10",
]
[[package]]
@ -2251,9 +2252,9 @@ dependencies = [
[[package]]
name = "openssl"
version = "0.10.16"
version = "0.10.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9"
checksum = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449"
dependencies = [
"bitflags",
"cfg-if",
@ -2280,15 +2281,15 @@ dependencies = [
[[package]]
name = "openssl-sys"
version = "0.9.43"
version = "0.9.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d"
checksum = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc"
dependencies = [
"autocfg",
"cc",
"libc",
"openssl-src",
"pkg-config",
"rustc_version",
"vcpkg",
]
@ -2391,7 +2392,7 @@ dependencies = [
"libc",
"rand 0.6.1",
"rustc_version",
"smallvec",
"smallvec 0.6.10",
"winapi 0.3.6",
]
@ -2406,7 +2407,7 @@ dependencies = [
"libc",
"redox_syscall",
"rustc_version",
"smallvec",
"smallvec 0.6.10",
"winapi 0.3.6",
]
@ -3134,7 +3135,7 @@ dependencies = [
"rustc_target",
"scoped-tls",
"serialize",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
]
@ -3146,7 +3147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009"
dependencies = [
"rustc-ap-rustc_data_structures",
"smallvec",
"smallvec 0.6.10",
]
[[package]]
@ -3175,7 +3176,7 @@ dependencies = [
"rustc-hash",
"rustc-rayon 0.2.0",
"rustc-rayon-core 0.2.0",
"smallvec",
"smallvec 0.6.10",
"stable_deref_trait",
]
@ -3203,7 +3204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea"
dependencies = [
"rustc-ap-serialize",
"smallvec",
"smallvec 0.6.10",
]
[[package]]
@ -3249,7 +3250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20"
dependencies = [
"indexmap",
"smallvec",
"smallvec 0.6.10",
]
[[package]]
@ -3269,7 +3270,7 @@ dependencies = [
"rustc-ap-serialize",
"rustc-ap-syntax_pos",
"scoped-tls",
"smallvec",
"smallvec 0.6.10",
]
[[package]]
@ -3392,7 +3393,7 @@ dependencies = [
"crossbeam-utils 0.6.5",
"serde",
"serde_json",
"smallvec",
"smallvec 0.6.10",
"syn 0.15.35",
"url 2.1.0",
"winapi 0.3.6",
@ -3403,7 +3404,7 @@ name = "rustc_apfloat"
version = "0.0.0"
dependencies = [
"bitflags",
"smallvec",
"smallvec 1.0.0",
]
[[package]]
@ -3483,7 +3484,7 @@ dependencies = [
"rustc-rayon-core 0.3.0",
"rustc_index",
"serialize",
"smallvec",
"smallvec 1.0.0",
"stable_deref_trait",
]
@ -3503,8 +3504,10 @@ dependencies = [
"rustc_lint",
"rustc_metadata",
"rustc_mir",
"rustc_parse",
"rustc_plugin",
"rustc_plugin_impl",
"rustc_resolve",
"rustc_save_analysis",
"rustc_target",
"serialize",
@ -3551,7 +3554,7 @@ name = "rustc_index"
version = "0.0.0"
dependencies = [
"serialize",
"smallvec",
"smallvec 1.0.0",
]
[[package]]
@ -3570,6 +3573,7 @@ dependencies = [
"rustc_lint",
"rustc_metadata",
"rustc_mir",
"rustc_parse",
"rustc_passes",
"rustc_plugin_impl",
"rustc_privacy",
@ -3578,7 +3582,7 @@ dependencies = [
"rustc_traits",
"rustc_typeck",
"serialize",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_expand",
"syntax_ext",
@ -3647,9 +3651,10 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_parse",
"rustc_target",
"serialize",
"smallvec",
"smallvec 1.0.0",
"stable_deref_trait",
"syntax",
"syntax_expand",
@ -3674,7 +3679,7 @@ dependencies = [
"rustc_lexer",
"rustc_target",
"serialize",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
]
@ -3690,6 +3695,21 @@ dependencies = [
"core",
]
[[package]]
name = "rustc_parse"
version = "0.0.0"
dependencies = [
"bitflags",
"log",
"rustc_data_structures",
"rustc_errors",
"rustc_lexer",
"rustc_target",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
]
[[package]]
name = "rustc_passes"
version = "0.0.0"
@ -3699,6 +3719,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_parse",
"rustc_target",
"syntax",
"syntax_pos",
@ -3745,7 +3766,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_metadata",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_expand",
"syntax_pos",
@ -3761,7 +3782,7 @@ dependencies = [
"rustc",
"rustc_codegen_utils",
"rustc_data_structures",
"rustc_target",
"rustc_parse",
"serde_json",
"syntax",
"syntax_pos",
@ -3798,7 +3819,7 @@ dependencies = [
"rustc",
"rustc_data_structures",
"rustc_target",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
]
@ -3825,7 +3846,7 @@ dependencies = [
"rustc_errors",
"rustc_index",
"rustc_target",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
]
@ -4069,7 +4090,7 @@ name = "serialize"
version = "0.0.0"
dependencies = [
"indexmap",
"smallvec",
"smallvec 1.0.0",
]
[[package]]
@ -4133,6 +4154,12 @@ version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
[[package]]
name = "smallvec"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
[[package]]
name = "socket2"
version = "0.3.8"
@ -4355,10 +4382,9 @@ dependencies = [
"rustc_errors",
"rustc_index",
"rustc_lexer",
"rustc_target",
"scoped-tls",
"serialize",
"smallvec",
"smallvec 1.0.0",
"syntax_pos",
]
@ -4366,17 +4392,13 @@ dependencies = [
name = "syntax_expand"
version = "0.0.0"
dependencies = [
"bitflags",
"lazy_static 1.3.0",
"log",
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_lexer",
"rustc_target",
"scoped-tls",
"rustc_parse",
"serialize",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_pos",
]
@ -4389,8 +4411,9 @@ dependencies = [
"log",
"rustc_data_structures",
"rustc_errors",
"rustc_parse",
"rustc_target",
"smallvec",
"smallvec 1.0.0",
"syntax",
"syntax_expand",
"syntax_pos",

View file

@ -21,7 +21,7 @@ The Rust build system has a Python script called `x.py` to bootstrap building
the compiler. More information about it may be found by running `./x.py --help`
or reading the [rustc guide][rustcguidebuild].
[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html
[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html
### Building on *nix
1. Make sure you have installed the dependencies:

View file

@ -448,12 +448,12 @@ Arguments:
Flags {
verbose: matches.opt_count("verbose"),
stage: matches.opt_str("stage").map(|j| j.parse().unwrap()),
stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")),
dry_run: matches.opt_present("dry-run"),
on_fail: matches.opt_str("on-fail"),
rustc_error_format: matches.opt_str("error-format"),
keep_stage: matches.opt_strs("keep-stage")
.into_iter().map(|j| j.parse().unwrap())
.into_iter().map(|j| j.parse().expect("`keep-stage` should be a number"))
.collect(),
host: split(&matches.opt_strs("host"))
.into_iter()
@ -464,7 +464,7 @@ Arguments:
.map(|x| INTERNER.intern_string(x))
.collect::<Vec<_>>(),
config: cfg_file,
jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
cmd,
incremental: matches.opt_present("incremental"),
exclude: split(&matches.opt_strs("exclude"))

View file

@ -570,7 +570,12 @@ impl Step for Clippy {
let host_libs = builder
.stage_out(compiler, Mode::ToolRustc)
.join(builder.cargo_dir());
let target_libs = builder
.stage_out(compiler, Mode::ToolRustc)
.join(&self.host)
.join(builder.cargo_dir());
cargo.env("HOST_LIBS", host_libs);
cargo.env("TARGET_LIBS", target_libs);
// clippy tests need to find the driver
cargo.env("CLIPPY_DRIVER_PATH", clippy);

View file

@ -318,7 +318,7 @@ jobs:
# 32/64 bit MSVC and GNU deployment
dist-x86_64-msvc:
MSYS_BITS: 64
RUST_CONFIGURE_ARGS: >
RUST_CONFIGURE_ARGS: >-
--build=x86_64-pc-windows-msvc
--target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc
--enable-full-tools
@ -328,7 +328,7 @@ jobs:
DEPLOY: 1
dist-i686-msvc:
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: >
RUST_CONFIGURE_ARGS: >-
--build=i686-pc-windows-msvc
--target=i586-pc-windows-msvc
--enable-full-tools

View file

@ -69,7 +69,7 @@ RUN ./build-python.sh
# Now build LLVM+Clang 7, afterwards configuring further compilations to use the
# clang/clang++ compilers.
COPY dist-x86_64-linux/build-clang.sh /tmp/
COPY dist-x86_64-linux/build-clang.sh dist-x86_64-linux/llvm-project-centos.patch /tmp/
RUN ./build-clang.sh
ENV CC=clang CXX=clang++

View file

@ -4,17 +4,17 @@
set -ex
# Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz
curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
# Originally from https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz
curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/clang%2Bllvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
tar xJf -
export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
git clone https://github.com/CraneStation/wasi-sysroot
git clone https://github.com/CraneStation/wasi-libc
cd wasi-sysroot
git reset --hard e5f14be38362f1ab83302895a6e74b2ffd0e2302
cd wasi-libc
git reset --hard a94d2d04e7722b323573da2bd04e909a5763d35b
make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
cd ..
rm -rf reference-sysroot-wasi
rm -rf wasi-libc
rm -rf clang+llvm*

View file

@ -69,7 +69,7 @@ RUN ./build-python.sh
# Now build LLVM+Clang 7, afterwards configuring further compilations to use the
# clang/clang++ compilers.
COPY dist-x86_64-linux/build-clang.sh /tmp/
COPY dist-x86_64-linux/build-clang.sh dist-x86_64-linux/llvm-project-centos.patch /tmp/
RUN ./build-clang.sh
ENV CC=clang CXX=clang++

View file

@ -4,7 +4,7 @@ set -ex
source shared.sh
LLVM=llvmorg-8.0.0-rc2
LLVM=llvmorg-9.0.0
mkdir llvm-project
cd llvm-project
@ -12,6 +12,9 @@ cd llvm-project
curl -L https://github.com/llvm/llvm-project/archive/$LLVM.tar.gz | \
tar xzf - --strip-components=1
yum install -y patch
patch -Np1 < ../llvm-project-centos.patch
mkdir clang-build
cd clang-build

View file

@ -0,0 +1,18 @@
diff --git a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
index 176d6d6abf3..a6d63bf24b8 100644
--- a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
+++ b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
@@ -33,6 +33,13 @@ namespace {
using namespace llvm;
using namespace clang;
+#define EPOLL_CLOEXEC -1
+#define IN_CLOEXEC -1
+#define O_CLOEXEC -1
+static int epoll_create1(int flags) { return -1; }
+static int inotify_init1(int flags) { return -1; }
+static int pipe2(int *fds, int flags) { return -1; }
+
/// Pipe for inter-thread synchronization - for epoll-ing on multiple
/// conditions. It is meant for uni-directional 1:1 signalling - specifically:
/// no multiple consumers, no data passing. Thread waiting for signal should

View file

@ -9,10 +9,10 @@ IFS=$'\n\t'
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
if isMacOS; then
curl -f "${MIRRORS_BASE}/clang%2Bllvm-7.0.0-x86_64-apple-darwin.tar.xz" | tar xJf -
curl -f "${MIRRORS_BASE}/clang%2Bllvm-9.0.0-x86_64-darwin-apple.tar.xz" | tar xJf -
ciCommandSetEnv CC "$(pwd)/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang"
ciCommandSetEnv CXX "$(pwd)/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++"
ciCommandSetEnv CC "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang"
ciCommandSetEnv CXX "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang++"
# Configure `AR` specifically so rustbuild doesn't try to infer it as
# `clang-ar` by accident.
@ -27,17 +27,18 @@ elif isWindows && [[ -z ${MINGW_URL+x} ]]; then
# Note that the LLVM installer is an NSIS installer
#
# Original downloaded here came from
# http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe
# That installer was run through `wine` on Linux and then the resulting
# installation directory (found in `$HOME/.wine/drive_c/Program Files/LLVM`) was
# packaged up into a tarball. We've had issues otherwise that the installer will
# randomly hang, provide not a lot of useful information, pollute global state,
# etc. In general the tarball is just more confined and easier to deal with when
# working with various CI environments.
# http://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe
# That installer was run through `wine ./installer.exe /S /NCRC` on Linux
# and then the resulting installation directory (found in
# `$HOME/.wine/drive_c/Program Files/LLVM`) was packaged up into a tarball.
# We've had issues otherwise that the installer will randomly hang, provide
# not a lot of useful information, pollute global state, etc. In general the
# tarball is just more confined and easier to deal with when working with
# various CI environments.
mkdir -p citools
cd citools
curl -f "${MIRRORS_BASE}/LLVM-7.0.0-win64.tar.gz" | tar xzf -
curl -f "${MIRRORS_BASE}/LLVM-9.0.0-win64.tar.gz" | tar xzf -
ciCommandSetEnv RUST_CONFIGURE_ARGS \
"${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe"
fi

@ -1 +1 @@
Subproject commit 941968db2fd9c85788a4f971c8e425d46b4cb734
Subproject commit 75a5f9236c689a547fe207a10854f0775bce7937

View file

@ -197,7 +197,11 @@ in software.
## prefer-dynamic
By default, `rustc` prefers to statically link dependencies. This option will
make it use dynamic linking instead.
indicate that dynamic linking should be used if possible if both a static and
dynamic versions of a library are available. There is an internal algorithm
for determining whether or not it is possible to statically or dynamically
link with a dependency. For example, `cdylib` crate types may only use static
linkage.
## no-integrated-as

View file

@ -21,8 +21,7 @@ to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
<a id="option-l-search-path"></a>
## `-L`: add a directory to the library search path
When looking for external crates or libraries, a directory passed to this flag
will be searched.
The `-L` flag adds a path to search for external crates and libraries.
The kind of search path can optionally be specified with the form `-L
KIND=PATH` where `KIND` may be one of:
@ -262,9 +261,30 @@ This flag, when combined with other flags, makes them produce extra output.
<a id="option-extern"></a>
## `--extern`: specify where an external library is located
This flag allows you to pass the name and location of an external crate that
will be linked into the crate you are building. This flag may be specified
multiple times. The format of the value should be `CRATENAME=PATH`.
This flag allows you to pass the name and location for an external crate of a
direct dependency. Indirect dependencies (dependencies of dependencies) are
located using the [`-L` flag](#option-l-search-path). The given crate name is
added to the [extern prelude], which is the same as specifying `extern crate`
within the root module. The given crate name does not need to match the name
the library was built with.
This flag may be specified multiple times. This flag takes an argument with
either of the following formats:
* `CRATENAME=PATH` Indicates the given crate is found at the given path.
* `CRATENAME` Indicates the given crate may be found in the search path,
such as within the sysroot or via the `-L` flag.
The same crate name may be specified multiple times for different crate types.
If both an `rlib` and `dylib` are found, an internal algorithm is used to
decide which to use for linking. The [`-C prefer-dynamic`
flag][prefer-dynamic] may be used to influence which is used.
If the same crate name is specified with and without a path, the one with the
path is used and the pathless flag has no effect.
[extern prelude]: ../reference/items/extern-crates.html#extern-prelude
[prefer-dynamic]: codegen-options/index.md#prefer-dynamic
<a id="option-sysroot"></a>
## `--sysroot`: Override the system root

View file

@ -45,53 +45,6 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
```
## legacy-constructor-visibility
[RFC 1506](https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md) modified some
visibility rules, and changed the visibility of struct constructors. Some
example code that triggers this lint:
```rust,ignore
mod m {
pub struct S(u8);
fn f() {
// this is trying to use S from the 'use' line, but because the `u8` is
// not pub, it is private
::S;
}
}
use m::S;
```
This will produce:
```text
error: private struct constructors are not usable through re-exports in outer modules
--> src/main.rs:5:9
|
5 | ::S;
| ^^^
|
= note: `#[deny(legacy_constructor_visibility)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #39207 <https://github.com/rust-lang/rust/issues/39207>
```
## legacy-directory-ownership
The legacy_directory_ownership warning is issued when
* There is a non-inline module with a `#[path]` attribute (e.g. `#[path = "foo.rs"] mod bar;`),
* The module's file ("foo.rs" in the above example) is not named "mod.rs", and
* The module's file contains a non-inline child module without a `#[path]` attribute.
The warning can be fixed by renaming the parent module to "mod.rs" and moving
it into its own directory if appropriate.
## missing-fragment-specifier
The missing_fragment_specifier warning is issued when an unused pattern in a
@ -169,40 +122,50 @@ error: literal out of range for u8
|
```
## parenthesized-params-in-types-and-modules
## patterns-in-fns-without-body
This lint detects incorrect parentheses. Some example code that triggers this
lint:
This lint detects patterns in functions without body were that were
previously erroneously allowed. Some example code that triggers this lint:
```rust,ignore
let x = 5 as usize();
```rust,compile_fail
trait Trait {
fn foo(mut arg: u8);
}
```
This will produce:
```text
error: parenthesized parameters may only be used with a trait
--> src/main.rs:2:21
warning: patterns aren't allowed in methods without bodies
--> src/main.rs:2:12
|
2 | let x = 5 as usize();
| ^^
2 | fn foo(mut arg: u8);
| ^^^^^^^
|
= note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default
= note: `#[warn(patterns_in_fns_without_body)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
= note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
```
To fix it, remove the `()`s.
To fix this, remove the pattern; it can be used in the implementation without
being used in the definition. That is:
```rust
trait Trait {
fn foo(arg: u8);
}
impl Trait for i32 {
fn foo(mut arg: u8) {
}
}
```
## pub-use-of-private-extern-crate
This lint detects a specific situation of re-exporting a private `extern crate`;
## safe-extern-statics
In older versions of Rust, there was a soundness issue where `extern static`s were allowed
to be accessed in safe code. This lint now catches and denies this kind of code.
## unknown-crate-types
This lint detects an unknown crate type found in a `#[crate_type]` directive. Some

View file

@ -307,46 +307,6 @@ warning: path statement with no effect
|
```
## patterns-in-fns-without-body
This lint detects patterns in functions without body were that were
previously erroneously allowed. Some example code that triggers this lint:
```rust
trait Trait {
fn foo(mut arg: u8);
}
```
This will produce:
```text
warning: patterns aren't allowed in methods without bodies
--> src/main.rs:2:12
|
2 | fn foo(mut arg: u8);
| ^^^^^^^
|
= note: `#[warn(patterns_in_fns_without_body)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
```
To fix this, remove the pattern; it can be used in the implementation without
being used in the definition. That is:
```rust
trait Trait {
fn foo(arg: u8);
}
impl Trait for i32 {
fn foo(mut arg: u8) {
}
}
```
## plugin-as-library
This lint detects when compiler plugins are used as ordinary library in

View file

@ -1,8 +1,10 @@
# The Rustdoc Book
- [What is rustdoc?](what-is-rustdoc.md)
- [How to write documentation](how-to-write-documentation.md)
- [Command-line arguments](command-line-arguments.md)
- [The `#[doc]` attribute](the-doc-attribute.md)
- [Documentation tests](documentation-tests.md)
- [Lints](lints.md)
- [Passes](passes.md)
- [Unstable features](unstable-features.md)

View file

@ -0,0 +1,82 @@
# How to write documentation
This chapter covers not only how to write documentation but specifically
how to write **good** documentation. Something to keep in mind when
writing documentation is that your audience is not just yourself but others
who simply don't have the context you do. It is important to be as clear
as you can, and as complete as possible. As a rule of thumb: the more
documentation you write for your crate the better. If an item is public
then it should be documented.
## Basic structure
It is recommended that each item's documentation follows this basic structure:
```text
[short sentence explaining what it is]
[more detailed explanation]
[at least one code example that users can copy/paste to try it]
[even more advanced explanations if necessary]
```
This basic structure should be straightforward to follow when writing your
documentation and, while you might think that a code example is trivial,
the examples are really important because they can help your users to
understand what an item is, how it is used, and for what purpose it exists.
Let's see an example coming from the [standard library] by taking a look at the
[`std::env::args()`][env::args] function:
``````text
Returns the arguments which this program was started with (normally passed
via the command line).
The first element is traditionally the path of the executable, but it can be
set to arbitrary text, and may not even exist. This means this property should
not be relied upon for security purposes.
On Unix systems shell usually expands unquoted arguments with glob patterns
(such as `*` and `?`). On Windows this is not done, and such arguments are
passed as-is.
# Panics
The returned iterator will panic during iteration if any argument to the
process is not valid unicode. If this is not desired,
use the [`args_os`] function instead.
# Examples
```
use std::env;
// Prints each argument on a separate line
for argument in env::args() {
println!("{}", argument);
}
```
[`args_os`]: ./fn.args_os.html
``````
As you can see, it follows the structure detailed above: it starts with a short
sentence explaining what the functions does, then it provides more information
and finally provides a code example.
## Markdown
`rustdoc` is using the [commonmark markdown specification]. You might be
interested into taking a look at their website to see what's possible to do.
## Lints
To be sure that you didn't miss any item without documentation or code examples,
you can take a look at the rustdoc lints [here][rustdoc-lints].
[standard library]: https://doc.rust-lang.org/stable/std/index.html
[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
[commonmark markdown specification]: https://commonmark.org/
[rustdoc-lints]: lints.md

View file

@ -0,0 +1,119 @@
# Lints
`rustdoc` provides lints to help you writing and testing your documentation. You
can use them like any other lints by doing this:
```rust,ignore
#![allow(missing_docs)] // allowing the lint, no message
#![warn(missing_docs)] // warn if there is missing docs
#![deny(missing_docs)] // rustdoc will fail if there is missing docs
```
Here is the list of the lints provided by `rustdoc`:
## intra_doc_link_resolution_failure
This lint **warns by default** and is **nightly-only**. This lint detects when
an intra-doc link fails to get resolved. For example:
```rust
/// I want to link to [`Inexistent`] but it doesn't exist!
pub fn foo() {}
```
You'll get a warning saying:
```text
error: `[`Inexistent`]` cannot be resolved, ignoring it...
```
## missing_docs
This lint is **allowed by default**. It detects items missing documentation.
For example:
```rust
#![warn(missing_docs)]
pub fn undocumented() {}
# fn main() {}
```
The `undocumented` function will then have the following warning:
```text
warning: missing documentation for a function
--> your-crate/lib.rs:3:1
|
3 | pub fn undocumented() {}
| ^^^^^^^^^^^^^^^^^^^^^
```
## missing_doc_code_examples
This lint is **allowed by default**. It detects when a documentation block
is missing a code example. For example:
```rust
#![warn(missing_doc_code_examples)]
/// There is no code example!
pub fn no_code_example() {}
# fn main() {}
```
The `no_code_example` function will then have the following warning:
```text
warning: Missing code example in this documentation
--> your-crate/lib.rs:3:1
|
LL | /// There is no code example!
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
To fix the lint, you need to add a code example into the documentation block:
```rust
/// There is no code example!
///
/// ```
/// println!("calling no_code_example...");
/// no_code_example();
/// println!("we called no_code_example!");
/// ```
pub fn no_code_example() {}
```
## private_doc_tests
This lint is **allowed by default**. It detects documentation tests when they
are on a private item. For example:
```rust
#![warn(private_doc_tests)]
mod foo {
/// private doc test
///
/// ```
/// assert!(false);
/// ```
fn bar() {}
}
# fn main() {}
```
Which will give:
```text
warning: Documentation test in private item
--> your-crate/lib.rs:4:1
|
4 | / /// private doc test
5 | | ///
6 | | /// ```
7 | | /// assert!(false);
8 | | /// ```
| |___________^
```

View file

@ -1,154 +0,0 @@
# `on_unimplemented`
The tracking issue for this feature is: [#29628]
[#29628]: https://github.com/rust-lang/rust/issues/29628
------------------------
The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
attribute, which allows trait definitions to add specialized notes to error
messages when an implementation was expected but not found. You can refer
to the trait's generic arguments by name and to the resolved type using
`Self`.
For example:
```rust,compile_fail
#![feature(on_unimplemented)]
#[rustc_on_unimplemented="an iterator over elements of type `{A}` \
cannot be built from a collection of type `{Self}`"]
trait MyIterator<A> {
fn next(&mut self) -> A;
}
fn iterate_chars<I: MyIterator<char>>(i: I) {
// ...
}
fn main() {
iterate_chars(&[1, 2, 3][..]);
}
```
When the user compiles this, they will see the following;
```txt
error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
--> <anon>:14:5
|
14 | iterate_chars(&[1, 2, 3][..]);
| ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
|
= help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
= note: required by `iterate_chars`
```
`on_unimplemented` also supports advanced filtering for better targeting
of messages, as well as modifying specific parts of the error message. You
target the text of:
- the main error message (`message`)
- the label (`label`)
- an extra note (`note`)
For example, the following attribute
```rust,compile_fail
#[rustc_on_unimplemented(
message="message",
label="label",
note="note"
)]
trait MyIterator<A> {
fn next(&mut self) -> A;
}
```
Would generate the following output:
```text
error[E0277]: message
--> <anon>:14:5
|
14 | iterate_chars(&[1, 2, 3][..]);
| ^^^^^^^^^^^^^ label
|
= note: note
= help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
= note: required by `iterate_chars`
```
To allow more targeted error messages, it is possible to filter the
application of these fields based on a variety of attributes when using
`on`:
- `crate_local`: whether the code causing the trait bound to not be
fulfilled is part of the user's crate. This is used to avoid suggesting
code changes that would require modifying a dependency.
- Any of the generic arguments that can be substituted in the text can be
referred by name as well for filtering, like `Rhs="i32"`, except for
`Self`.
- `_Self`: to filter only on a particular calculated trait resolution, like
`Self="std::iter::Iterator<char>"`. This is needed because `Self` is a
keyword which cannot appear in attributes.
- `direct`: user-specified rather than derived obligation.
- `from_method`: usable both as boolean (whether the flag is present, like
`crate_local`) or matching against a particular method. Currently used
for `try`.
- `from_desugaring`: usable both as boolean (whether the flag is present)
or matching against a particular desugaring. The desugaring is identified
with its variant name in the `DesugaringKind` enum.
For example, the `Iterator` trait can be annotated in the following way:
```rust,compile_fail
#[rustc_on_unimplemented(
on(
_Self="&str",
note="call `.chars()` or `.as_bytes()` on `{Self}"
),
message="`{Self}` is not an iterator",
label="`{Self}` is not an iterator",
note="maybe try calling `.iter()` or a similar method"
)]
pub trait Iterator {}
```
Which would produce the following outputs:
```text
error[E0277]: `Foo` is not an iterator
--> src/main.rs:4:16
|
4 | for foo in Foo {}
| ^^^ `Foo` is not an iterator
|
= note: maybe try calling `.iter()` or a similar method
= help: the trait `std::iter::Iterator` is not implemented for `Foo`
= note: required by `std::iter::IntoIterator::into_iter`
error[E0277]: `&str` is not an iterator
--> src/main.rs:5:16
|
5 | for foo in "" {}
| ^^ `&str` is not an iterator
|
= note: call `.chars()` or `.bytes() on `&str`
= help: the trait `std::iter::Iterator` is not implemented for `&str`
= note: required by `std::iter::IntoIterator::into_iter`
```
If you need to filter on multiple attributes, you can use `all`, `any` or
`not` in the following way:
```rust,compile_fail
#[rustc_on_unimplemented(
on(
all(_Self="&str", T="std::string::String"),
note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
)
)]
pub trait From<T>: Sized { /* ... */ }
```

View file

@ -1,23 +0,0 @@
# `re_rebalance_coherence`
The tracking issue for this feature is: [#55437]
[#55437]: https://github.com/rust-lang/rust/issues/55437
------------------------
The `re_rebalance_coherence` feature tweaks the rules regarding which trait
impls are allowed in crates.
The following rule is used:
Given `impl<P1..=Pn> Trait<T1..=Tn> for T0`, an impl is valid only if at
least one of the following is true:
- `Trait` is a local trait
- All of
- At least one of the types `T0..=Tn` must be a local type. Let `Ti` be the
first such type.
- No uncovered type parameters `P1..=Pn` may appear in `T0..Ti` (excluding
`Ti`)
See the [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2451-re-rebalancing-coherence.md) for details.

View file

@ -14,8 +14,7 @@ TEST_DIR = os.path.abspath(
os.path.join(os.path.dirname(__file__), '../test/ui/derives/'))
TEMPLATE = """\
// ignore-x86
// ^ due to stderr output differences
// ignore-x86 FIXME: missing sysroot spans (#53081)
// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
{error_deriving}

View file

@ -90,7 +90,7 @@ impl<T> Clone for Iter<'_, T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
// We do *not* exclusively own the entire list here, references to node's `element`
// have been handed out by the iterator! So be careful when using this; the methods
// have been handed out by the iterator! So be careful when using this; the methods
// called must be aware that there can be aliasing pointers to `element`.
list: &'a mut LinkedList<T>,
head: Option<NonNull<Node<T>>>,

View file

@ -835,7 +835,8 @@ impl<T> VecDeque<T> {
}
}
/// Shortens the `VecDeque`, dropping excess elements from the back.
/// Shortens the `VecDeque`, keeping the first `len` elements and dropping
/// the rest.
///
/// If `len` is greater than the `VecDeque`'s current length, this has no
/// effect.
@ -855,8 +856,31 @@ impl<T> VecDeque<T> {
/// ```
#[stable(feature = "deque_extras", since = "1.16.0")]
pub fn truncate(&mut self, len: usize) {
for _ in len..self.len() {
self.pop_back();
// Safe because:
//
// * Any slice passed to `drop_in_place` is valid; the second case has
// `len <= front.len()` and returning on `len > self.len()` ensures
// `begin <= back.len()` in the first case
// * The head of the VecDeque is moved before calling `drop_in_place`,
// so no value is dropped twice if `drop_in_place` panics
unsafe {
if len > self.len() {
return;
}
let num_dropped = self.len() - len;
let (front, back) = self.as_mut_slices();
if len > front.len() {
let begin = len - front.len();
let drop_back = back.get_unchecked_mut(begin..) as *mut _;
self.head = self.wrap_sub(self.head, num_dropped);
ptr::drop_in_place(drop_back);
} else {
let drop_back = back as *mut _;
let drop_front = front.get_unchecked_mut(len..) as *mut _;
self.head = self.wrap_sub(self.head, num_dropped);
ptr::drop_in_place(drop_front);
ptr::drop_in_place(drop_back);
}
}
}
@ -1117,7 +1141,7 @@ impl<T> VecDeque<T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn clear(&mut self) {
self.drain(..);
self.truncate(0);
}
/// Returns `true` if the `VecDeque` contains an element equal to the

View file

@ -384,6 +384,41 @@ fn test_clone_from() {
}
}
#[test]
fn test_vec_deque_truncate_drop() {
static mut DROPS: u32 = 0;
#[derive(Clone)]
struct Elem(i32);
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
for push_front in 0..=v.len() {
let v = v.clone();
let mut tester = VecDeque::with_capacity(5);
for (index, elem) in v.into_iter().enumerate() {
if index < push_front {
tester.push_front(elem);
} else {
tester.push_back(elem);
}
}
assert_eq!(unsafe { DROPS }, 0);
tester.truncate(3);
assert_eq!(unsafe { DROPS }, 2);
tester.truncate(0);
assert_eq!(unsafe { DROPS }, 5);
unsafe {
DROPS = 0;
}
}
}
#[test]
fn issue_53529() {
use crate::boxed::Box;

View file

@ -116,7 +116,7 @@
#![feature(unsize)]
#![feature(unsized_locals)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![cfg_attr(bootstrap, feature(on_unimplemented))]
#![feature(rustc_const_unstable)]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit_extra, maybe_uninit_slice)]

View file

@ -280,7 +280,7 @@ struct RcBox<T: ?Sized> {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
ptr: NonNull<RcBox<T>>,
phantom: PhantomData<T>,
phantom: PhantomData<RcBox<T>>,
}
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -687,7 +687,7 @@ impl String {
/// checked:
///
/// * The memory at `ptr` needs to have been previously allocated by the
/// same allocator the standard library uses.
/// same allocator the standard library uses, with a required alignment of exactly 1.
/// * `length` needs to be less than or equal to `capacity`.
/// * `capacity` needs to be the correct value.
///

View file

@ -195,7 +195,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,
phantom: PhantomData<T>,
phantom: PhantomData<ArcInner<T>>,
}
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -10,4 +10,4 @@ path = "lib.rs"
[dependencies]
rustc_data_structures = { path = "../librustc_data_structures" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }

View file

@ -1,5 +1,7 @@
//! Memory allocation APIs
// ignore-tidy-undocumented-unsafe
#![stable(feature = "alloc_module", since = "1.28.0")]
use crate::cmp;

View file

@ -182,6 +182,7 @@ impl dyn Any {
#[inline]
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
if self.is::<T>() {
// SAFETY: just checked whether we are pointing to the correct type
unsafe {
Some(&*(self as *const dyn Any as *const T))
}
@ -217,6 +218,7 @@ impl dyn Any {
#[inline]
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
// SAFETY: just checked whether we are pointing to the correct type
unsafe {
Some(&mut *(self as *mut dyn Any as *mut T))
}
@ -424,7 +426,11 @@ impl TypeId {
#[rustc_const_unstable(feature="const_type_id")]
pub const fn of<T: ?Sized + 'static>() -> TypeId {
TypeId {
#[cfg(bootstrap)]
// SAFETY: going away soon
t: unsafe { intrinsics::type_id::<T>() },
#[cfg(not(bootstrap))]
t: intrinsics::type_id::<T>(),
}
}
}

View file

@ -51,7 +51,7 @@ where
/// iterator (either via `IntoIterator` for arrays or via another way).
#[unstable(feature = "array_value_iter", issue = "65798")]
pub fn new(array: [T; N]) -> Self {
// The transmute here is actually safe. The docs of `MaybeUninit`
// SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
// promise:
//
// > `MaybeUninit<T>` is guaranteed to have the same size and alignment
@ -84,10 +84,10 @@ where
/// Returns an immutable slice of all elements that have not been yielded
/// yet.
fn as_slice(&self) -> &[T] {
// This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
let slice = &self.data[self.alive.clone()];
// SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
// the size and alignment of `T`. Furthermore, we know that all
// elements within `alive` are properly initialized.
let slice = &self.data[self.alive.clone()];
unsafe {
mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
}
@ -117,7 +117,8 @@ where
let idx = self.alive.start;
self.alive.start += 1;
// Read the element from the array. This is safe: `idx` is an index
// Read the element from the array.
// SAFETY: This is safe: `idx` is an index
// into the "alive" region of the array. Reading this element means
// that `data[idx]` is regarded as dead now (i.e. do not touch). As
// `idx` was the start of the alive-zone, the alive zone is now
@ -163,7 +164,8 @@ where
// + 1]`.
self.alive.end -= 1;
// Read the element from the array. This is safe: `alive.end` is an
// Read the element from the array.
// SAFETY: This is safe: `alive.end` is an
// index into the "alive" region of the array. Compare the previous
// comment that states that the alive region is
// `data[alive.start..alive.end + 1]`. Reading this element means that
@ -226,6 +228,7 @@ where
[T; N]: LengthAtMost32,
{
fn clone(&self) -> Self {
// SAFETY: each point of unsafety is documented inside the unsafe block
unsafe {
// This creates a new uninitialized array. Note that the `assume_init`
// refers to the array, not the individual elements. And it is Ok if

View file

@ -156,6 +156,7 @@ where
fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
if slice.len() == N {
let ptr = slice.as_ptr() as *const [T; N];
// SAFETY: ok because we just checked that the length fits
unsafe { Ok(&*ptr) }
} else {
Err(TryFromSliceError(()))
@ -173,6 +174,7 @@ where
fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
if slice.len() == N {
let ptr = slice.as_mut_ptr() as *mut [T; N];
// SAFETY: ok because we just checked that the length fits
unsafe { Ok(&mut *ptr) }
} else {
Err(TryFromSliceError(()))

View file

@ -135,6 +135,7 @@ impl FusedIterator for EscapeDefault {}
#[stable(feature = "ascii_escape_display", since = "1.39.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: ok because `escape_default` created only valid utf-8 data
f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
}
}

View file

@ -118,6 +118,7 @@ benches! {
}
fn case07_fake_simd_u32(bytes: &mut [u8]) {
// SAFETY: transmuting a sequence of `u8` to `u32` is always fine
let (before, aligned, after) = unsafe {
bytes.align_to_mut::<u32>()
};
@ -142,6 +143,7 @@ benches! {
}
fn case08_fake_simd_u64(bytes: &mut [u8]) {
// SAFETY: transmuting a sequence of `u8` to `u64` is always fine
let (before, aligned, after) = unsafe {
bytes.align_to_mut::<u64>()
};

View file

@ -137,9 +137,11 @@
//! use std::cell::Cell;
//! use std::ptr::NonNull;
//! use std::intrinsics::abort;
//! use std::marker::PhantomData;
//!
//! struct Rc<T: ?Sized> {
//! ptr: NonNull<RcBox<T>>
//! ptr: NonNull<RcBox<T>>,
//! phantom: PhantomData<RcBox<T>>,
//! }
//!
//! struct RcBox<T: ?Sized> {
@ -151,7 +153,10 @@
//! impl<T: ?Sized> Clone for Rc<T> {
//! fn clone(&self) -> Rc<T> {
//! self.inc_strong();
//! Rc { ptr: self.ptr }
//! Rc {
//! ptr: self.ptr,
//! phantom: PhantomData,
//! }
//! }
//! }
//!
@ -182,6 +187,8 @@
//! ```
//!
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::cmp::Ordering;

View file

@ -224,6 +224,7 @@ impl TryFrom<u32> for char {
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
Err(CharTryFromError(()))
} else {
// SAFETY: checked that it's a legal unicode value
Ok(unsafe { from_u32_unchecked(i) })
}
}

View file

@ -87,7 +87,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
};
if u < 0xD800 || 0xDFFF < u {
// not a surrogate
// SAFETY: not a surrogate
Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
} else if u >= 0xDC00 {
// a trailing surrogate
@ -107,6 +107,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
// all ok, so lets decode it.
let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
// SAFETY: we checked that it's a legal unicode value
Some(Ok(unsafe { from_u32_unchecked(c) }))
}
}

View file

@ -438,6 +438,7 @@ impl char {
#[inline]
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
let code = self as u32;
// SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops
unsafe {
let len = if code < MAX_ONE_B && !dst.is_empty() {
*dst.get_unchecked_mut(0) = code as u8;
@ -507,6 +508,7 @@ impl char {
#[inline]
pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
let mut code = self as u32;
// SAFETY: each arm checks whether there are enough bits to write into
unsafe {
if (code & 0xFFFF) == code && !dst.is_empty() {
// The BMP falls through (assuming non-surrogate, as it should)

View file

@ -205,11 +205,12 @@ pub trait AsMut<T: ?Sized> {
/// A value-to-value conversion that consumes the input value. The
/// opposite of [`From`].
///
/// One should only implement [`Into`] if a conversion to a type outside the current crate is
/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because
/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to
/// the blanket implementation in the standard library. [`From`] cannot do these type of
/// conversions because of Rust's orphaning rules.
/// One should avoid implementing [`Into`] and implement [`From`] instead.
/// Implementing [`From`] automatically provides one with an implementation of [`Into`]
/// thanks to the blanket implementation in the standard library.
///
/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function
/// to ensure that types that only implement [`Into`] can be used as well.
///
/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`].
///
@ -218,13 +219,13 @@ pub trait AsMut<T: ?Sized> {
/// - [`From`]`<T> for U` implies `Into<U> for T`
/// - [`Into`] is reflexive, which means that `Into<T> for T` is implemented
///
/// # Implementing [`Into`] for conversions to external types
/// # Implementing [`Into`] for conversions to external types in old versions of Rust
///
/// If the destination type is not part of the current crate
/// then you can't implement [`From`] directly.
/// Prior to Rust 1.40, if the destination type was not part of the current crate
/// then you couldn't implement [`From`] directly.
/// For example, take this code:
///
/// ```compile_fail
/// ```
/// struct Wrapper<T>(Vec<T>);
/// impl<T> From<Wrapper<T>> for Vec<T> {
/// fn from(w: Wrapper<T>) -> Vec<T> {
@ -232,9 +233,8 @@ pub trait AsMut<T: ?Sized> {
/// }
/// }
/// ```
/// This will fail to compile because we cannot implement a trait for a type
/// if both the trait and the type are not defined by the current crate.
/// This is due to Rust's orphaning rules. To bypass this, you can implement [`Into`] directly:
/// This will fail to compile in older versions of the language because Rust's orphaning rules
/// used to be a little bit more strict. To bypass this, you could implement [`Into`] directly:
///
/// ```
/// struct Wrapper<T>(Vec<T>);
@ -249,9 +249,6 @@ pub trait AsMut<T: ?Sized> {
/// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`]
/// and then fall back to [`Into`] if [`From`] can't be implemented.
///
/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function
/// to ensure that types that only implement [`Into`] can be used as well.
///
/// # Examples
///
/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:

View file

@ -315,6 +315,7 @@ impl<'f> Clone for VaListImpl<'f> {
#[inline]
fn clone(&self) -> Self {
let mut dest = crate::mem::MaybeUninit::uninit();
// SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal
unsafe {
va_copy(dest.as_mut_ptr(), self);
dest.assume_init()

View file

@ -2,6 +2,8 @@ use crate::fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug};
use crate::mem::MaybeUninit;
use crate::num::flt2dec;
// ignore-tidy-undocumented-unsafe
// Don't inline this so callers don't use the stack space this function
// requires unless they have to.
#[inline(never)]

View file

@ -1,5 +1,7 @@
//! Utilities for formatting and printing strings.
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::cell::{UnsafeCell, Cell, RefCell, Ref, RefMut};

View file

@ -1,5 +1,7 @@
//! Integer and floating-point number formatting
// ignore-tidy-undocumented-unsafe
use crate::fmt;
use crate::ops::{Div, Rem, Sub};

View file

@ -79,6 +79,8 @@
//! }
//! ```
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::fmt;

View file

@ -1,5 +1,7 @@
//! An implementation of SipHash.
// ignore-tidy-undocumented-unsafe
#![allow(deprecated)] // the types in this module are deprecated
use crate::marker::PhantomData;

View file

@ -2,6 +2,8 @@
//! Hints to compiler that affects how code should be emitted or optimized.
// ignore-tidy-undocumented-unsafe
use crate::intrinsics;
/// Informs the compiler that this point in the code is not reachable, enabling

View file

@ -517,8 +517,18 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
// overflow handling
loop {
let mul = n.checked_mul(step);
if unsafe { intrinsics::likely(mul.is_some()) } {
return self.iter.nth(mul.unwrap() - 1);
#[cfg(bootstrap)]
{
// SAFETY: going away soon
if unsafe { intrinsics::likely(mul.is_some()) } {
return self.iter.nth(mul.unwrap() - 1);
}
}
#[cfg(not(bootstrap))]
{
if intrinsics::likely(mul.is_some()) {
return self.iter.nth(mul.unwrap() - 1);
}
}
let div_n = usize::MAX / n;
let div_step = usize::MAX / step;

View file

@ -1,3 +1,5 @@
// ignore-tidy-undocumented-unsafe
use crate::cmp;
use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};

View file

@ -205,6 +205,7 @@ pub trait FromIterator<A>: Sized {
/// .collect()
/// }
/// ```
#[rustc_diagnostic_item = "IntoIterator"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
/// The type of the elements being iterated over.

View file

@ -89,7 +89,7 @@
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![cfg_attr(bootstrap, feature(on_unimplemented))]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]

View file

@ -26,31 +26,29 @@ macro_rules! panic {
/// For details, see `std::macros`.
#[cfg(not(bootstrap))]
#[macro_export]
#[allow_internal_unstable(core_panic, panic_internals)]
#[allow_internal_unstable(core_panic,
// FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling
// the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
// `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
core_intrinsics,
)]
#[stable(feature = "core", since = "1.6.0")]
macro_rules! panic {
() => (
$crate::panic!("explicit panic")
);
($msg:expr) => ({
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
$crate::file!(),
$crate::line!(),
$crate::column!(),
);
$crate::panicking::panic($msg, LOC)
});
($msg:expr) => (
$crate::panicking::panic($msg, $crate::intrinsics::caller_location())
);
($msg:expr,) => (
$crate::panic!($msg)
);
($fmt:expr, $($arg:tt)+) => ({
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
$crate::file!(),
$crate::line!(),
$crate::column!(),
);
$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC)
});
($fmt:expr, $($arg:tt)+) => (
$crate::panicking::panic_fmt(
$crate::format_args!($fmt, $($arg)+),
$crate::intrinsics::caller_location(),
)
);
}
/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
@ -1276,6 +1274,10 @@ pub(crate) mod builtin {
}
/// Inline assembly.
///
/// Read the [unstable book] for the usage.
///
/// [unstable book]: ../unstable-book/library-features/asm.html
#[unstable(feature = "asm", issue = "29722",
reason = "inline assembly is not stable enough for use and is subject to change")]
#[rustc_builtin_macro]

View file

@ -1,6 +1,8 @@
use crate::intrinsics;
use crate::mem::ManuallyDrop;
// ignore-tidy-undocumented-unsafe
/// A wrapper type to construct uninitialized instances of `T`.
///
/// # Initialization invariant
@ -254,10 +256,48 @@ impl<T> MaybeUninit<T> {
/// [type]: union.MaybeUninit.html
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[inline(always)]
#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "maybe_uninit_uninit")]
pub const fn uninit() -> MaybeUninit<T> {
MaybeUninit { uninit: () }
}
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
///
/// Note: in a future Rust version this method may become unnecessary
/// when array literal syntax allows
/// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
/// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
///
/// # Examples
///
/// ```no_run
/// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)]
///
/// use std::mem::MaybeUninit;
///
/// extern "C" {
/// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize;
/// }
///
/// /// Returns a (possibly smaller) slice of data that was actually read
/// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
/// unsafe {
/// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
/// MaybeUninit::slice_get_ref(&buf[..len])
/// }
/// }
///
/// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
/// let data = read(&mut buf);
/// ```
#[unstable(feature = "maybe_uninit_uninit_array", issue = "0")]
#[inline(always)]
pub fn uninit_array<const LEN: usize>() -> [Self; LEN] {
unsafe {
MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init()
}
}
/// A promotable constant, equivalent to `uninit()`.
#[unstable(feature = "internal_uninit_const", issue = "0",
reason = "hack to work around promotability")]
@ -300,6 +340,7 @@ impl<T> MaybeUninit<T> {
/// ```
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[inline]
#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "maybe_uninit_zeroed")]
pub fn zeroed() -> MaybeUninit<T> {
let mut u = MaybeUninit::<T>::uninit();
unsafe {
@ -440,6 +481,7 @@ impl<T> MaybeUninit<T> {
/// ```
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[inline(always)]
#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "assume_init")]
pub unsafe fn assume_init(self) -> T {
intrinsics::panic_if_uninhabited::<T>();
ManuallyDrop::into_inner(self.value)
@ -509,35 +551,212 @@ impl<T> MaybeUninit<T> {
self.as_ptr().read()
}
/// Gets a reference to the contained value.
/// Gets a shared reference to the contained value.
///
/// This can be useful when we want to access a `MaybeUninit` that has been
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
/// of `.assume_init()`).
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
/// Calling this when the content is not yet fully initialized causes undefined
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
/// is in an initialized state.
///
/// # Examples
///
/// ### Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// // Initialize `x`:
/// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
/// // create a shared reference to it:
/// let x: &Vec<u32> = unsafe {
/// // Safety: `x` has been initialized.
/// x.get_ref()
/// };
/// assert_eq!(x, &vec![1, 2, 3]);
/// ```
///
/// ### *Incorrect* usages of this method:
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// let x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_vec: &Vec<u32> = unsafe { x.get_ref() };
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
/// ```
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::{cell::Cell, mem::MaybeUninit};
///
/// let b = MaybeUninit::<Cell<bool>>::uninit();
/// // Initialize the `MaybeUninit` using `Cell::set`:
/// unsafe {
/// b.get_ref().set(true);
/// // ^^^^^^^^^^^
/// // Reference to an uninitialized `Cell<bool>`: UB!
/// }
/// ```
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
#[inline(always)]
pub unsafe fn get_ref(&self) -> &T {
intrinsics::panic_if_uninhabited::<T>();
&*self.value
}
/// Gets a mutable reference to the contained value.
/// Gets a mutable (unique) reference to the contained value.
///
/// This can be useful when we want to access a `MaybeUninit` that has been
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
/// of `.assume_init()`).
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
/// Calling this when the content is not yet fully initialized causes undefined
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
/// is in an initialized state. For instance, `.get_mut()` cannot be used to
/// initialize a `MaybeUninit`.
///
/// # Examples
///
/// ### Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] }
/// # #[cfg(FALSE)]
/// extern "C" {
/// /// Initializes *all* the bytes of the input buffer.
/// fn initialize_buffer(buf: *mut [u8; 2048]);
/// }
///
/// let mut buf = MaybeUninit::<[u8; 2048]>::uninit();
///
/// // Initialize `buf`:
/// unsafe { initialize_buffer(buf.as_mut_ptr()); }
/// // Now we know that `buf` has been initialized, so we could `.assume_init()` it.
/// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes.
/// // To assert our buffer has been initialized without copying it, we upgrade
/// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`:
/// let buf: &mut [u8; 2048] = unsafe {
/// // Safety: `buf` has been initialized.
/// buf.get_mut()
/// };
///
/// // Now we can use `buf` as a normal slice:
/// buf.sort_unstable();
/// assert!(
/// buf.chunks(2).all(|chunk| chunk[0] <= chunk[1]),
/// "buffer is sorted",
/// );
/// ```
///
/// ### *Incorrect* usages of this method:
///
/// You cannot use `.get_mut()` to initialize a value:
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// let mut b = MaybeUninit::<bool>::uninit();
/// unsafe {
/// *b.get_mut() = true;
/// // We have created a (mutable) reference to an uninitialized `bool`!
/// // This is undefined behavior.
/// }
/// ```
///
/// For instance, you cannot [`Read`] into an uninitialized buffer:
///
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::{io, mem::MaybeUninit};
///
/// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]>
/// {
/// let mut buffer = MaybeUninit::<[u8; 64]>::uninit();
/// reader.read_exact(unsafe { buffer.get_mut() })?;
/// // ^^^^^^^^^^^^^^^^
/// // (mutable) reference to uninitialized memory!
/// // This is undefined behavior.
/// Ok(unsafe { buffer.assume_init() })
/// }
/// ```
///
/// Nor can you use direct field access to do field-by-field gradual initialization:
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::{mem::MaybeUninit, ptr};
///
/// struct Foo {
/// a: u32,
/// b: u8,
/// }
///
/// let foo: Foo = unsafe {
/// let mut foo = MaybeUninit::<Foo>::uninit();
/// ptr::write(&mut foo.get_mut().a as *mut u32, 1337);
/// // ^^^^^^^^^^^^^
/// // (mutable) reference to uninitialized memory!
/// // This is undefined behavior.
/// ptr::write(&mut foo.get_mut().b as *mut u8, 42);
/// // ^^^^^^^^^^^^^
/// // (mutable) reference to uninitialized memory!
/// // This is undefined behavior.
/// foo.assume_init()
/// };
/// ```
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
// a final decision about the rules before stabilization.
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
#[inline(always)]
pub unsafe fn get_mut(&mut self) -> &mut T {
intrinsics::panic_if_uninhabited::<T>();
&mut *self.value
}
/// Assuming all the elements are initialized, get a slice to them.
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
/// really are in an initialized state.
/// Calling this when the content is not yet fully initialized causes undefined behavior.
#[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")]
#[inline(always)]
pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] {
&*(slice as *const [Self] as *const [T])
}
/// Assuming all the elements are initialized, get a mutable slice to them.
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
/// really are in an initialized state.
/// Calling this when the content is not yet fully initialized causes undefined behavior.
#[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")]
#[inline(always)]
pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] {
&mut *(slice as *mut [Self] as *mut [T])
}
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]

View file

@ -93,6 +93,8 @@ pub fn forget<T>(t: T) {
#[inline]
#[unstable(feature = "forget_unsized", issue = "0")]
pub fn forget_unsized<T: ?Sized>(t: T) {
// SAFETY: the forget intrinsic could be safe, but there's no point in making it safe since
// we'll be implementing this function soon via `ManuallyDrop`
unsafe { intrinsics::forget(t) }
}
@ -266,7 +268,11 @@ pub const fn size_of<T>() -> usize {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
#[cfg(bootstrap)]
// SAFETY: going away soon
unsafe { intrinsics::size_of_val(val) }
#[cfg(not(bootstrap))]
intrinsics::size_of_val(val)
}
/// Returns the [ABI]-required minimum alignment of a type.
@ -310,7 +316,11 @@ pub fn min_align_of<T>() -> usize {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
#[cfg(bootstrap)]
// SAFETY: going away soon
unsafe { intrinsics::min_align_of_val(val) }
#[cfg(not(bootstrap))]
intrinsics::min_align_of_val(val)
}
/// Returns the [ABI]-required minimum alignment of a type.
@ -350,8 +360,9 @@ pub const fn align_of<T>() -> usize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
min_align_of_val(val)
}
/// Returns `true` if dropping values of type `T` matters.
@ -457,6 +468,7 @@ pub const fn needs_drop<T>() -> bool {
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated_in_future)]
#[allow(deprecated)]
#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "mem_zeroed")]
pub unsafe fn zeroed<T>() -> T {
intrinsics::panic_if_uninhabited::<T>();
intrinsics::init()
@ -485,6 +497,7 @@ pub unsafe fn zeroed<T>() -> T {
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated_in_future)]
#[allow(deprecated)]
#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "mem_uninitialized")]
pub unsafe fn uninitialized<T>() -> T {
intrinsics::panic_if_uninhabited::<T>();
intrinsics::uninit()
@ -508,6 +521,8 @@ pub unsafe fn uninitialized<T>() -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
// SAFETY: the raw pointers have been created from safe mutable references satisfying all the
// constraints on `ptr::swap_nonoverlapping_one`
unsafe {
ptr::swap_nonoverlapping_one(x, y);
}
@ -822,7 +837,11 @@ impl<T> fmt::Debug for Discriminant<T> {
/// ```
#[stable(feature = "discriminant_value", since = "1.21.0")]
pub fn discriminant<T>(v: &T) -> Discriminant<T> {
#[cfg(bootstrap)]
// SAFETY: going away soon
unsafe {
Discriminant(intrinsics::discriminant_value(v), PhantomData)
}
#[cfg(not(bootstrap))]
Discriminant(intrinsics::discriminant_value(v), PhantomData)
}

View file

@ -58,6 +58,8 @@ mod fpu_precision {
pub struct FPUControlWord(u16);
fn set_cw(cw: u16) {
// SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { asm!("fldcw $0" :: "m" (cw) :: "volatile") }
}
@ -74,6 +76,8 @@ mod fpu_precision {
// Get the original value of the control word to restore it later, when the
// `FPUControlWord` structure is dropped
// SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }
// Set the control word to the desired precision. This is achieved by masking away the old

View file

@ -414,6 +414,7 @@ impl f32 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u32 {
// SAFETY: `u32` is a plain old datatype so we can always transmute to it
unsafe { mem::transmute(self) }
}
@ -456,6 +457,7 @@ impl f32 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u32) -> Self {
// SAFETY: `u32` is a plain old datatype so we can always transmute from it
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}

View file

@ -427,6 +427,7 @@ impl f64 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn to_bits(self) -> u64 {
// SAFETY: `u64` is a plain old datatype so we can always transmute to it
unsafe { mem::transmute(self) }
}
@ -469,6 +470,7 @@ impl f64 {
#[stable(feature = "float_bits_conv", since = "1.20.0")]
#[inline]
pub fn from_bits(v: u64) -> Self {
// SAFETY: `u64` is a plain old datatype so we can always transmute from it
// It turns out the safety issues with sNaN were overblown! Hooray!
unsafe { mem::transmute(v) }
}

View file

@ -71,6 +71,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
#[inline]
pub fn new(n: $Int) -> Option<Self> {
if n != 0 {
// SAFETY: we just checked that there's no `0`
Some(unsafe { $Ty(n) })
} else {
None
@ -234,7 +235,6 @@ depending on the target pointer size.
"}
}
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr,
$EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
@ -703,6 +703,7 @@ $EndFeature, "
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
None
} else {
// SAFETY: div by zero and by INT_MIN have been checked above
Some(unsafe { intrinsics::unchecked_div(self, rhs) })
}
}
@ -759,6 +760,7 @@ $EndFeature, "
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
None
} else {
// SAFETY: div by zero and by INT_MIN have been checked above
Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
}
}
@ -1329,6 +1331,8 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
}
@ -1358,6 +1362,8 @@ $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
}
@ -2113,6 +2119,8 @@ assert_eq!(
#[rustc_const_unstable(feature = "const_int_conversion")]
#[inline]
pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
// SAFETY: integers are plain old datatypes so we can always transmute them to
// arrays of bytes
unsafe { mem::transmute(self) }
}
}
@ -2221,6 +2229,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
#[rustc_const_unstable(feature = "const_int_conversion")]
#[inline]
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
// SAFETY: integers are plain old datatypes so we can always transmute to them
unsafe { mem::transmute(bytes) }
}
}
@ -2293,7 +2302,6 @@ impl isize {
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
}
// `Int` + `UnsignedInt` implemented for unsigned integers
macro_rules! uint_impl {
($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
$rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
@ -2748,6 +2756,8 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
pub fn checked_div(self, rhs: Self) -> Option<Self> {
match rhs {
0 => None,
// SAFETY: div by zero has been checked above and unsigned types have no other
// failure modes for division
rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }),
}
}
@ -2799,6 +2809,8 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
if rhs == 0 {
None
} else {
// SAFETY: div by zero has been checked above and unsigned types have no other
// failure modes for division
Some(unsafe { intrinsics::unchecked_rem(self, rhs) })
}
}
@ -3248,6 +3260,8 @@ assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
}
@ -3279,6 +3293,8 @@ assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
without modifying the original"]
#[inline]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
}
@ -3775,11 +3791,11 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
fn one_less_than_next_power_of_two(self) -> Self {
if self <= 1 { return 0; }
// Because `p > 0`, it cannot consist entirely of leading zeros.
let p = self - 1;
// SAFETY: Because `p > 0`, it cannot consist entirely of leading zeros.
// That means the shift is always in-bounds, and some processors
// (such as intel pre-haswell) have more efficient ctlz
// intrinsics when the argument is non-zero.
let p = self - 1;
let z = unsafe { intrinsics::ctlz_nonzero(p) };
<$SelfT>::max_value() >> z
}
@ -3925,6 +3941,8 @@ assert_eq!(
#[rustc_const_unstable(feature = "const_int_conversion")]
#[inline]
pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
// SAFETY: integers are plain old datatypes so we can always transmute them to
// arrays of bytes
unsafe { mem::transmute(self) }
}
}
@ -4033,6 +4051,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
#[rustc_const_unstable(feature = "const_int_conversion")]
#[inline]
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
// SAFETY: integers are plain old datatypes so we can always transmute to them
unsafe { mem::transmute(bytes) }
}
}

View file

@ -133,6 +133,8 @@
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
//! [`i32`]: ../../std/primitive.i32.html
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::iter::{FromIterator, FusedIterator, TrustedLen};

View file

@ -20,6 +20,8 @@
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.
// ignore-tidy-undocumented-unsafe
#![allow(dead_code, missing_docs)]
#![unstable(feature = "core_panic",
reason = "internal details of the implementation of the `panic!` \

View file

@ -552,6 +552,7 @@ impl<P: Deref> Pin<P> {
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
pub fn as_ref(&self) -> Pin<&P::Target> {
// SAFETY: see documentation on this function
unsafe { Pin::new_unchecked(&*self.pointer) }
}
@ -610,6 +611,7 @@ impl<P: DerefMut> Pin<P> {
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
// SAFETY: see documentation on this function
unsafe { Pin::new_unchecked(&mut *self.pointer) }
}

View file

@ -18,6 +18,10 @@
//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
//! * All pointers (except for the null pointer) are valid for all operations of
//! [size zero][zst].
//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer
//! be *dereferencable*: the memory range of the given size starting at the pointer must all be
//! within the bounds of a single allocated object. Note that in Rust,
//! every (stack-allocated) variable is considered a separate allocated object.
//! * All accesses performed by functions in this module are *non-atomic* in the sense
//! of [atomic operations] used to synchronize between threads. This means it is
//! undefined behavior to perform two concurrent accesses to the same location from different
@ -61,6 +65,8 @@
//! [`write_volatile`]: ./fn.write_volatile.html
//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
use crate::intrinsics;
@ -221,10 +227,15 @@ pub(crate) struct FatPtr<T> {
pub(crate) len: usize,
}
/// Forms a slice from a pointer and a length.
/// Forms a raw slice from a pointer and a length.
///
/// The `len` argument is the number of **elements**, not the number of bytes.
///
/// This function is safe, but actually using the return value is unsafe.
/// See the documentation of [`from_raw_parts`] for slice safety requirements.
///
/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html
///
/// # Examples
///
/// ```rust
@ -243,12 +254,16 @@ pub fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
unsafe { Repr { raw: FatPtr { data, len } }.rust }
}
/// Performs the same functionality as [`from_raw_parts`], except that a
/// mutable slice is returned.
/// Performs the same functionality as [`slice_from_raw_parts`], except that a
/// raw mutable slice is returned, as opposed to a raw immutable slice.
///
/// See the documentation of [`from_raw_parts`] for more details.
/// See the documentation of [`slice_from_raw_parts`] for more details.
///
/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html
/// This function is safe, but actually using the return value is unsafe.
/// See the documentation of [`from_raw_parts_mut`] for slice safety requirements.
///
/// [`slice_from_raw_parts`]: fn.slice_from_raw_parts.html
/// [`from_raw_parts_mut`]: ../../std/slice/fn.from_raw_parts_mut.html
#[inline]
#[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")]
pub fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {

View file

@ -7,6 +7,8 @@ use crate::mem;
use crate::ptr::Unique;
use crate::cmp::Ordering;
// ignore-tidy-undocumented-unsafe
/// `*mut T` but non-zero and covariant.
///
/// This is often the correct thing to use when building data structures using

View file

@ -5,6 +5,8 @@ use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ptr::NonNull;
// ignore-tidy-undocumented-unsafe
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.

View file

@ -1,6 +1,8 @@
// Original implementation taken from rust-memchr.
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
// ignore-tidy-undocumented-unsafe
use crate::cmp;
use crate::mem;

View file

@ -1,4 +1,5 @@
// ignore-tidy-filelength
// ignore-tidy-undocumented-unsafe
//! Slice management and manipulation.
//!
@ -5272,18 +5273,24 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
///
/// # Safety
///
/// This function is unsafe as there is no guarantee that the given pointer is
/// valid for `len` elements, nor whether the lifetime inferred is a suitable
/// lifetime for the returned slice.
/// Behavior is undefined if any of the following conditions are violated:
///
/// `data` must be non-null and aligned, even for zero-length slices. One
/// reason for this is that enum layout optimizations may rely on references
/// (including slices of any length) being aligned and non-null to distinguish
/// them from other data. You can obtain a pointer that is usable as `data`
/// for zero-length slices using [`NonNull::dangling()`].
/// * `data` must be [valid] for reads for `len * mem::size_of::<T>()` many bytes,
/// and it must be properly aligned. This means in particular:
///
/// The total size of the slice must be no larger than `isize::MAX` **bytes**
/// in memory. See the safety documentation of [`pointer::offset`].
/// * The entire memory range of this slice must be contained within a single allocated object!
/// Slices can never span across multiple allocated objects.
/// * `data` must be non-null and aligned even for zero-length slices. One
/// reason for this is that enum layout optimizations may rely on references
/// (including slices of any length) being aligned and non-null to distinguish
/// them from other data. You can obtain a pointer that is usable as `data`
/// for zero-length slices using [`NonNull::dangling()`].
///
/// * The memory referenced by the returned slice must not be mutated for the duration
/// of lifetime `'a`, except inside an `UnsafeCell`.
///
/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
/// See the safety documentation of [`pointer::offset`].
///
/// # Caveat
///
@ -5305,6 +5312,7 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
/// assert_eq!(slice[0], 42);
/// ```
///
/// [valid]: ../../std/ptr/index.html#safety
/// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling
/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
#[inline]
@ -5312,28 +5320,45 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
"attempt to create slice covering half the address space");
"attempt to create slice covering at least half the address space");
&*ptr::slice_from_raw_parts(data, len)
}
/// Performs the same functionality as [`from_raw_parts`], except that a
/// mutable slice is returned.
///
/// This function is unsafe for the same reasons as [`from_raw_parts`], as well
/// as not being able to provide a non-aliasing guarantee of the returned
/// mutable slice. `data` must be non-null and aligned even for zero-length
/// slices as with [`from_raw_parts`]. The total size of the slice must be no
/// larger than `isize::MAX` **bytes** in memory.
/// # Safety
///
/// See the documentation of [`from_raw_parts`] for more details.
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `data` must be [valid] for writes for `len * mem::size_of::<T>()` many bytes,
/// and it must be properly aligned. This means in particular:
///
/// * The entire memory range of this slice must be contained within a single allocated object!
/// Slices can never span across multiple allocated objects.
/// * `data` must be non-null and aligned even for zero-length slices. One
/// reason for this is that enum layout optimizations may rely on references
/// (including slices of any length) being aligned and non-null to distinguish
/// them from other data. You can obtain a pointer that is usable as `data`
/// for zero-length slices using [`NonNull::dangling()`].
///
/// * The memory referenced by the returned slice must not be accessed through any other pointer
/// (not derived from the return value) for the duration of lifetime `'a`.
/// Both read and write accesses are forbidden.
///
/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
/// See the safety documentation of [`pointer::offset`].
///
/// [valid]: ../../std/ptr/index.html#safety
/// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling
/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
"attempt to create slice covering half the address space");
"attempt to create slice covering at least half the address space");
&mut *ptr::slice_from_raw_parts_mut(data, len)
}

View file

@ -6,6 +6,8 @@
//! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our
//! stable sorting implementation.
// ignore-tidy-undocumented-unsafe
use crate::cmp;
use crate::mem::{self, MaybeUninit};
use crate::ptr;

View file

@ -3,6 +3,8 @@ use crate::str as core_str;
use crate::fmt::{self, Write};
use crate::mem;
// ignore-tidy-undocumented-unsafe
/// Lossy UTF-8 string.
#[unstable(feature = "str_internals", issue = "0")]
pub struct Utf8Lossy {

View file

@ -1,4 +1,5 @@
// ignore-tidy-filelength
// ignore-tidy-undocumented-unsafe
//! String manipulation.
//!

View file

@ -3,6 +3,8 @@
//! For more details, see the traits [`Pattern`], [`Searcher`],
//! [`ReverseSearcher`], and [`DoubleEndedSearcher`].
// ignore-tidy-undocumented-unsafe
#![unstable(feature = "pattern",
reason = "API not fully fleshed out and ready to be stabilized",
issue = "27721")]

View file

@ -112,6 +112,8 @@
//! println!("live threads: {}", old_thread_count + 1);
//! ```
// ignore-tidy-undocumented-unsafe
#![stable(feature = "rust1", since = "1.0.0")]
#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]

View file

@ -85,6 +85,8 @@ fn ldexp_f64(a: f64, b: i32) -> f64 {
extern {
fn ldexp(x: f64, n: i32) -> f64;
}
// SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly
// cause undefined behavior
unsafe { ldexp(a, b) }
}

View file

@ -920,7 +920,7 @@ impl fmt::Debug for Duration {
if end == 0 {
write!(f, "{}", integer_part)
} else {
// We are only writing ASCII digits into the buffer and it was
// SAFETY: We are only writing ASCII digits into the buffer and it was
// initialized with '0's, so it contains valid UTF8.
let s = unsafe {
crate::str::from_utf8_unchecked(&buf[..end])

View file

@ -35,7 +35,7 @@ impl InnerOffset {
/// A piece is a portion of the format string which represents the next part
/// to emit. These are emitted as a stream by the `Parser` class.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Piece<'a> {
/// A literal string which should directly be emitted
String(&'a str),
@ -45,7 +45,7 @@ pub enum Piece<'a> {
}
/// Representation of an argument specification.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Argument<'a> {
/// Where to find this argument
pub position: Position,
@ -54,7 +54,7 @@ pub struct Argument<'a> {
}
/// Specification for the formatting of an argument in the format string.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct FormatSpec<'a> {
/// Optionally specified character to fill alignment with.
pub fill: Option<char>,
@ -74,10 +74,12 @@ pub struct FormatSpec<'a> {
/// this argument, this can be empty or any number of characters, although
/// it is required to be one word.
pub ty: &'a str,
/// The span of the descriptor string (for diagnostics).
pub ty_span: Option<InnerSpan>,
}
/// Enum describing where an argument for a format can be located.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Position {
/// The argument is implied to be located at an index
ArgumentImplicitlyIs(usize),
@ -97,7 +99,7 @@ impl Position {
}
/// Enum of alignments which are supported.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Alignment {
/// The value will be aligned to the left.
AlignLeft,
@ -111,7 +113,7 @@ pub enum Alignment {
/// Various flags which can be applied to format strings. The meaning of these
/// flags is defined by the formatters themselves.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Flag {
/// A `+` will be used to denote positive numbers.
FlagSignPlus,
@ -131,7 +133,7 @@ pub enum Flag {
/// A count is used for the precision and width parameters of an integer, and
/// can reference either an argument or a literal integer.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Count {
/// The count is specified explicitly.
CountIs(usize),
@ -475,6 +477,7 @@ impl<'a> Parser<'a> {
width: CountImplied,
width_span: None,
ty: &self.input[..0],
ty_span: None,
};
if !self.consume(':') {
return spec;
@ -548,6 +551,7 @@ impl<'a> Parser<'a> {
spec.precision_span = sp;
}
}
let ty_span_start = self.cur.peek().map(|(pos, _)| *pos);
// Optional radix followed by the actual format specifier
if self.consume('x') {
if self.consume('?') {
@ -567,6 +571,12 @@ impl<'a> Parser<'a> {
spec.ty = "?";
} else {
spec.ty = self.word();
let ty_span_end = self.cur.peek().map(|(pos, _)| *pos);
if !spec.ty.is_empty() {
spec.ty_span = ty_span_start
.and_then(|s| ty_span_end.map(|e| (s, e)))
.map(|(start, end)| self.to_span_index(start).to(self.to_span_index(end)));
}
}
spec
}

View file

@ -2,7 +2,7 @@ use super::*;
fn same(fmt: &'static str, p: &[Piece<'static>]) {
let parser = Parser::new(fmt, None, vec![], false);
assert!(parser.collect::<Vec<Piece<'static>>>() == p);
assert_eq!(parser.collect::<Vec<Piece<'static>>>(), p);
}
fn fmtdflt() -> FormatSpec<'static> {
@ -15,6 +15,7 @@ fn fmtdflt() -> FormatSpec<'static> {
precision_span: None,
width_span: None,
ty: "",
ty_span: None,
};
}
@ -82,7 +83,7 @@ fn format_position_nothing_else() {
#[test]
fn format_type() {
same(
"{3:a}",
"{3:x}",
&[NextArgument(Argument {
position: ArgumentIs(3),
format: FormatSpec {
@ -93,7 +94,8 @@ fn format_type() {
width: CountImplied,
precision_span: None,
width_span: None,
ty: "a",
ty: "x",
ty_span: None,
},
})]);
}
@ -112,6 +114,7 @@ fn format_align_fill() {
precision_span: None,
width_span: None,
ty: "",
ty_span: None,
},
})]);
same(
@ -127,6 +130,7 @@ fn format_align_fill() {
precision_span: None,
width_span: None,
ty: "",
ty_span: None,
},
})]);
same(
@ -142,6 +146,7 @@ fn format_align_fill() {
precision_span: None,
width_span: None,
ty: "abcd",
ty_span: Some(InnerSpan::new(6, 10)),
},
})]);
}
@ -150,7 +155,7 @@ fn format_counts() {
use syntax_pos::{GLOBALS, Globals, edition};
GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
same(
"{:10s}",
"{:10x}",
&[NextArgument(Argument {
position: ArgumentImplicitlyIs(0),
format: FormatSpec {
@ -161,11 +166,12 @@ fn format_counts() {
width: CountIs(10),
precision_span: None,
width_span: None,
ty: "s",
ty: "x",
ty_span: None,
},
})]);
same(
"{:10$.10s}",
"{:10$.10x}",
&[NextArgument(Argument {
position: ArgumentImplicitlyIs(0),
format: FormatSpec {
@ -176,11 +182,12 @@ fn format_counts() {
width: CountIsParam(10),
precision_span: None,
width_span: Some(InnerSpan::new(3, 6)),
ty: "s",
ty: "x",
ty_span: None,
},
})]);
same(
"{:.*s}",
"{:.*x}",
&[NextArgument(Argument {
position: ArgumentImplicitlyIs(1),
format: FormatSpec {
@ -191,11 +198,12 @@ fn format_counts() {
width: CountImplied,
precision_span: Some(InnerSpan::new(3, 5)),
width_span: None,
ty: "s",
ty: "x",
ty_span: None,
},
})]);
same(
"{:.10$s}",
"{:.10$x}",
&[NextArgument(Argument {
position: ArgumentImplicitlyIs(0),
format: FormatSpec {
@ -206,11 +214,12 @@ fn format_counts() {
width: CountImplied,
precision_span: Some(InnerSpan::new(3, 7)),
width_span: None,
ty: "s",
ty: "x",
ty_span: None,
},
})]);
same(
"{:a$.b$s}",
"{:a$.b$?}",
&[NextArgument(Argument {
position: ArgumentImplicitlyIs(0),
format: FormatSpec {
@ -221,7 +230,8 @@ fn format_counts() {
width: CountIsName(Symbol::intern("a")),
precision_span: None,
width_span: None,
ty: "s",
ty: "?",
ty_span: None,
},
})]);
});
@ -241,6 +251,7 @@ fn format_flags() {
precision_span: None,
width_span: None,
ty: "",
ty_span: None,
},
})]);
same(
@ -256,13 +267,14 @@ fn format_flags() {
precision_span: None,
width_span: None,
ty: "",
ty_span: None,
},
})]);
}
#[test]
fn format_mixture() {
same(
"abcd {3:a} efg",
"abcd {3:x} efg",
&[
String("abcd "),
NextArgument(Argument {
@ -275,7 +287,8 @@ fn format_mixture() {
width: CountImplied,
precision_span: None,
width_span: None,
ty: "a",
ty: "x",
ty_span: None,
},
}),
String(" efg"),

View file

@ -21,6 +21,7 @@
// Rust's "try" function, but if we're aborting on panics we just call the
// function as there's nothing else we need to do here.
#[rustc_std_internal_symbol]
#[allow(improper_ctypes)]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
data: *mut u8,
_data_ptr: *mut usize,

View file

@ -69,6 +69,7 @@ mod dwarf;
// hairy and tightly coupled, for more information see the compiler's
// implementation of this.
#[no_mangle]
#[allow(improper_ctypes)]
pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8),
data: *mut u8,
data_ptr: *mut usize,

View file

@ -39,5 +39,5 @@ parking_lot = "0.9"
byteorder = { version = "1.3" }
chalk-engine = { version = "0.9.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" }
smallvec = { version = "0.6.8", features = ["union", "may_dangle"] }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
measureme = "0.4"

View file

@ -304,7 +304,7 @@ impl DropArena {
// Move the content to the arena by copying it and then forgetting
// the content of the SmallVec
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
mem::forget(vec.drain());
mem::forget(vec.drain(..));
// Record the destructors after doing the allocation as that may panic
// and would cause `object`'s destuctor to run twice if it was recorded before

View file

@ -525,7 +525,7 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum {
}
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
tcx.crate_name(*self).as_str().to_string()
tcx.crate_name(*self).to_string()
}
}

View file

@ -335,7 +335,7 @@ This works because `Box` is a pointer, so its size is well-known.
"##,
E0080: r##"
This error indicates that the compiler was unable to sensibly evaluate an
This error indicates that the compiler was unable to sensibly evaluate a
constant expression that had to be evaluated. Attempting to divide by 0
or causing integer overflow are two ways to induce this error. For example:
@ -607,7 +607,7 @@ position that needs that trait. For example, when the following code is
compiled:
```compile_fail
#![feature(on_unimplemented)]
#![feature(rustc_attrs)]
fn foo<T: Index<u8>>(x: T){}
@ -639,7 +639,7 @@ position that needs that trait. For example, when the following code is
compiled:
```compile_fail
#![feature(on_unimplemented)]
#![feature(rustc_attrs)]
fn foo<T: Index<u8>>(x: T){}
@ -669,7 +669,7 @@ position that needs that trait. For example, when the following code is
compiled:
```compile_fail
#![feature(on_unimplemented)]
#![feature(rustc_attrs)]
fn foo<T: Index<u8>>(x: T){}
@ -2336,6 +2336,7 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC.
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
E0703, // invalid ABI
// E0707, // multiple elided lifetimes used in arguments of `async fn`
E0708, // `async` non-`move` closures with parameters are not currently
// supported

View file

@ -40,10 +40,10 @@ pub enum NonMacroAttrKind {
Tool,
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
DeriveHelper,
/// Single-segment custom attribute registered with `#[register_attr]`.
Registered,
/// Single-segment custom attribute registered by a legacy plugin (`register_attribute`).
LegacyPluginHelper,
/// Single-segment custom attribute not registered in any way (`#[my_attr]`).
Custom,
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
@ -329,8 +329,24 @@ impl NonMacroAttrKind {
NonMacroAttrKind::Builtin => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper => "derive helper attribute",
NonMacroAttrKind::Registered => "explicitly registered attribute",
NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
NonMacroAttrKind::Custom => "custom attribute",
}
}
pub fn article(self) -> &'static str {
match self {
NonMacroAttrKind::Registered => "an",
_ => "a",
}
}
/// Users of some attributes cannot mark them as used, so they are considered always used.
pub fn is_used(self) -> bool {
match self {
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered |
NonMacroAttrKind::LegacyPluginHelper => false,
}
}
}
@ -389,6 +405,7 @@ impl<Id> Res<Id> {
pub fn article(&self) -> &'static str {
match *self {
Res::Def(kind, _) => kind.article(),
Res::NonMacroAttr(kind) => kind.article(),
Res::Err => "an",
_ => "a",
}

View file

@ -45,7 +45,7 @@ pub enum FnKind<'a> {
ItemFn(Ident, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]),
/// `fn foo(&self)`
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]),
Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a [Attribute]),
/// `|x, y| {}`
Closure(&'a [Attribute]),
@ -481,13 +481,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_ty(typ);
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref declaration, header, ref generics, body_id) => {
ItemKind::Fn(ref sig, ref generics, body_id) => {
visitor.visit_fn(FnKind::ItemFn(item.ident,
generics,
header,
sig.header,
&item.vis,
&item.attrs),
declaration,
&sig.decl,
body_id,
item.span,
item.hir_id)

View file

@ -44,8 +44,7 @@ use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS};
use crate::hir::{GenericArg, ConstArg};
use crate::hir::ptr::P;
use crate::lint;
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
ELIDED_LIFETIMES_IN_PATHS};
use crate::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
use crate::middle::cstore::CrateStore;
use crate::session::Session;
use crate::session::config::nightly_options;
@ -65,9 +64,8 @@ use syntax::ast;
use syntax::ptr::P as AstP;
use syntax::ast::*;
use syntax::errors;
use syntax::expand::SpecialDerives;
use syntax::print::pprust;
use syntax::parse::token::{self, Nonterminal, Token};
use syntax::token::{self, Nonterminal, Token};
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::sess::ParseSess;
use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
@ -184,9 +182,9 @@ pub trait Resolver {
ns: Namespace,
) -> (ast::Path, Res<NodeId>);
fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool;
fn lint_buffer(&mut self) -> &mut lint::LintBuffer;
fn next_node_id(&mut self) -> NodeId;
}
type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
@ -301,7 +299,6 @@ enum ParamMode {
enum ParenthesizedGenericArgs {
Ok,
Warn,
Err,
}
@ -677,7 +674,8 @@ impl<'a> LoweringContext<'a> {
}
fn next_id(&mut self) -> hir::HirId {
self.lower_node_id(self.sess.next_node_id())
let node_id = self.resolver.next_node_id();
self.lower_node_id(node_id)
}
fn lower_res(&mut self, res: Res<NodeId>) -> Res {
@ -786,7 +784,7 @@ impl<'a> LoweringContext<'a> {
hir_name: ParamName,
parent_index: DefIndex,
) -> hir::GenericParam {
let node_id = self.sess.next_node_id();
let node_id = self.resolver.next_node_id();
// Get the name we'll use to make the def-path. Note
// that collisions are ok here and this shouldn't
@ -1000,14 +998,20 @@ impl<'a> LoweringContext<'a> {
// Note that we explicitly do not walk the path. Since we don't really
// lower attributes (we use the AST version) there is nowhere to keep
// the `HirId`s. We don't actually need HIR version of attributes anyway.
let kind = match attr.kind {
AttrKind::Normal(ref item) => {
AttrKind::Normal(AttrItem {
path: item.path.clone(),
tokens: self.lower_token_stream(item.tokens.clone()),
})
}
AttrKind::DocComment(comment) => AttrKind::DocComment(comment)
};
Attribute {
item: AttrItem {
path: attr.path.clone(),
tokens: self.lower_token_stream(attr.tokens.clone()),
},
kind,
id: attr.id,
style: attr.style,
is_sugared_doc: attr.is_sugared_doc,
span: attr.span,
}
}
@ -1105,7 +1109,7 @@ impl<'a> LoweringContext<'a> {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that.
let impl_trait_node_id = self.sess.next_node_id();
let impl_trait_node_id = self.resolver.next_node_id();
let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
self.resolver.definitions().create_def_with_parent(
parent_def_index,
@ -1116,9 +1120,10 @@ impl<'a> LoweringContext<'a> {
);
self.with_dyn_type_scope(false, |this| {
let node_id = this.resolver.next_node_id();
let ty = this.lower_ty(
&Ty {
id: this.sess.next_node_id(),
id: node_id,
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
span: constraint.span,
},
@ -1212,8 +1217,8 @@ impl<'a> LoweringContext<'a> {
&NodeMap::default(),
ImplTraitContext::disallowed(),
),
unsafety: this.lower_unsafety(f.unsafety),
abi: f.abi,
unsafety: f.unsafety,
abi: this.lower_abi(f.abi),
decl: this.lower_fn_decl(&f.decl, None, false, None),
param_names: this.lower_fn_params_to_names(&f.decl),
}))
@ -1585,7 +1590,7 @@ impl<'a> LoweringContext<'a> {
name,
}));
let def_node_id = self.context.sess.next_node_id();
let def_node_id = self.context.resolver.next_node_id();
let hir_id =
self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id);
self.context.resolver.definitions().create_def_with_parent(
@ -1698,29 +1703,19 @@ impl<'a> LoweringContext<'a> {
};
let parenthesized_generic_args = match partial_res.base_res() {
// `a::b::Trait(Args)`
Res::Def(DefKind::Trait, _)
if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
ParenthesizedGenericArgs::Ok
}
// `a::b::Trait(Args)::TraitItem`
Res::Def(DefKind::Method, _)
| Res::Def(DefKind::AssocConst, _)
| Res::Def(DefKind::AssocTy, _)
if i + 2 == proj_start =>
{
Res::Def(DefKind::Method, _) |
Res::Def(DefKind::AssocConst, _) |
Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => {
ParenthesizedGenericArgs::Ok
}
// Avoid duplicated errors.
Res::Err => ParenthesizedGenericArgs::Ok,
// An error
Res::Def(DefKind::Struct, _)
| Res::Def(DefKind::Enum, _)
| Res::Def(DefKind::Union, _)
| Res::Def(DefKind::TyAlias, _)
| Res::Def(DefKind::Variant, _) if i + 1 == proj_start =>
{
ParenthesizedGenericArgs::Err
}
// A warning for now, for compatibility reasons.
_ => ParenthesizedGenericArgs::Warn,
_ => ParenthesizedGenericArgs::Err,
};
let num_lifetimes = type_def_id.map_or(0, |def_id| {
@ -1783,7 +1778,7 @@ impl<'a> LoweringContext<'a> {
segment,
param_mode,
0,
ParenthesizedGenericArgs::Warn,
ParenthesizedGenericArgs::Err,
itctx.reborrow(),
None,
));
@ -1859,15 +1854,6 @@ impl<'a> LoweringContext<'a> {
}
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
ParenthesizedGenericArgs::Warn => {
self.resolver.lint_buffer().buffer_lint(
PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
CRATE_NODE_ID,
data.span,
msg.into(),
);
(hir::GenericArgs::none(), true)
}
ParenthesizedGenericArgs::Err => {
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
err.span_label(data.span, "only `Fn` traits may use parentheses");
@ -2095,13 +2081,6 @@ impl<'a> LoweringContext<'a> {
}, ids)
}
fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
match m {
Mutability::Mutable => hir::MutMutable,
Mutability::Immutable => hir::MutImmutable,
}
}
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
// as they are not explicit in HIR/Ty function signatures.
@ -2671,7 +2650,7 @@ impl<'a> LoweringContext<'a> {
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy {
hir::MutTy {
ty: self.lower_ty(&mt.ty, itctx),
mutbl: self.lower_mutability(mt.mutbl),
mutbl: mt.mutbl,
}
}
@ -2772,7 +2751,7 @@ impl<'a> LoweringContext<'a> {
}
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
PatKind::Ref(ref inner, mutbl) => {
hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
hir::PatKind::Ref(self.lower_pat(inner), mutbl)
}
PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
P(self.lower_expr(e1)),
@ -3252,7 +3231,7 @@ impl<'a> LoweringContext<'a> {
Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
None => (
self.sess.next_node_id(),
self.resolver.next_node_id(),
"`&` without an explicit lifetime name cannot be used here",
"explicit lifetime name needed here",
),
@ -3289,7 +3268,7 @@ impl<'a> LoweringContext<'a> {
span,
"expected 'implicit elided lifetime not allowed' error",
);
let id = self.sess.next_node_id();
let id = self.resolver.next_node_id();
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
}
// `PassThrough` is the normal case.
@ -3385,7 +3364,7 @@ pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
// either in std or core, i.e. has either a `::std::ops::Range` or
// `::core::ops::Range` prefix.
fn is_range_path(path: &Path) -> bool {
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.as_str().to_string()).collect();
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
// "{{root}}" is the equivalent of `::` prefix in `Path`.
@ -3426,7 +3405,7 @@ pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
ExprKind::Call(ref func, _) => {
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
let new_call = segment.ident.as_str() == "new";
let new_call = segment.ident.name == sym::new;
return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
}
}

View file

@ -64,7 +64,6 @@ impl LoweringContext<'_> {
hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
}
ExprKind::AddrOf(m, ref ohs) => {
let m = self.lower_mutability(m);
let ohs = P(self.lower_expr(ohs));
hir::ExprKind::AddrOf(m, ohs)
}
@ -474,7 +473,6 @@ impl LoweringContext<'_> {
async_gen_kind: hir::AsyncGeneratorKind,
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
) -> hir::ExprKind {
let capture_clause = self.lower_capture_clause(capture_clause);
let output = match ret_ty {
Some(ty) => FunctionRetTy::Ty(ty),
None => FunctionRetTy::Default(span),
@ -495,7 +493,7 @@ impl LoweringContext<'_> {
decl,
body_id,
span,
Some(hir::GeneratorMovability::Static)
Some(hir::Movability::Static)
);
let generator = hir::Expr {
hir_id: self.lower_node_id(closure_node_id),
@ -595,7 +593,7 @@ impl LoweringContext<'_> {
};
// `::std::task::Poll::Ready(result) => break result`
let loop_node_id = self.sess.next_node_id();
let loop_node_id = self.resolver.next_node_id();
let loop_hir_id = self.lower_node_id(loop_node_id);
let ready_arm = {
let x_ident = Ident::with_dummy_span(sym::result);
@ -701,7 +699,6 @@ impl LoweringContext<'_> {
generator_kind,
movability,
);
let capture_clause = this.lower_capture_clause(capture_clause);
this.current_item = prev;
hir::ExprKind::Closure(
capture_clause,
@ -713,20 +710,13 @@ impl LoweringContext<'_> {
})
}
fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
match c {
CaptureBy::Value => hir::CaptureByValue,
CaptureBy::Ref => hir::CaptureByRef,
}
}
fn generator_movability_for_fn(
&mut self,
decl: &FnDecl,
fn_decl_span: Span,
generator_kind: Option<hir::GeneratorKind>,
movability: Movability,
) -> Option<hir::GeneratorMovability> {
) -> Option<hir::Movability> {
match generator_kind {
Some(hir::GeneratorKind::Gen) => {
if !decl.inputs.is_empty() {
@ -737,10 +727,7 @@ impl LoweringContext<'_> {
"generators cannot have explicit parameters"
);
}
Some(match movability {
Movability::Movable => hir::GeneratorMovability::Movable,
Movability::Static => hir::GeneratorMovability::Static,
})
Some(movability)
},
Some(hir::GeneratorKind::Async(_)) => {
bug!("non-`async` closure body turned `async` during lowering");
@ -811,7 +798,7 @@ impl LoweringContext<'_> {
this.expr(fn_decl_span, async_body, ThinVec::new())
});
hir::ExprKind::Closure(
this.lower_capture_clause(capture_clause),
capture_clause,
fn_decl,
body_id,
fn_decl_span,
@ -1350,7 +1337,7 @@ impl LoweringContext<'_> {
}
fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
self.expr(span, hir::ExprKind::AddrOf(hir::MutMutable, e), ThinVec::new())
self.expr(span, hir::ExprKind::AddrOf(hir::Mutability::Mutable, e), ThinVec::new())
}
fn expr_unit(&mut self, sp: Span) -> hir::Expr {

View file

@ -12,14 +12,14 @@ use crate::hir::def::{Res, DefKind};
use crate::util::nodemap::NodeMap;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_target::spec::abi;
use std::collections::BTreeSet;
use smallvec::SmallVec;
use syntax::attr;
use syntax::ast::*;
use syntax::visit::{self, Visitor};
use syntax::expand::SpecialDerives;
use syntax::source_map::{respan, DesugaringKind, Spanned};
use syntax::source_map::{respan, DesugaringKind};
use syntax::symbol::{kw, sym};
use syntax_pos::Span;
@ -227,13 +227,7 @@ impl LoweringContext<'_> {
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
let mut ident = i.ident;
let mut vis = self.lower_visibility(&i.vis, None);
let mut attrs = self.lower_attrs_extendable(&i.attrs);
if self.resolver.has_derives(i.id, SpecialDerives::PARTIAL_EQ | SpecialDerives::EQ) {
// Add `#[structural_match]` if the item derived both `PartialEq` and `Eq`.
let ident = Ident::new(sym::structural_match, i.span);
attrs.push(attr::mk_attr_outer(attr::mk_word_item(ident)));
}
let attrs = attrs.into();
let attrs = self.lower_attrs(&i.attrs);
if let ItemKind::MacroDef(ref def) = i.kind {
if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
@ -295,7 +289,7 @@ impl LoweringContext<'_> {
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
}
),
self.lower_mutability(m),
m,
self.lower_const_body(e),
)
}
@ -312,7 +306,7 @@ impl LoweringContext<'_> {
self.lower_const_body(e)
)
}
ItemKind::Fn(ref decl, header, ref generics, ref body) => {
ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
let fn_def_id = self.resolver.definitions().local_def_id(id);
self.with_new_scopes(|this| {
this.current_item = Some(ident.span);
@ -323,7 +317,7 @@ impl LoweringContext<'_> {
// declaration (decl), not the return types.
let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
let (generics, fn_decl) = this.add_in_band_defs(
let (generics, decl) = this.add_in_band_defs(
generics,
fn_def_id,
AnonymousLifetimeMode::PassThrough,
@ -334,13 +328,8 @@ impl LoweringContext<'_> {
header.asyncness.node.opt_return_id()
),
);
hir::ItemKind::Fn(
fn_decl,
this.lower_fn_header(header),
generics,
body_id,
)
let sig = hir::FnSig { decl, header: this.lower_fn_header(header) };
hir::ItemKind::Fn(sig, generics, body_id)
})
}
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
@ -444,8 +433,8 @@ impl LoweringContext<'_> {
);
hir::ItemKind::Impl(
self.lower_unsafety(unsafety),
self.lower_impl_polarity(polarity),
unsafety,
polarity,
self.lower_defaultness(defaultness, true /* [1] */),
generics,
trait_ref,
@ -460,8 +449,8 @@ impl LoweringContext<'_> {
.map(|item| self.lower_trait_item_ref(item))
.collect();
hir::ItemKind::Trait(
self.lower_is_auto(is_auto),
self.lower_unsafety(unsafety),
is_auto,
unsafety,
self.lower_generics(generics, ImplTraitContext::disallowed()),
bounds,
items,
@ -533,7 +522,7 @@ impl LoweringContext<'_> {
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
seg.id = self.sess.next_node_id();
seg.id = self.resolver.next_node_id();
}
let span = path.span;
@ -610,7 +599,7 @@ impl LoweringContext<'_> {
// Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments {
seg.id = self.sess.next_node_id();
seg.id = self.resolver.next_node_id();
}
// Each `use` import is an item and thus are owners of the
@ -730,7 +719,7 @@ impl LoweringContext<'_> {
}
ForeignItemKind::Static(ref t, m) => {
hir::ForeignItemKind::Static(
self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m))
self.lower_ty(t, ImplTraitContext::disallowed()), m)
}
ForeignItemKind::Ty => hir::ForeignItemKind::Type,
ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"),
@ -742,7 +731,7 @@ impl LoweringContext<'_> {
fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
hir::ForeignMod {
abi: fm.abi,
abi: self.lower_abi(fm.abi),
items: fm.items
.iter()
.map(|x| self.lower_foreign_item(x))
@ -1022,13 +1011,6 @@ impl LoweringContext<'_> {
}
}
fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
match i {
ImplPolarity::Positive => hir::ImplPolarity::Positive,
ImplPolarity::Negative => hir::ImplPolarity::Negative,
}
}
fn record_body(&mut self, params: HirVec<hir::Param>, value: hir::Expr) -> hir::BodyId {
let body = hir::Body {
generator_kind: self.generator_kind,
@ -1266,11 +1248,11 @@ impl LoweringContext<'_> {
fn lower_method_sig(
&mut self,
generics: &Generics,
sig: &MethodSig,
sig: &FnSig,
fn_def_id: DefId,
impl_trait_return_allow: bool,
is_async: Option<NodeId>,
) -> (hir::Generics, hir::MethodSig) {
) -> (hir::Generics, hir::FnSig) {
let header = self.lower_fn_header(sig.header);
let (generics, decl) = self.add_in_band_defs(
generics,
@ -1283,37 +1265,36 @@ impl LoweringContext<'_> {
is_async,
),
);
(generics, hir::MethodSig { header, decl })
}
fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
match a {
IsAuto::Yes => hir::IsAuto::Yes,
IsAuto::No => hir::IsAuto::No,
}
(generics, hir::FnSig { header, decl })
}
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
hir::FnHeader {
unsafety: self.lower_unsafety(h.unsafety),
unsafety: h.unsafety,
asyncness: self.lower_asyncness(h.asyncness.node),
constness: self.lower_constness(h.constness),
abi: h.abi,
constness: h.constness.node,
abi: self.lower_abi(h.abi),
}
}
pub(super) fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
match u {
Unsafety::Unsafe => hir::Unsafety::Unsafe,
Unsafety::Normal => hir::Unsafety::Normal,
}
pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi {
abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| {
self.error_on_invalid_abi(abi);
abi::Abi::Rust
})
}
fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
match c.node {
Constness::Const => hir::Constness::Const,
Constness::NotConst => hir::Constness::NotConst,
}
fn error_on_invalid_abi(&self, abi: Abi) {
struct_span_err!(
self.sess,
abi.span,
E0703,
"invalid ABI: found `{}`",
abi.symbol
)
.span_label(abi.span, "invalid ABI")
.help(&format!("valid ABIs: {}", abi::all_names().join(", ")))
.emit();
}
fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {

View file

@ -158,25 +158,25 @@ impl<'a> FnLikeNode<'a> {
pub fn body(self) -> ast::BodyId {
self.handle(|i: ItemFnParts<'a>| i.body,
|_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body,
|_, _, _: &'a ast::FnSig, _, body: ast::BodyId, _, _| body,
|c: ClosureParts<'a>| c.body)
}
pub fn decl(self) -> &'a FnDecl {
self.handle(|i: ItemFnParts<'a>| &*i.decl,
|_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl,
|_, _, sig: &'a ast::FnSig, _, _, _, _| &sig.decl,
|c: ClosureParts<'a>| c.decl)
}
pub fn span(self) -> Span {
self.handle(|i: ItemFnParts<'_>| i.span,
|_, _, _: &'a ast::MethodSig, _, _, span, _| span,
|_, _, _: &'a ast::FnSig, _, _, span, _| span,
|c: ClosureParts<'_>| c.span)
}
pub fn id(self) -> ast::HirId {
self.handle(|i: ItemFnParts<'_>| i.id,
|id, _, _: &'a ast::MethodSig, _, _, _, _| id,
|id, _, _: &'a ast::FnSig, _, _, _, _| id,
|c: ClosureParts<'_>| c.id)
}
@ -199,7 +199,7 @@ impl<'a> FnLikeNode<'a> {
let closure = |c: ClosureParts<'a>| {
FnKind::Closure(c.attrs)
};
let method = |_, ident: Ident, sig: &'a ast::MethodSig, vis, _, _, attrs| {
let method = |_, ident: Ident, sig: &'a ast::FnSig, vis, _, _, attrs| {
FnKind::Method(ident, sig, vis, attrs)
};
self.handle(item, method, closure)
@ -209,7 +209,7 @@ impl<'a> FnLikeNode<'a> {
I: FnOnce(ItemFnParts<'a>) -> A,
M: FnOnce(ast::HirId,
Ident,
&'a ast::MethodSig,
&'a ast::FnSig,
Option<&'a ast::Visibility>,
ast::BodyId,
Span,
@ -219,16 +219,16 @@ impl<'a> FnLikeNode<'a> {
{
match self.node {
map::Node::Item(i) => match i.kind {
ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
ast::ItemKind::Fn(ref sig, ref generics, block) =>
item_fn(ItemFnParts {
id: i.hir_id,
ident: i.ident,
decl: &decl,
decl: &sig.decl,
body: block,
vis: &i.vis,
span: i.span,
attrs: &i.attrs,
header,
header: sig.header,
generics,
}),
_ => bug!("item FnLikeNode that is not fn-like"),

View file

@ -4,7 +4,7 @@ use crate::hir::def_id::DefIndex;
use syntax::ast::*;
use syntax::visit;
use syntax::symbol::{kw, sym};
use syntax::parse::token::{self, Token};
use syntax::token::{self, Token};
use syntax_pos::hygiene::ExpnId;
use syntax_pos::Span;
@ -100,7 +100,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
// Pick the def data. This need not be unique, but the more
// information we encapsulate into, the better
let def_data = match i.kind {
let def_data = match &i.kind {
ItemKind::Impl(..) => DefPathData::Impl,
ItemKind::Mod(..) if i.ident.name == kw::Invalid => {
return visit::walk_item(self, i);
@ -109,19 +109,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
ItemKind::OpaqueTy(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
ItemKind::Fn(
ref decl,
ref header,
ref generics,
ref body,
) if header.asyncness.node.is_async() => {
ItemKind::Fn(sig, generics, body) if sig.header.asyncness.node.is_async() => {
return self.visit_async_fn(
i.id,
i.ident.name,
i.span,
header,
&sig.header,
generics,
decl,
&sig.decl,
body,
)
}
@ -228,7 +223,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
let def_data = match ii.kind {
ImplItemKind::Method(MethodSig {
ImplItemKind::Method(FnSig {
ref header,
ref decl,
}, ref body) if header.asyncness.node.is_async() => {

View file

@ -19,7 +19,7 @@ use std::hash::Hash;
use syntax::ast;
use syntax_pos::symbol::{Symbol, sym};
use syntax_pos::hygiene::ExpnId;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::Span;
/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
@ -310,10 +310,6 @@ pub enum DefPathData {
AnonConst,
/// An `impl Trait` type node.
ImplTrait,
/// Identifies a piece of crate metadata that is global to a whole crate
/// (as opposed to just one item). `GlobalMetaData` components are only
/// supposed to show up right below the crate root.
GlobalMetaData(Symbol),
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@ -444,9 +440,6 @@ impl Definitions {
self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
self.set_invocation_parent(ExpnId::root(), root_index);
// Allocate some other `DefIndex`es that always must exist.
GlobalMetaDataKind::allocate_def_indices(self);
root_index
}
@ -553,8 +546,7 @@ impl DefPathData {
TypeNs(name) |
ValueNs(name) |
MacroNs(name) |
LifetimeNs(name) |
GlobalMetaData(name) => Some(name),
LifetimeNs(name) => Some(name),
Impl |
CrateRoot |
@ -572,8 +564,7 @@ impl DefPathData {
TypeNs(name) |
ValueNs(name) |
MacroNs(name) |
LifetimeNs(name) |
GlobalMetaData(name) => {
LifetimeNs(name) => {
name
}
// Note that this does not show up in user print-outs.
@ -591,78 +582,3 @@ impl DefPathData {
self.as_symbol().to_string()
}
}
// We define the `GlobalMetaDataKind` enum with this macro because we want to
// make sure that we exhaustively iterate over all variants when registering
// the corresponding `DefIndex`es in the `DefTable`.
macro_rules! define_global_metadata_kind {
(pub enum GlobalMetaDataKind {
$($variant:ident),*
}) => (
pub enum GlobalMetaDataKind {
$($variant),*
}
impl GlobalMetaDataKind {
fn allocate_def_indices(definitions: &mut Definitions) {
$({
let instance = GlobalMetaDataKind::$variant;
definitions.create_def_with_parent(
CRATE_DEF_INDEX,
ast::DUMMY_NODE_ID,
DefPathData::GlobalMetaData(instance.name()),
ExpnId::root(),
DUMMY_SP
);
// Make sure calling `def_index` does not crash.
instance.def_index(&definitions.table);
})*
}
pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex {
let def_key = DefKey {
parent: Some(CRATE_DEF_INDEX),
disambiguated_data: DisambiguatedDefPathData {
data: DefPathData::GlobalMetaData(self.name()),
disambiguator: 0,
}
};
// These `DefKey`s are all right after the root,
// so a linear search is fine.
let index = def_path_table.index_to_key
.iter()
.position(|k| *k == def_key)
.unwrap();
DefIndex::from(index)
}
fn name(&self) -> Symbol {
let string = match *self {
$(
GlobalMetaDataKind::$variant => {
concat!("{{GlobalMetaData::", stringify!($variant), "}}")
}
)*
};
Symbol::intern(string)
}
}
)
}
define_global_metadata_kind!(pub enum GlobalMetaDataKind {
Krate,
CrateDeps,
DylibDependencyFormats,
LangItems,
LangItemsMissing,
NativeLibraries,
SourceMap,
Impls,
ExportedSymbols
});

View file

@ -49,21 +49,21 @@ impl<'hir> Entry<'hir> {
match self.node {
Node::Item(ref item) => {
match item.kind {
ItemKind::Fn(ref fn_decl, _, _, _) => Some(fn_decl),
ItemKind::Fn(ref sig, _, _) => Some(&sig.decl),
_ => None,
}
}
Node::TraitItem(ref item) => {
match item.kind {
TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
TraitItemKind::Method(ref sig, _) => Some(&sig.decl),
_ => None
}
}
Node::ImplItem(ref item) => {
match item.kind {
ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
ImplItemKind::Method(ref sig, _) => Some(&sig.decl),
_ => None,
}
}
@ -85,7 +85,7 @@ impl<'hir> Entry<'hir> {
match item.kind {
ItemKind::Const(_, body) |
ItemKind::Static(.., body) |
ItemKind::Fn(_, _, _, body) => Some(body),
ItemKind::Fn(.., body) => Some(body),
_ => None,
}
}
@ -605,7 +605,7 @@ impl<'hir> Map<'hir> {
Node::TraitItem(ref trait_item) => Some(&trait_item.generics),
Node::Item(ref item) => {
match item.kind {
ItemKind::Fn(_, _, ref generics, _) |
ItemKind::Fn(_, ref generics, _) |
ItemKind::TyAlias(_, ref generics) |
ItemKind::Enum(_, ref generics) |
ItemKind::Struct(_, ref generics) |
@ -702,9 +702,9 @@ impl<'hir> Map<'hir> {
..
}) => true,
Node::Item(&Item {
kind: ItemKind::Fn(_, header, ..),
kind: ItemKind::Fn(ref sig, ..),
..
}) => header.constness == Constness::Const,
}) => sig.header.constness == Constness::Const,
_ => false,
}
}

View file

@ -3,9 +3,7 @@
//! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
pub use self::BlockCheckMode::*;
pub use self::CaptureClause::*;
pub use self::FunctionRetTy::*;
pub use self::Mutability::*;
pub use self::PrimTy::*;
pub use self::UnOp::*;
pub use self::UnsafeSource::*;
@ -23,6 +21,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use syntax::source_map::Spanned;
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy, IsAuto, ImplPolarity};
use syntax::attr::{InlineAttr, OptimizeAttr};
use syntax::symbol::{Symbol, kw};
use syntax::tokenstream::TokenStream;
@ -1053,30 +1052,6 @@ pub enum PatKind {
Slice(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>),
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Mutability {
MutMutable,
MutImmutable,
}
impl Mutability {
/// Returns `MutMutable` only if both `self` and `other` are mutable.
pub fn and(self, other: Self) -> Self {
match self {
MutMutable => other,
MutImmutable => MutImmutable,
}
}
pub fn invert(self) -> Self {
match self {
MutMutable => MutImmutable,
MutImmutable => MutMutable,
}
}
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum BinOpKind {
/// The `+` operator (addition).
@ -1616,6 +1591,11 @@ pub enum ExprKind {
/// and the remaining elements are the rest of the arguments.
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
///
/// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with
/// the `hir_id` of the `MethodCall` node itself.
///
/// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id
MethodCall(P<PathSegment>, Span, HirVec<Expr>),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(HirVec<Expr>),
@ -1647,8 +1627,8 @@ pub enum ExprKind {
/// The `Span` is the argument block `|...|`.
///
/// This may also be a generator literal or an `async block` as indicated by the
/// `Option<GeneratorMovability>`.
Closure(CaptureClause, P<FnDecl>, BodyId, Span, Option<GeneratorMovability>),
/// `Option<Movability>`.
Closure(CaptureBy, P<FnDecl>, BodyId, Span, Option<Movability>),
/// A block (e.g., `'label: { ... }`).
Block(P<Block>, Option<Label>),
@ -1698,6 +1678,10 @@ pub enum ExprKind {
}
/// Represents an optionally `Self`-qualified value/type path or associated extension.
///
/// To resolve the path to a `DefId`, call [`qpath_res`].
///
/// [`qpath_res`]: ../ty/struct.TypeckTables.html#method.qpath_res
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum QPath {
/// Path to a definition, optionally "fully-qualified" with a `Self`
@ -1817,17 +1801,6 @@ pub struct Destination {
pub target_id: Result<HirId, LoopIdError>,
}
/// Whether a generator contains self-references, causing it to be `!Unpin`.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GeneratorMovability {
/// May contain self-references, `!Unpin`.
Static,
/// Must not contain self-references, `Unpin`.
Movable,
}
/// The yield kind that caused an `ExprKind::Yield`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub enum YieldSource {
@ -1846,12 +1819,6 @@ impl fmt::Display for YieldSource {
}
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum CaptureClause {
CaptureByValue,
CaptureByRef,
}
// N.B., if you change this, you'll probably want to change the corresponding
// type structure in middle/ty.rs as well.
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
@ -1860,9 +1827,10 @@ pub struct MutTy {
pub mutbl: Mutability,
}
/// Represents a method's signature in a trait declaration or implementation.
/// Represents a function's signature in a trait declaration,
/// trait implementation, or a free function.
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct MethodSig {
pub struct FnSig {
pub header: FnHeader,
pub decl: P<FnDecl>,
}
@ -1905,7 +1873,7 @@ pub enum TraitItemKind {
/// An associated constant with an optional value (otherwise `impl`s must contain a value).
Const(P<Ty>, Option<BodyId>),
/// A method with an optional body.
Method(MethodSig, TraitMethod),
Method(FnSig, TraitMethod),
/// An associated type with (possibly empty) bounds and optional concrete
/// type.
Type(GenericBounds, Option<P<Ty>>),
@ -1939,7 +1907,7 @@ pub enum ImplItemKind {
/// of the expression.
Const(P<Ty>, BodyId),
/// A method implementation with the given signature and body.
Method(MethodSig, BodyId),
Method(FnSig, BodyId),
/// An associated type.
TyAlias(P<Ty>),
/// An associated `type = impl Trait`.
@ -2154,13 +2122,6 @@ impl ImplicitSelfKind {
}
}
/// Is the trait definition an auto trait?
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum IsAuto {
Yes,
No
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, HashStable,
Ord, RustcEncodable, RustcDecodable, Debug)]
pub enum IsAsync {
@ -2168,19 +2129,6 @@ pub enum IsAsync {
NotAsync,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Unsafety {
Unsafe,
Normal,
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum Constness {
Const,
NotConst,
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum Defaultness {
Default { has_value: bool },
@ -2207,33 +2155,6 @@ impl Defaultness {
}
}
impl fmt::Display for Unsafety {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Unsafety::Normal => "normal",
Unsafety::Unsafe => "unsafe",
})
}
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
/// `impl !Trait for Type`
Negative,
}
impl fmt::Debug for ImplPolarity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
ImplPolarity::Positive => "positive",
ImplPolarity::Negative => "negative",
})
}
}
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum FunctionRetTy {
/// Return type is not specified.
@ -2509,7 +2430,7 @@ pub enum ItemKind {
/// A `const` item.
Const(P<Ty>, BodyId),
/// A function declaration.
Fn(P<FnDecl>, FnHeader, Generics, BodyId),
Fn(FnSig, Generics, BodyId),
/// A module.
Mod(Mod),
/// An external module, e.g. `extern { .. }`.
@ -2574,7 +2495,7 @@ impl ItemKind {
pub fn generics(&self) -> Option<&Generics> {
Some(match *self {
ItemKind::Fn(_, _, ref generics, _) |
ItemKind::Fn(_, ref generics, _) |
ItemKind::TyAlias(_, ref generics) |
ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) |
ItemKind::Enum(_, ref generics) |
@ -2667,7 +2588,7 @@ pub struct Upvar {
pub span: Span
}
pub type CaptureModeMap = NodeMap<CaptureClause>;
pub type CaptureModeMap = NodeMap<CaptureBy>;
// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
// has length > 0 if the trait is found through an chain of imports, starting with the

View file

@ -169,10 +169,11 @@ impl hir::Pat {
self.each_binding(|annotation, _, _, _| {
match annotation {
hir::BindingAnnotation::Ref => match result {
None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable),
None | Some(hir::Mutability::Immutable) =>
result = Some(hir::Mutability::Immutable),
_ => {}
}
hir::BindingAnnotation::RefMut => result = Some(hir::MutMutable),
hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mutable),
_ => {}
}
});

View file

@ -295,8 +295,8 @@ impl<'a> State<'a> {
hir::TyKind::Ptr(ref mt) => {
self.s.word("*");
match mt.mutbl {
hir::MutMutable => self.word_nbsp("mut"),
hir::MutImmutable => self.word_nbsp("const"),
hir::Mutability::Mutable => self.word_nbsp("mut"),
hir::Mutability::Immutable => self.word_nbsp("const"),
}
self.print_type(&mt.ty);
}
@ -390,7 +390,7 @@ impl<'a> State<'a> {
}
hir::ForeignItemKind::Static(ref t, m) => {
self.head(visibility_qualified(&item.vis, "static"));
if m == hir::MutMutable {
if m == hir::Mutability::Mutable {
self.word_space("mut");
}
self.print_ident(item.ident);
@ -506,7 +506,7 @@ impl<'a> State<'a> {
}
hir::ItemKind::Static(ref ty, m, expr) => {
self.head(visibility_qualified(&item.vis, "static"));
if m == hir::MutMutable {
if m == hir::Mutability::Mutable {
self.word_space("mut");
}
self.print_ident(item.ident);
@ -533,10 +533,10 @@ impl<'a> State<'a> {
self.s.word(";");
self.end(); // end the outer cbox
}
hir::ItemKind::Fn(ref decl, header, ref param_names, body) => {
hir::ItemKind::Fn(ref sig, ref param_names, body) => {
self.head("");
self.print_fn(decl,
header,
self.print_fn(&sig.decl,
sig.header,
Some(item.ident.name),
param_names,
&item.vis,
@ -564,7 +564,7 @@ impl<'a> State<'a> {
}
hir::ItemKind::GlobalAsm(ref ga) => {
self.head(visibility_qualified(&item.vis, "global asm"));
self.s.word(ga.asm.as_str().to_string());
self.s.word(ga.asm.to_string());
self.end()
}
hir::ItemKind::TyAlias(ref ty, ref generics) => {
@ -835,7 +835,7 @@ impl<'a> State<'a> {
}
pub fn print_method_sig(&mut self,
ident: ast::Ident,
m: &hir::MethodSig,
m: &hir::FnSig,
generics: &hir::Generics,
vis: &hir::Visibility,
arg_names: &[ast::Ident],
@ -1628,11 +1628,11 @@ impl<'a> State<'a> {
match binding_mode {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
self.print_mutability(hir::MutImmutable);
self.print_mutability(hir::Mutability::Immutable);
}
hir::BindingAnnotation::RefMut => {
self.word_nbsp("ref");
self.print_mutability(hir::MutMutable);
self.print_mutability(hir::Mutability::Mutable);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
@ -1734,9 +1734,7 @@ impl<'a> State<'a> {
_ => false,
};
self.s.word("&");
if mutbl == hir::MutMutable {
self.s.word("mut ");
}
self.s.word(mutbl.prefix_str());
if is_range_inner {
self.popen();
}
@ -1855,7 +1853,7 @@ impl<'a> State<'a> {
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
s.ibox(INDENT_UNIT);
if let Some(arg_name) = arg_names.get(i) {
s.s.word(arg_name.as_str().to_string());
s.s.word(arg_name.to_string());
s.s.word(":");
s.s.space();
} else if let Some(body_id) = body_id {
@ -1911,10 +1909,10 @@ impl<'a> State<'a> {
}
}
pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) {
pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
match capture_clause {
hir::CaptureByValue => self.word_space("move"),
hir::CaptureByRef => {},
hir::CaptureBy::Value => self.word_space("move"),
hir::CaptureBy::Ref => {},
}
}
@ -2063,8 +2061,8 @@ impl<'a> State<'a> {
pub fn print_mutability(&mut self, mutbl: hir::Mutability) {
match mutbl {
hir::MutMutable => self.word_nbsp("mut"),
hir::MutImmutable => {},
hir::Mutability::Mutable => self.word_nbsp("mut"),
hir::Mutability::Immutable => {},
}
}

View file

@ -309,11 +309,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
// position that belongs to it, as opposed to hashing the first
// position past it.
let span = self.data();
if span.hi < span.lo {
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
}
let (file_lo, line_lo, col_lo) = match hcx.source_map()
.byte_pos_to_line_and_col(span.lo) {
Some(pos) => pos,

View file

@ -8,9 +8,9 @@ use std::mem;
use syntax::ast;
use syntax::feature_gate;
use syntax::parse::token;
use syntax::symbol::LocalInternedString;
use syntax::token;
use syntax::tokenstream;
use syntax_pos::symbol::SymbolStr;
use syntax_pos::SourceFile;
use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
@ -18,7 +18,7 @@ use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
use smallvec::SmallVec;
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
impl<'a> HashStable<StableHashingContext<'a>> for SymbolStr {
#[inline]
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let str = self as &str;
@ -26,13 +26,13 @@ impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
}
}
impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
type KeyType = LocalInternedString;
impl<'a> ToStableHashKey<StableHashingContext<'a>> for SymbolStr {
type KeyType = SymbolStr;
#[inline]
fn to_stable_hash_key(&self,
_: &StableHashingContext<'a>)
-> LocalInternedString {
-> SymbolStr {
self.clone()
}
}
@ -45,12 +45,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
}
impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
type KeyType = LocalInternedString;
type KeyType = SymbolStr;
#[inline]
fn to_stable_hash_key(&self,
_: &StableHashingContext<'a>)
-> LocalInternedString {
-> SymbolStr {
self.as_str()
}
}
@ -124,7 +124,6 @@ for ::syntax::attr::StabilityLevel {
impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion });
impl_stable_hash_for!(enum ::syntax::attr::IntType {
SignedInt(int_ty),
UnsignedInt(uint_ty)
@ -136,6 +135,11 @@ impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
Unsuffixed
});
impl_stable_hash_for!(enum ::syntax::ast::LitFloatType {
Suffixed(float_ty),
Unsuffixed
});
impl_stable_hash_for!(struct ::syntax::ast::Lit {
kind,
token,
@ -148,8 +152,7 @@ impl_stable_hash_for!(enum ::syntax::ast::LitKind {
Byte(value),
Char(value),
Int(value, lit_int_type),
Float(value, float_ty),
FloatUnsuffixed(value),
Float(value, lit_float_type),
Bool(value),
Err(value)
});
@ -165,6 +168,10 @@ impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
impl_stable_hash_for!(enum ::syntax::ast::Movability { Static, Movable });
impl_stable_hash_for!(enum ::syntax::ast::CaptureBy { Value, Ref });
impl_stable_hash_for!(enum ::syntax::ast::IsAuto { Yes, No });
impl_stable_hash_for!(enum ::syntax::ast::ImplPolarity { Positive, Negative });
impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
@ -177,7 +184,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
let filtered: SmallVec<[&ast::Attribute; 8]> = self
.iter()
.filter(|attr| {
!attr.is_sugared_doc &&
!attr.is_doc_comment() &&
!attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name))
})
.collect();
@ -207,19 +214,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
// Make sure that these have been filtered out.
debug_assert!(!self.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)));
debug_assert!(!self.is_sugared_doc);
debug_assert!(!self.is_doc_comment());
let ast::Attribute {
ref item,
id: _,
style,
is_sugared_doc: _,
span,
} = *self;
item.hash_stable(hcx, hasher);
style.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
let ast::Attribute { kind, id: _, style, span } = self;
if let ast::AttrKind::Normal(item) = kind {
item.hash_stable(hcx, hasher);
style.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher);
} else {
unreachable!();
}
}
}

View file

@ -897,11 +897,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} else {
r.push(' ');
}
s.push_highlighted(format!(
"&{}{}",
r,
if mutbl == hir::MutMutable { "mut " } else { "" }
));
s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str()));
s.push_normal(ty.to_string());
}
@ -1234,8 +1230,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
// In some (most?) cases cause.body_id points to actual body, but in some cases
// it's a actual definition. According to the comments (e.g. in
// librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
// is relied upon by some other code. This might (or might not) need cleanup.
let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id)
.unwrap_or_else(|| {
self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
});
self.check_and_note_conflicting_crates(diag, terr, span);
self.tcx.note_and_explain_type_err(diag, terr, span);
self.tcx.note_and_explain_type_err(diag, terr, span, body_owner_def_id);
// It reads better to have the error origin as the final
// thing.

View file

@ -31,10 +31,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
if let Some(hir_id) = self.tcx().hir().as_local_hir_id(def_id) {
let fndecl = match self.tcx().hir().get(hir_id) {
Node::Item(&hir::Item {
kind: hir::ItemKind::Fn(ref fndecl, ..),
kind: hir::ItemKind::Fn(ref m, ..),
..
}) => &fndecl,
Node::TraitItem(&hir::TraitItem {
})
| Node::TraitItem(&hir::TraitItem {
kind: hir::TraitItemKind::Method(ref m, ..),
..
})

View file

@ -1,3 +1,3 @@
For info on how the current borrowck works, see the [rustc guide].
[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
[rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html

Some files were not shown because too many files have changed in this diff Show more