Merge remote-tracking branch 'rust-lang/master' into hermit
This commit is contained in:
commit
8871731914
1546 changed files with 11671 additions and 9924 deletions
|
|
@ -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
|
||||
|
|
|
|||
97
Cargo.lock
97
Cargo.lock
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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++
|
||||
|
||||
|
|
|
|||
|
|
@ -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*
|
||||
|
|
|
|||
|
|
@ -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++
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
18
src/ci/docker/dist-x86_64-linux/llvm-project-centos.patch
Normal file
18
src/ci/docker/dist-x86_64-linux/llvm-project-centos.patch
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
82
src/doc/rustdoc/src/how-to-write-documentation.md
Normal file
82
src/doc/rustdoc/src/how-to-write-documentation.md
Normal 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
|
||||
119
src/doc/rustdoc/src/lints.md
Normal file
119
src/doc/rustdoc/src/lints.md
Normal 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 | | /// ```
|
||||
| |___________^
|
||||
```
|
||||
|
|
@ -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 { /* ... */ }
|
||||
```
|
||||
|
|
@ -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.
|
||||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>>>,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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"] }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//! Memory allocation APIs
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "alloc_module", since = "1.28.0")]
|
||||
|
||||
use crate::cmp;
|
||||
|
|
|
|||
|
|
@ -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>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(()))
|
||||
|
|
|
|||
|
|
@ -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()]) })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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`]`>>`:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
//! Integer and floating-point number formatting
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
|
||||
use crate::fmt;
|
||||
use crate::ops::{Div, Rem, Sub};
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@
|
|||
//! }
|
||||
//! ```
|
||||
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::fmt;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
use crate::cmp;
|
||||
|
||||
use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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!` \
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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] {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>`.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// ignore-tidy-filelength
|
||||
// ignore-tidy-undocumented-unsafe
|
||||
|
||||
//! String manipulation.
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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))]
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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() => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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, ..),
|
||||
..
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue