diff --git a/.travis.yml b/.travis.yml index 4eff6337ad8c..36329ab91143 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,6 @@ matrix: SRC=. DEPLOY_ALT=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 - SCCACHE_ERROR_LOG=/tmp/sccache.log MACOSX_DEPLOYMENT_TARGET=10.7 NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 @@ -50,13 +49,12 @@ matrix: RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler" SRC=. RUSTC_RETRY_LINKER_ON_SEGFAULT=1 - SCCACHE_ERROR_LOG=/tmp/sccache.log MACOSX_DEPLOYMENT_TARGET=10.8 MACOSX_STD_DEPLOYMENT_TARGET=10.7 NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode9.2 + osx_image: xcode9.3-moar if: branch = auto - env: > @@ -64,13 +62,12 @@ matrix: RUST_CONFIGURE_ARGS=--build=i686-apple-darwin SRC=. RUSTC_RETRY_LINKER_ON_SEGFAULT=1 - SCCACHE_ERROR_LOG=/tmp/sccache.log MACOSX_DEPLOYMENT_TARGET=10.8 MACOSX_STD_DEPLOYMENT_TARGET=10.7 NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode9.2 + osx_image: xcode9.3-moar if: branch = auto # OSX builders producing releases. These do not run the full test suite and @@ -85,7 +82,6 @@ matrix: SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 - SCCACHE_ERROR_LOG=/tmp/sccache.log MACOSX_DEPLOYMENT_TARGET=10.7 NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 @@ -99,7 +95,6 @@ matrix: SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 - SCCACHE_ERROR_LOG=/tmp/sccache.log MACOSX_DEPLOYMENT_TARGET=10.7 NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 @@ -176,14 +171,11 @@ matrix: if: branch = auto - env: IMAGE=x86_64-gnu-distcheck if: branch = auto - - env: IMAGE=x86_64-gnu-incremental - if: branch = auto - stage: publish toolstate if: branch = master AND type = push before_install: [] install: [] - cache: false sudo: false script: MESSAGE_FILE=$(mktemp -t msg.XXXXXX); @@ -201,7 +193,12 @@ env: - secure: "cFh8thThqEJLC98XKI5pfqflUzOlxsYPRW20AWRaYOOgYHPTiGWypTXiPbGSKaeAXTZoOA+DpQtEmefc0U6lt9dHc7a/MIaK6isFurjlnKYiLOeTruzyu1z7PWCeZ/jKXsU2RK/88DBtlNwfMdaMIeuKj14IVfpepPPL71ETbuk=" before_install: - - zcat $HOME/docker/rust-ci.tar.gz | docker load || true + # We'll use the AWS cli to download/upload cached docker layers, so install + # that here. + - if [ "$TRAVIS_OS_NAME" = linux ]; then + pip install --user awscli; + export PATH=$PATH:$HOME/.local/bin; + fi - mkdir -p $HOME/rustsrc # FIXME(#46924): these two commands are required to enable IPv6, # they shouldn't exist, please revert once more official solutions appeared. @@ -223,7 +220,7 @@ install: travis_retry brew update && travis_retry brew install xz; fi && - travis_retry curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-12-sccache-x86_64-apple-darwin && + travis_retry curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin && chmod +x /usr/local/bin/sccache && travis_retry curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin && chmod +x /usr/local/bin/stamp @@ -264,44 +261,25 @@ after_failure: df -h; du . | sort -nr | head -n100 - # One of these is the linux sccache log, one is the OSX sccache log. Instead - # of worrying about what system we are just cat both. One of these commands - # will fail but that's ok, they'll both get executed. - - cat obj/tmp/sccache.log - - cat /tmp/sccache.log - # Random attempt at debugging currently. Just poking around in here to see if # anything shows up. - ls -lat $HOME/Library/Logs/DiagnosticReports/ - find $HOME/Library/Logs/DiagnosticReports -type f + -name '*.crash' -not -name '*.stage2-*.crash' -not -name 'com.apple.CoreSimulator.CoreSimulatorService-*.crash' -exec printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" {} \; -exec head -750 {} \; - -exec echo travis_fold":"end:crashlog \; + -exec echo travis_fold":"end:crashlog \; || true # attempt to debug anything killed by the oom killer on linux, just to see if # it happened - dmesg | grep -i kill -# Save tagged docker images we created and load them if they're available -# Travis saves caches whether the build failed or not, nuke rustsrc if -# the failure was while updating it (as it may be in a bad state) -# https://github.com/travis-ci/travis-ci/issues/4472 -before_cache: - - docker history -q rust-ci | - grep -v missing | - xargs docker save | - gzip > $HOME/docker/rust-ci.tar.gz - notifications: email: false -cache: - directories: - - $HOME/docker - before_deploy: - mkdir -p deploy/$TRAVIS_COMMIT - > diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index e9b39717c700..d70b2b52aca1 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -11,9 +11,9 @@ A version of this document [can be found online](https://www.rust-lang.org/condu * Please be kind and courteous. There's no need to be mean or rude. * Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. * Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. -* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behaviour. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. +* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. * Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. -* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome. +* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome. ## Moderation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 552961b9b66c..7a62405f0596 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,10 +26,10 @@ As a reminder, all contributors are expected to follow our [Code of Conduct][coc ## Feature Requests [feature-requests]: #feature-requests -To request a change to the way that the Rust language works, please open an -issue in the [RFCs repository](https://github.com/rust-lang/rfcs/issues/new) -rather than this one. New features and other significant language changes -must go through the RFC process. +To request a change to the way the Rust language works, please head over +to the [RFCs repository](https://github.com/rust-lang/rfcs) and view the +[README](https://github.com/rust-lang/rfcs/blob/master/README.md) +for instructions. ## Bug Reports [bug-reports]: #bug-reports @@ -594,7 +594,7 @@ If you're looking for somewhere to start, check out the [E-easy][eeasy] tag. [inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated [eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy [lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc -[rfcbot]: https://github.com/dikaiosune/rust-dashboard/blob/master/RFCBOT.md +[rfcbot]: https://github.com/anp/rfcbot-rs/ ## Out-of-tree Contributions [out-of-tree-contributions]: #out-of-tree-contributions diff --git a/RELEASES.md b/RELEASES.md index 64e2145e0f37..39cef1e2a577 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,115 @@ +Version 1.25.0 (2018-03-29) +========================== + +Language +-------- +- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358] +- [You can now use nested groups of imports.][47948] + e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};` +- [You can now have `|` at the start of a match arm.][47947] e.g. +```rust +enum Foo { A, B, C } + +fn main() { + let x = Foo::A; + match x { + | Foo::A + | Foo::B => println!("AB"), + | Foo::C => println!("C"), + } +} +``` + +Compiler +-------- +- [Upgraded to LLVM 6.][47828] +- [Added `-C lto=val` option.][47521] +- [Added `i586-unknown-linux-musl` target][47282] + +Libraries +--------- +- [Impl Send for `process::Command` on Unix.][47760] +- [Impl PartialEq and Eq for `ParseCharError`.][47790] +- [`UnsafeCell::into_inner` is now safe.][47204] +- [Implement libstd for CloudABI.][47268] +- [`Float::{from_bits, to_bits}` is now available in libcore.][46931] +- [Implement `AsRef` for Component][46985] +- [Implemented `Write` for `Cursor<&mut Vec>`][46830] +- [Moved `Duration` to libcore.][46666] + +Stabilized APIs +--------------- +- [`Location::column`] +- [`ptr::NonNull`] + +The following functions can now be used in a constant expression. +eg. `static MINUTE: Duration = Duration::from_secs(60);` +- [`Duration::new`][47300] +- [`Duration::from_secs`][47300] +- [`Duration::from_millis`][47300] + +Cargo +----- +- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013] +- [`cargo new` now defaults to creating a binary crate, instead of a + library crate.][cargo/5029] + +Misc +---- +- [Rust by example is now shipped with new releases][46196] + +Compatibility Notes +------------------- +- [Deprecated `net::lookup_host`.][47510] +- [`rustdoc` has switched to pulldown as the default markdown renderer.][47398] +- The borrow checker was sometimes incorrectly permitting overlapping borrows + around indexing operations (see [#47349][47349]). This has been fixed (which also + enabled some correct code that used to cause errors (e.g. [#33903][33903] and [#46095][46095]). +- [Removed deprecated unstable attribute `#[simd]`.][47251] + +[33903]: https://github.com/rust-lang/rust/pull/33903 +[47947]: https://github.com/rust-lang/rust/pull/47947 +[47948]: https://github.com/rust-lang/rust/pull/47948 +[47760]: https://github.com/rust-lang/rust/pull/47760 +[47790]: https://github.com/rust-lang/rust/pull/47790 +[47828]: https://github.com/rust-lang/rust/pull/47828 +[47398]: https://github.com/rust-lang/rust/pull/47398 +[47510]: https://github.com/rust-lang/rust/pull/47510 +[47521]: https://github.com/rust-lang/rust/pull/47521 +[47204]: https://github.com/rust-lang/rust/pull/47204 +[47251]: https://github.com/rust-lang/rust/pull/47251 +[47268]: https://github.com/rust-lang/rust/pull/47268 +[47282]: https://github.com/rust-lang/rust/pull/47282 +[47300]: https://github.com/rust-lang/rust/pull/47300 +[47349]: https://github.com/rust-lang/rust/pull/47349 +[46931]: https://github.com/rust-lang/rust/pull/46931 +[46985]: https://github.com/rust-lang/rust/pull/46985 +[47006]: https://github.com/rust-lang/rust/pull/47006 +[46830]: https://github.com/rust-lang/rust/pull/46830 +[46095]: https://github.com/rust-lang/rust/pull/46095 +[46666]: https://github.com/rust-lang/rust/pull/46666 +[46196]: https://github.com/rust-lang/rust/pull/46196 +[cargo/5013]: https://github.com/rust-lang/cargo/pull/5013 +[cargo/5029]: https://github.com/rust-lang/cargo/pull/5029 +[RFC 1358]: https://github.com/rust-lang/rfcs/pull/1358 +[`Location::column`]: https://doc.rust-lang.org/std/panic/struct.Location.html#method.column +[`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html + + +Version 1.24.1 (2018-03-01) +========================== + + - [Do not abort when unwinding through FFI][48251] + - [Emit UTF-16 files for linker arguments on Windows][48318] + - [Make the error index generator work again][48308] + - [Cargo will warn on Windows 7 if an update is needed][cargo/5069]. + +[48251]: https://github.com/rust-lang/rust/issues/48251 +[48308]: https://github.com/rust-lang/rust/issues/48308 +[48318]: https://github.com/rust-lang/rust/issues/48318 +[cargo/5069]: https://github.com/rust-lang/cargo/pull/5069 + + Version 1.24.0 (2018-02-15) ========================== diff --git a/appveyor.yml b/appveyor.yml index 45e1b4b90d6c..09c6fca5d02a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,10 +20,10 @@ environment: SCRIPT: python x.py test - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: python x.py test --exclude src/test/run-pass --exclude src/test/compile-fail + SCRIPT: make appveyor-subset-1 - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: python x.py test src/test/run-pass src/test/compile-fail + SCRIPT: make appveyor-subset-2 # MSVC aux tests - MSYS_BITS: 64 @@ -53,13 +53,13 @@ environment: # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: python x.py test --exclude src/test/run-pass --exclude src/test/compile-fail + SCRIPT: make appveyor-subset-1 MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: python x.py test src/test/run-pass src/test/compile-fail + SCRIPT: make appveyor-subset-2 MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 @@ -152,8 +152,8 @@ install: - set PATH=C:\Python27;%PATH% # Download and install sccache - - appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-12-sccache-x86_64-pc-windows-msvc - - mv 2017-05-12-sccache-x86_64-pc-windows-msvc sccache.exe + - appveyor-retry appveyor DownloadFile https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-pc-windows-msvc + - mv 2018-04-02-sccache-x86_64-pc-windows-msvc sccache.exe - set PATH=%PATH%;%CD% # Download and install ninja @@ -176,9 +176,6 @@ install: - set PATH=%PATH%;%CD%\handle - handle.exe -accepteula -help - # Attempt to debug sccache failures - - set SCCACHE_ERROR_LOG=%CD%/sccache.log - test_script: - if not exist C:\cache\rustsrc\NUL mkdir C:\cache\rustsrc - sh src/ci/init_repo.sh . /c/cache/rustsrc @@ -186,9 +183,6 @@ test_script: - set NO_CCACHE=1 - sh src/ci/run.sh -on_failure: - - cat %CD%\sccache.log || exit 0 - branches: only: - auto diff --git a/config.toml.example b/config.toml.example index b47f9163c0da..9dd3002506e4 100644 --- a/config.toml.example +++ b/config.toml.example @@ -118,6 +118,10 @@ # Indicate whether submodules are managed and updated automatically. #submodules = true +# Update submodules only when the checked out commit in the submodules differs +# from what is committed in the main rustc repo. +#fast-submodules = true + # The path to (or name of) the GDB executable to use. This is only used for # executing the debuginfo test suite. #gdb = "gdb" @@ -182,6 +186,10 @@ # essentially skipping stage0 as the local compiler is recompiling itself again. #local-rebuild = false +# Print out how long each rustbuild step took (mostly intended for CI and +# tracking over time) +#print-step-timings = false + # ============================================================================= # General install configuration options # ============================================================================= @@ -239,11 +247,6 @@ # compiler. #codegen-units = 1 -# Whether to enable ThinLTO (and increase the codegen units to either a default -# or the configured value). On by default. If we want the fastest possible -# compiler, we should disable this. -#thinlto = true - # Whether or not debug assertions are enabled for the compiler and standard # library. Also enables compilation of debug! and trace! logging macros. #debug-assertions = false @@ -268,6 +271,9 @@ # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true +# Build rustc with experimental parallelization +#experimental-parallel-queries = false + # The default linker that will be hard-coded into the generated compiler for # targets that don't specify linker explicitly in their target specifications. # Note that this is not the linker used to link said compiler. diff --git a/src/Cargo.lock b/src/Cargo.lock index 646ddf1a7447..2f77d4125ab0 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1,20 +1,3 @@ -[[package]] -name = "advapi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.4" @@ -28,7 +11,7 @@ name = "alloc" version = "0.0.0" dependencies = [ "core 0.0.0", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "std_unicode 0.0.0", ] @@ -39,7 +22,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.0.0", ] @@ -56,8 +39,11 @@ dependencies = [ [[package]] name = "ansi_term" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ar" @@ -81,7 +67,7 @@ name = "atty" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -93,8 +79,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -103,8 +89,8 @@ name = "backtrace-sys" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -131,16 +117,18 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -158,67 +146,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "build_helper" version = "0.1.0" -dependencies = [ - "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "byteorder" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo" -version = "0.26.0" +version = "0.27.0" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cargotest 0.1.0", - "core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crates-io 0.15.0", + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crates-io 0.16.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -227,37 +212,21 @@ name = "cargo_metadata" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cargo_metadata" -version = "0.4.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cargotest" -version = "0.1.0" -dependencies = [ - "cargo 0.26.0", - "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -266,7 +235,7 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -276,22 +245,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.29.0" +version = "2.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -300,17 +270,18 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.186" +version = "0.0.191" dependencies = [ - "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.186", - "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.191", + "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -319,41 +290,21 @@ version = "0.2.0" [[package]] name = "clippy_lints" -version = "0.0.186" +version = "0.0.191" dependencies = [ "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clippy_lints" -version = "0.0.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -361,7 +312,7 @@ name = "cmake" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -377,14 +328,14 @@ name = "commoncrypto-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "compiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -393,33 +344,35 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "compiletest_rs" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -429,41 +382,39 @@ version = "0.1.0" [[package]] name = "core" version = "0.0.0" +dependencies = [ + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "core-foundation" -version = "0.4.6" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.4.6" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crates-io" -version = "0.15.0" +version = "0.16.0" dependencies = [ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "crossbeam" version = "0.3.2" @@ -474,19 +425,19 @@ name = "crossbeam-deque" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -502,14 +453,13 @@ dependencies = [ [[package]] name = "crypto-hash" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -519,11 +469,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -532,10 +482,10 @@ name = "curl-sys" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -547,12 +497,12 @@ version = "0.1.0" [[package]] name = "derive-new" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -560,6 +510,11 @@ name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "dlmalloc" version = "0.0.0" @@ -568,37 +523,14 @@ dependencies = [ "core 0.0.0", ] -[[package]] -name = "docopt" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "duct" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "either" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -619,45 +551,19 @@ name = "enum_primitive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "error-chain" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -704,7 +610,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -716,12 +622,17 @@ version = "0.1.0" name = "find_impls" version = "0.1.0" +[[package]] +name = "fixedbitset" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "flate2" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -752,7 +663,7 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -772,36 +683,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "git2" -version = "0.6.11" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "git2-curl" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -811,48 +723,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "globset" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "graphviz" version = "0.0.0" -[[package]] -name = "hamcrest" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "handlebars" -version = "0.29.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "hex" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "hex" version = "0.3.1" @@ -860,14 +759,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "home" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -895,18 +792,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ignore" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -925,13 +823,13 @@ version = "0.1.0" name = "installer" version = "0.0.0" dependencies = [ - "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -943,37 +841,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.6.5" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itertools" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "json" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -981,11 +872,11 @@ name = "jsonrpc-core" version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -999,14 +890,14 @@ dependencies = [ [[package]] name = "languageserver-types" -version = "0.30.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1022,7 +913,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazycell" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1034,21 +925,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.36" +version = "0.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libgit2-sys" -version = "0.6.19" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1058,9 +949,9 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1069,8 +960,8 @@ name = "libz-sys" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1108,9 +999,9 @@ name = "lzma-sys" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1121,44 +1012,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdbook" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1171,19 +1054,8 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1191,7 +1063,7 @@ name = "miow" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1199,114 +1071,46 @@ dependencies = [ name = "miri" version = "0.1.0" dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "multiple_bins" version = "0.1.0" -[[package]] -name = "net2" -version = "0.2.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nibble_vec" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "nix" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "num" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-bigint" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-complex" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-integer" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.41" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1314,7 +1118,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1324,14 +1128,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.9.23" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1341,24 +1145,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.24" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "os_pipe" -version = "0.5.1" +name = "ordermap" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "owning_ref" @@ -1388,23 +1187,22 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,14 +1212,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pest" -version = "0.3.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pest_derive" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "petgraph" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pkg-config" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pretty_assertions" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.2.3" @@ -1430,6 +1256,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc_macro" version = "0.0.0" @@ -1444,26 +1278,17 @@ dependencies = [ name = "profiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] -[[package]] -name = "pulldown-cmark" -version = "0.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pulldown-cmark" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1490,14 +1315,22 @@ dependencies = [ ] [[package]] -name = "racer" -version = "2.0.12" +name = "quote" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "racer" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1505,28 +1338,29 @@ dependencies = [ [[package]] name = "radix_trie" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nibble_vec 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.3.20" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1537,9 +1371,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1565,37 +1399,23 @@ version = "0.1.0" [[package]] name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex-syntax" -version = "0.4.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "remote-test-client" @@ -1605,44 +1425,52 @@ version = "0.1.0" name = "remote-test-server" version = "0.1.0" +[[package]] +name = "remove_dir_all" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rls" version = "0.126.0" dependencies = [ - "cargo 0.26.0", - "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy_lints 0.0.186 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo 0.27.0", + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.191", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)", + "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "languageserver-types 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-blacklist 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-blacklist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.3.8", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.4.1", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-analysis" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1650,7 +1478,7 @@ dependencies = [ [[package]] name = "rls-blacklist" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1660,13 +1488,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rls-rustc" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1675,8 +1503,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1684,7 +1512,7 @@ name = "rls-vfs" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1692,8 +1520,8 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1703,11 +1531,11 @@ dependencies = [ "arena 0.0.0", "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", - "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", @@ -1719,11 +1547,12 @@ dependencies = [ "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "29.0.0" +version = "73.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1732,64 +1561,69 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "29.0.0" +version = "73.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "29.0.0" +version = "73.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "29.0.0" +version = "73.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "29.0.0" +version = "73.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "29.0.0" +version = "73.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1839,7 +1673,7 @@ name = "rustc_back" version = "0.0.0" dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax 0.0.0", ] @@ -1881,8 +1715,8 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1893,7 +1727,7 @@ version = "0.0.0" dependencies = [ "ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "arena 0.0.0", - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -1911,6 +1745,7 @@ dependencies = [ "rustc_privacy 0.0.0", "rustc_resolve 0.0.0", "rustc_save_analysis 0.0.0", + "rustc_traits 0.0.0", "rustc_trans_utils 0.0.0", "rustc_typeck 0.0.0", "serialize 0.0.0", @@ -1927,7 +1762,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "serialize 0.0.0", "syntax_pos 0.0.0", - "termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1937,7 +1772,7 @@ version = "0.0.0" dependencies = [ "graphviz 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", @@ -1962,8 +1797,8 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "build_helper 0.1.0", - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", ] @@ -2001,7 +1836,7 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2095,20 +1930,33 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "rustc_traits" +version = "0.0.0" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "graphviz 0.0.0", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc 0.0.0", + "rustc_data_structures 0.0.0", + "syntax 0.0.0", + "syntax_pos 0.0.0", +] + [[package]] name = "rustc_trans" version = "0.0.0" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", "rustc_back 0.0.0", @@ -2123,7 +1971,7 @@ dependencies = [ "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2174,7 +2022,7 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2190,27 +2038,26 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.3.8" +version = "0.4.1" dependencies = [ - "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2223,7 +2070,7 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2232,12 +2079,7 @@ dependencies = [ [[package]] name = "scoped-tls" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2245,30 +2087,13 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "semver" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2278,26 +2103,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.27" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.27" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.19.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2305,37 +2131,27 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.9" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serialize" version = "0.0.0" -[[package]] -name = "shared_child" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "shell-escape" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2350,11 +2166,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2377,7 +2193,7 @@ dependencies = [ "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", @@ -2395,7 +2211,7 @@ dependencies = [ [[package]] name = "strsim" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2410,7 +2226,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.12.13" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2418,6 +2234,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synom" version = "0.11.3" @@ -2444,6 +2270,7 @@ dependencies = [ "rustc_cratesio_shim 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax_pos 0.0.0", ] @@ -2465,6 +2292,7 @@ name = "syntax_pos" version = "0.0.0" dependencies = [ "rustc_data_structures 0.0.0", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2474,7 +2302,7 @@ name = "syntex_errors" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2496,7 +2324,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2511,17 +2339,30 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempdir" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempfile" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2538,11 +2379,20 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "0.3.3" +name = "term" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2550,7 +2400,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2559,7 +2409,7 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.0.0", ] @@ -2571,23 +2421,6 @@ dependencies = [ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.5" @@ -2601,9 +2434,9 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2611,7 +2444,7 @@ name = "time" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2629,7 +2462,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2640,10 +2473,15 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -2694,6 +2532,7 @@ dependencies = [ name = "unstable-book-gen" version = "0.1.0" dependencies = [ + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tidy 0.1.0", ] @@ -2707,7 +2546,7 @@ dependencies = [ [[package]] name = "url" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2720,8 +2559,8 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2733,11 +2572,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "utf8-ranges" version = "1.0.0" @@ -2760,10 +2594,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.0.1" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2797,32 +2632,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wincolor" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "workspace_symbol" version = "0.1.0" -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2839,10 +2664,8 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" -"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" @@ -2852,45 +2675,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" -"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" -"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643" -"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" +"checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3" +"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9" -"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f" -"checksum clippy_lints 0.0.186 (registry+https://github.com/rust-lang/crates.io-index)" = "a3864104a4e6092e644b985dd7543e5f24e99aa7262f5ee400bcb17cfeec1bf5" +"checksum chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5f60682a4c264e7f8d77b82e7788938a76befdf949d4a98026d19099c9d873" +"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5aafb5d4a77c6b5fa384fe93c7a9a3561bd88c4b8b8e45187cf5e779b1badc" -"checksum core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8047f547cd6856d45b1cdd75ef8d2f21f3d0e4bf1dab0a0041b0ae9a5dda9c0e" -"checksum core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "152195421a2e6497a8179195672e9d4ee8e45ed8c465b626f1606d27a08ebcd5" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" +"checksum compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "608d9d3ccc45b63bf337d2ff5e65def5a5a52c187122232509f6b72707f61b1b" +"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" +"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-epoch 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59796cc6cbbdc6bb319161349db0c3250ec73ec7fcb763a51065ec4e2e158552" +"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34903878eec1694faf53cae8473a088df333181de421d4d3d48061d6559fe602" +"checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e" "checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961" -"checksum derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92f8b8e1d6c8a5f5ea0849a0e4c55941576115c62d3fc425e96918bbbeb3d3c2" +"checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a" +"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" -"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c" -"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834" "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3cc21490995c841d68e00276eba02071ebb269ec24011d5728bd00eabd39e31" +"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" +"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -2898,35 +2716,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" -"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" -"checksum git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b4bb7cd2a44e6e5ee3a26ba6a9ca10d4ce2771cdc3839bbc54b47b7d1be84" -"checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" +"checksum futures 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5a3176836efa0b37f0e321b86672dfada1564aeb516fbed67b7c24050a0263" +"checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" +"checksum git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f41c0035c37ec11ed3f1e1946a76070b0c740393687e9a9c7612f6a709036b3" +"checksum git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b502f6b1b467957403d168f0039e0c46fa6a1220efa2adaef25d5b267b5fe024" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "464627f948c3190ae3d04b1bc6d7dca2f785bda0ac01278e6db129ad383dbeb6" -"checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" -"checksum handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04af2006ea09d985fef82b81e0eb25337e51b691c76403332378a53d521edc" -"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" +"checksum globset 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e96ab92362c06811385ae9a34d2698e8a1160745e0c78fbb434a44c8de3fabc" +"checksum handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07af2ff31f66f39a5c8b8b8a5dc02734a453110146763e3a2323f4931a915a76" "checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc" -"checksum home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f25ae61099d8f3fee8b483df0bd4ecccf4b2731897aad40d50eca1b641fe6db" +"checksum home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f94f6fbdc000a6eba0c8cf08632b2091bb59141d36ac321a2a96d6365e5e4dc" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8" -"checksum ignore 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb2f0238094bd1b41800fb6eb9b16fdd5e9832ed6053ed91409f0cd5bf28dcfd" +"checksum ignore 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "245bea0ba52531a3739cb8ba99f8689eda13d7faf8c36b6a73ce4421aab42588" "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053" -"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21" -"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394" -"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" -"checksum jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "565f6106bd87b394398f813bea4e5ecad6d6b0f6aa077592d088f882a506481d" -"checksum json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)" = "39ebf0fac977ee3a4a3242b6446004ff64514889e3e2730bbd4f764a67a2e483" +"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" +"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" +"checksum jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "60af5f849e1981434e4a31d3d782c4774ae9b434ce55b101a96ecfd09147e8be" +"checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum languageserver-types 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1541f9b22687f060511d213036e1f058797c48e3501e177f01cb6e88de802f5b" +"checksum languageserver-types 0.35.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36e264ab825353617bbc80844717555be6e9e1d403474b1d0a3b8e190440b13e" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" -"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" -"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357" +"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" +"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecbd6428006c321c29b6c8a895f0d90152f1cf4fd8faab69fc436a3d9594f63" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -2934,109 +2749,102 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6" "checksum lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b93b78f89e8737dac81837fc8f5521ac162abcba902e1a3db949d55346d1da" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fef236caad7ba3b5b3944df946f19ab3e190bca53c111dd00fe05fa8d879f2fd" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "326d0861da5681a13c19a00952a56c254dd04f00eb944e506fdb36e93ae6f1ca" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d" -"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" -"checksum nibble_vec 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62e678237a4c70c5f2b917cefd7d080dfbf800421f06e8a59d4e28ef5130fd9e" -"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" +"checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca" -"checksum num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc1494b5912f088f260b775799468d9b9209ac60885d8186a547a0476289e23" -"checksum num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "58de7b4bf7cf5dbecb635a5797d489864eadd03b107930cbccf9e0fd7428b47c" -"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" -"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" -"checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe" -"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" +"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "169a4b9160baf9b9b1ab975418c673686638995ba921683a7f1e01470dcb8854" +"checksum openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1636c9f1d78af9cbcc50e523bfff4a30274108aad5e86761afd4d31e4e184fa7" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "14ba54ac7d5a4eabd1d5f2c1fdeb7e7c14debfa669d94b983d01b465e767ba9e" -"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1" +"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9" +"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" -"checksum parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6bf05dc61189828dfd7a59fd6e66d538e88d6b30390da1124a291e09fd3098b3" +"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" +"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" +"checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" +"checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf" +"checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" -"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" +"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" -"checksum racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "034f1c4528581c40a60e96875467c03315868084e08ff4ceb46a00f7be3b16b4" -"checksum radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "211c49b6a9995cac0fd1dd9ca60b42cf3a51e151a12eb954b3a9e75513426ee8" -"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" -"checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d" +"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" +"checksum racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "40d44bc30fc8d403b665286b2c9a83466ddbf69297668fb02b785c3e58eb8e0d" +"checksum radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "03d0d770481e8af620ca61d3d304bf014f965d7f78e923dc58545e6a545070a9" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" -"checksum rls-analysis 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39461c31c9ec26c2f15821d6aaa349216bf71e24e69550d9f8eeded78dc435e1" -"checksum rls-blacklist 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56fb7b8e4850b988fbcf277fbdb1eff36879070d02fc1ca243b559273866973d" +"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" +"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" +"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" +"checksum rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4b9a3a3f2345854e39768e6425d1c893855da217183d1c0b3ff6f1664b6b6d" +"checksum rls-blacklist 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "156cee9c1750b2e97d404dd0506c4780b7a2d615164f49874013807fb3cbfe5e" "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510" -"checksum rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "85cfb9dde19e313da3e47738008f8a472e470cc42d910b71595a9238494701f2" +"checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb" -"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524" -"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad" -"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182" -"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b" -"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d" -"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0" -"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum rustc-ap-rustc_cratesio_shim 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "421262e22426c06306e46057a75048f883dbc43886f78dbe1e750397a9c9b8e6" +"checksum rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8460c1207f9abb48a9720aee8be418bcfac018b6eee7b740b98a410e7799d24a" +"checksum rustc-ap-rustc_errors 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad2077469162e52fcd84543334e18632088b9e342fe54e3b78c37d7077d09714" +"checksum rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69943901ae255dca5f63faeae2ff08b402d34a56d1eb50d34fbff6e83e6ace60" +"checksum rustc-ap-syntax 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a44363359a43df753e26a4d4fef72720af183de635ebae8699686cb5d5de813" +"checksum rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "413f464657e8d5f3864de308dba1867526f21a44809b6f338b34e8c0caf88fb0" +"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" -"checksum schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "acece75e0f987c48863a6c792ec8b7d6c4177d4a027f8ccc72f849794f437016" -"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" -"checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" +"checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4" +"checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" -"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" -"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" -"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" +"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" +"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" -"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" -"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" +"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" +"checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" -"checksum socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf5d5aa364bf61a0d744a293da20381617b6445b89eb524800fab857c5aed2d8" +"checksum socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "71ebbe82fcdd697244ba7fe6e05e63b5c45910c3927e28469a04947494ff48d8" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.12.13 (registry+https://github.com/rust-lang/crates.io-index)" = "517f6da31bc53bf080b9a77b29fbd0ff8da2f5a2ebd24c73c2238274a94ac7cb" +"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" +"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b" "checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac" "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" "checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195" -"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "439d9a7c00f98b1b5ee730039bf5b1f9203d508690e3c76b509e7ad59f8f7c99" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" -"checksum termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9065bced9c3e43453aa3d56f1e98590b8455b341d2fa191a1090c0dd0b242c75" +"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" +"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" @@ -3045,22 +2853,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" +"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" "checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de" +"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a39ee4464208f6430992ff20154216ab2357772ac871d994c51628d60e58b8b0" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" "checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc" "checksum xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df591c3504d014dd791d998123ed00a476c7e26dc6b2e873cb55c6ac9e59fa" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/src/Cargo.toml b/src/Cargo.toml index c03301852cd3..814c054c51e4 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -72,3 +72,4 @@ cargo = { path = "tools/cargo" } # RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section # for crates.io rustfmt-nightly = { path = "tools/rustfmt" } +clippy_lints = { path = "tools/clippy/clippy_lints" } diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 2d4783413178..2f9c4e148a6b 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -42,3 +42,7 @@ serde_json = "1.0.2" toml = "0.4" lazy_static = "0.2" time = "0.1" +petgraph = "0.4.12" + +[dev-dependencies] +pretty_assertions = "0.5" diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 6c3c48aba72f..6701f58ba8e9 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -31,9 +31,11 @@ extern crate bootstrap; use std::env; use std::ffi::OsString; -use std::str::FromStr; +use std::io; use std::path::PathBuf; -use std::process::{Command, ExitStatus}; +use std::process::Command; +use std::str::FromStr; +use std::time::Instant; fn main() { let mut args = env::args_os().skip(1).collect::>(); @@ -90,12 +92,12 @@ fn main() { }; let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set"); let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"); - let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of)); + let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of)); let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc)); let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir)); let mut dylib_path = bootstrap::util::dylib_path(); - dylib_path.insert(0, PathBuf::from(libdir)); + dylib_path.insert(0, PathBuf::from(&libdir)); let mut cmd = Command::new(rustc); cmd.args(&args) @@ -103,11 +105,12 @@ fn main() { .arg(format!("stage{}", stage)) .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + let mut maybe_crate = None; if let Some(target) = target { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option. - cmd.arg("--sysroot").arg(sysroot); + cmd.arg("--sysroot").arg(&sysroot); // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of @@ -134,6 +137,7 @@ fn main() { .find(|a| &*a[0] == "--crate-name") .unwrap(); let crate_name = &*crate_name[1]; + maybe_crate = Some(crate_name); // If we're compiling specifically the `panic_abort` crate then we pass // the `-C panic=abort` option. Note that we do not do this for any @@ -175,9 +179,6 @@ fn main() { if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { cmd.arg("-C").arg(format!("codegen-units={}", s)); } - if env::var("RUSTC_THINLTO").is_ok() { - cmd.arg("-Ccodegen-units=16").arg("-Zthinlto"); - } // Emit save-analysis info. if env::var("RUSTC_SAVE_ANALYSIS") == Ok("api".to_string()) { @@ -280,33 +281,56 @@ fn main() { if verbose > 1 { eprintln!("rustc command: {:?}", cmd); + eprintln!("sysroot: {:?}", sysroot); + eprintln!("libdir: {:?}", libdir); } - // Actually run the compiler! - std::process::exit(if let Some(ref mut on_fail) = on_fail { - match cmd.status() { - Ok(s) if s.success() => 0, - _ => { - println!("\nDid not run successfully:\n{:?}\n-------------", cmd); - exec_cmd(on_fail).expect("could not run the backup command"); - 1 + if let Some(mut on_fail) = on_fail { + let e = match cmd.status() { + Ok(s) if s.success() => std::process::exit(0), + e => e, + }; + println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd); + exec_cmd(&mut on_fail).expect("could not run the backup command"); + std::process::exit(1); + } + + if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() { + if let Some(krate) = maybe_crate { + let start = Instant::now(); + let status = cmd + .status() + .expect(&format!("\n\n failed to run {:?}", cmd)); + let dur = start.elapsed(); + + let is_test = args.iter().any(|a| a == "--test"); + eprintln!("[RUSTC-TIMING] {} test:{} {}.{:03}", + krate.to_string_lossy(), + is_test, + dur.as_secs(), + dur.subsec_nanos() / 1_000_000); + + match status.code() { + Some(i) => std::process::exit(i), + None => { + eprintln!("rustc exited with {}", status); + std::process::exit(0xfe); + } } } - } else { - std::process::exit(match exec_cmd(&mut cmd) { - Ok(s) => s.code().unwrap_or(0xfe), - Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), - }) - }) + } + + let code = exec_cmd(&mut cmd).expect(&format!("\n\n failed to run {:?}", cmd)); + std::process::exit(code); } #[cfg(unix)] -fn exec_cmd(cmd: &mut Command) -> ::std::io::Result { +fn exec_cmd(cmd: &mut Command) -> io::Result { use std::os::unix::process::CommandExt; Err(cmd.exec()) } #[cfg(not(unix))] -fn exec_cmd(cmd: &mut Command) -> ::std::io::Result { - cmd.status() +fn exec_cmd(cmd: &mut Command) -> io::Result { + cmd.status().map(|status| status.code().unwrap()) } diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d8f7cd7ed922..cf54591f25cd 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -314,7 +314,7 @@ class RustBuild(object): self.build_dir = os.path.join(os.getcwd(), "build") self.clean = False self.config_toml = '' - self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + self.rust_root = '' self.use_locked_deps = '' self.use_vendored_sources = '' self.verbose = False @@ -597,10 +597,8 @@ class RustBuild(object): self.cargo())) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] - if self.verbose: + for _ in range(1, self.verbose): args.append("--verbose") - if self.verbose > 1: - args.append("--verbose") if self.use_locked_deps: args.append("--locked") if self.use_vendored_sources: @@ -614,20 +612,55 @@ class RustBuild(object): return config return default_build_triple() + def check_submodule(self, module, slow_submodules): + if not slow_submodules: + checked_out = subprocess.Popen(["git", "rev-parse", "HEAD"], + cwd=os.path.join(self.rust_root, module), + stdout=subprocess.PIPE) + return checked_out + else: + return None + + def update_submodule(self, module, checked_out, recorded_submodules): + module_path = os.path.join(self.rust_root, module) + + if checked_out != None: + default_encoding = sys.getdefaultencoding() + checked_out = checked_out.communicate()[0].decode(default_encoding).strip() + if recorded_submodules[module] == checked_out: + return + + print("Updating submodule", module) + + run(["git", "submodule", "-q", "sync", module], + cwd=self.rust_root, verbose=self.verbose) + run(["git", "submodule", "update", + "--init", "--recursive", module], + cwd=self.rust_root, verbose=self.verbose) + run(["git", "reset", "-q", "--hard"], + cwd=module_path, verbose=self.verbose) + run(["git", "clean", "-qdfx"], + cwd=module_path, verbose=self.verbose) + def update_submodules(self): """Update submodules""" if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \ self.get_toml('submodules') == "false": return - print('Updating submodules') + slow_submodules = self.get_toml('fast-submodules') == "false" + start_time = time() + if slow_submodules: + print('Unconditionally updating all submodules') + else: + print('Updating only changed submodules') default_encoding = sys.getdefaultencoding() - run(["git", "submodule", "-q", "sync"], cwd=self.rust_root, verbose=self.verbose) submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"), "--get-regexp", "path"] ).decode(default_encoding).splitlines()] filtered_submodules = [] + submodules_names = [] for module in submodules: if module.endswith("llvm"): if self.get_toml('llvm-config'): @@ -645,16 +678,19 @@ class RustBuild(object): config = self.get_toml('lld') if config is None or config == 'false': continue - filtered_submodules.append(module) - run(["git", "submodule", "update", - "--init", "--recursive"] + filtered_submodules, - cwd=self.rust_root, verbose=self.verbose) - run(["git", "submodule", "-q", "foreach", "git", - "reset", "-q", "--hard"], - cwd=self.rust_root, verbose=self.verbose) - run(["git", "submodule", "-q", "foreach", "git", - "clean", "-qdfx"], - cwd=self.rust_root, verbose=self.verbose) + check = self.check_submodule(module, slow_submodules) + filtered_submodules.append((module, check)) + submodules_names.append(module) + recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names, + cwd=self.rust_root, stdout=subprocess.PIPE) + recorded = recorded.communicate()[0].decode(default_encoding).strip().splitlines() + recorded_submodules = {} + for data in recorded: + data = data.split() + recorded_submodules[data[3]] = data[2] + for module in filtered_submodules: + self.update_submodule(module[0], module[1], recorded_submodules) + print("Submodules updated in %.2f seconds" % (time() - start_time)) def set_dev_environment(self): """Set download URL for development environment""" @@ -674,14 +710,16 @@ def bootstrap(help_triggered): parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') parser.add_argument('--build') + parser.add_argument('--src') parser.add_argument('--clean', action='store_true') - parser.add_argument('-v', '--verbose', action='store_true') + parser.add_argument('-v', '--verbose', action='count', default=0) args = [a for a in sys.argv if a != '-h' and a != '--help'] args, _ = parser.parse_known_args(args) # Configure initial bootstrap build = RustBuild() + build.rust_root = args.src or os.path.abspath(os.path.join(__file__, '../../..')) build.verbose = args.verbose build.clean = args.clean @@ -691,10 +729,9 @@ def bootstrap(help_triggered): except (OSError, IOError): pass - if '\nverbose = 2' in build.config_toml: - build.verbose = 2 - elif '\nverbose = 1' in build.config_toml: - build.verbose = 1 + match = re.search(r'\nverbose = (\d+)', build.config_toml) + if match is not None: + build.verbose = max(build.verbose, int(match.group(1))) build.use_vendored_sources = '\nvendor = true' in build.config_toml @@ -753,6 +790,7 @@ def bootstrap(help_triggered): env["SRC"] = build.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) env["BOOTSTRAP_PYTHON"] = sys.executable + env["BUILD_DIR"] = build.build_dir run(args, env=env, verbose=build.verbose) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 22656e5a9da4..3f5ec4933d02 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::any::Any; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::env; use std::fmt::Debug; @@ -18,6 +18,8 @@ use std::hash::Hash; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::process::Command; +use std::time::{Instant, Duration}; +use std::collections::HashMap; use compile; use install; @@ -34,12 +36,20 @@ use native; pub use Compiler; +use petgraph::Graph; +use petgraph::graph::NodeIndex; + pub struct Builder<'a> { pub build: &'a Build, pub top_stage: u32, pub kind: Kind, cache: Cache, stack: RefCell>>, + time_spent_on_dependencies: Cell, + pub paths: Vec, + graph_nodes: RefCell>, + graph: RefCell>, + parent: Cell>, } impl<'a> Deref for Builder<'a> { @@ -60,12 +70,6 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// Run this rule for all hosts without cross compiling. const ONLY_HOSTS: bool = false; - /// Run this rule for all targets, but only with the native host. - const ONLY_BUILD_TARGETS: bool = false; - - /// Only run this step with the build triple as host and target. - const ONLY_BUILD: bool = false; - /// Primary function to execute this rule. Can call `builder.ensure(...)` /// with other steps to run those. fn run(self, builder: &Builder) -> Self::Output; @@ -101,8 +105,6 @@ pub struct RunConfig<'a> { struct StepDescription { default: bool, only_hosts: bool, - only_build_targets: bool, - only_build: bool, should_run: fn(ShouldRun) -> ShouldRun, make_run: fn(RunConfig), name: &'static str, @@ -138,8 +140,6 @@ impl StepDescription { StepDescription { default: S::DEFAULT, only_hosts: S::ONLY_HOSTS, - only_build_targets: S::ONLY_BUILD_TARGETS, - only_build: S::ONLY_BUILD, should_run: S::should_run, make_run: S::make_run, name: unsafe { ::std::intrinsics::type_name::() }, @@ -155,18 +155,12 @@ impl StepDescription { self.name, builder.config.exclude); } let build = builder.build; - let hosts = if self.only_build_targets || self.only_build { - build.build_triple() - } else { - &build.hosts - }; + let hosts = &build.hosts; // Determine the targets participating in this rule. let targets = if self.only_hosts { - if build.config.run_host_only { - &[] - } else if self.only_build { - build.build_triple() + if !build.config.run_host_only { + return; // don't run anything } else { &build.hosts } @@ -324,19 +318,24 @@ impl<'a> Builder<'a> { test::UiFullDeps, test::RunPassFullDeps, test::RunFailFullDeps, test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty, test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty, - test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake, - test::Crate, test::CrateLibrustc, test::Rustdoc, test::Linkcheck, test::Cargotest, - test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck, + test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, + test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck, + test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck, + test::RunMakeFullDeps, test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample, test::TheBook, test::UnstableBook, - test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme), + test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme, + // Run run-make last, since these won't pass without make on Windows + test::RunMake), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, - doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, - doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook), - Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, - dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo, - dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign), + doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc, + doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample, + doc::CargoBook), + Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc, + dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, + dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended, + dist::HashSign), Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls, install::Rustfmt, install::Analysis, install::Src, install::Rustc), } @@ -359,6 +358,11 @@ impl<'a> Builder<'a> { kind, cache: Cache::new(), stack: RefCell::new(Vec::new()), + time_spent_on_dependencies: Cell::new(Duration::new(0, 0)), + paths: vec![], + graph_nodes: RefCell::new(HashMap::new()), + graph: RefCell::new(Graph::new()), + parent: Cell::new(None), }; let builder = &builder; @@ -375,7 +379,7 @@ impl<'a> Builder<'a> { Some(help) } - pub fn run(build: &Build) { + pub fn new(build: &Build) -> Builder { let (kind, paths) = match build.config.cmd { Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), Subcommand::Check { ref paths } => (Kind::Check, &paths[..]), @@ -387,32 +391,40 @@ impl<'a> Builder<'a> { Subcommand::Clean { .. } => panic!(), }; - if let Some(path) = paths.get(0) { - if path == Path::new("nonexistent/path/to/trigger/cargo/metadata") { - return; - } - } - let builder = Builder { build, top_stage: build.config.stage.unwrap_or(2), kind, cache: Cache::new(), stack: RefCell::new(Vec::new()), + time_spent_on_dependencies: Cell::new(Duration::new(0, 0)), + paths: paths.to_owned(), + graph_nodes: RefCell::new(HashMap::new()), + graph: RefCell::new(Graph::new()), + parent: Cell::new(None), }; if kind == Kind::Dist { - assert!(!build.config.test_miri, "Do not distribute with miri enabled.\n\ + assert!(!builder.config.test_miri, "Do not distribute with miri enabled.\n\ The distributed libraries would include all MIR (increasing binary size). The distributed MIR would include validation statements."); } - StepDescription::run(&Builder::get_step_descriptions(builder.kind), &builder, paths); + builder + } + + pub fn execute_cli(&self) -> Graph { + self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths); + self.graph.borrow().clone() } pub fn default_doc(&self, paths: Option<&[PathBuf]>) { let paths = paths.unwrap_or(&[]); - StepDescription::run(&Builder::get_step_descriptions(Kind::Doc), self, paths); + self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths); + } + + fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) { + StepDescription::run(v, self, paths); } /// Obtain a compiler at a given stage and for a given host. Explicitly does @@ -562,7 +574,9 @@ impl<'a> Builder<'a> { let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default(); if stage != 0 { let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default(); - extra_args.push_str(" "); + if !extra_args.is_empty() { + extra_args.push_str(" "); + } extra_args.push_str(&s); } @@ -678,6 +692,10 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_ON_FAIL", on_fail); } + if self.config.print_step_timings { + cargo.env("RUSTC_PRINT_STEP_TIMINGS", "1"); + } + cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); // Throughout the build Cargo can execute a number of build scripts @@ -775,9 +793,11 @@ impl<'a> Builder<'a> { // be resolved because MinGW has the import library. The downside is we // don't get newer functions from Windows, but we don't use any of them // anyway. - cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1"); + if mode != Mode::Tool { + cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1"); + } - if self.is_very_verbose() { + for _ in 1..self.verbosity { cargo.arg("-v"); } @@ -792,17 +812,6 @@ impl<'a> Builder<'a> { if cmd != "bench" { cargo.arg("--release"); } - - if self.config.rust_codegen_units.is_none() && - self.build.is_rust_llvm(compiler.host) && - self.config.rust_thinlto { - cargo.env("RUSTC_THINLTO", "1"); - } else if self.config.rust_codegen_units.is_none() { - // Generally, if ThinLTO has been disabled for some reason, we - // want to set the codegen units to 1. However, we shouldn't do - // this if the option was specifically set by the user. - cargo.env("RUSTC_CODEGEN_UNITS", "1"); - } } if self.config.locked_deps { @@ -838,12 +847,56 @@ impl<'a> Builder<'a> { if let Some(out) = self.cache.get(&step) { self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step)); + { + let mut graph = self.graph.borrow_mut(); + let parent = self.parent.get(); + let us = *self.graph_nodes.borrow_mut() + .entry(format!("{:?}", step)) + .or_insert_with(|| graph.add_node(format!("{:?}", step))); + if let Some(parent) = parent { + graph.add_edge(parent, us, false); + } + } + return out; } self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step)); stack.push(Box::new(step.clone())); } - let out = step.clone().run(self); + + let prev_parent = self.parent.get(); + + { + let mut graph = self.graph.borrow_mut(); + let parent = self.parent.get(); + let us = *self.graph_nodes.borrow_mut() + .entry(format!("{:?}", step)) + .or_insert_with(|| graph.add_node(format!("{:?}", step))); + self.parent.set(Some(us)); + if let Some(parent) = parent { + graph.add_edge(parent, us, true); + } + } + + let (out, dur) = { + let start = Instant::now(); + let zero = Duration::new(0, 0); + let parent = self.time_spent_on_dependencies.replace(zero); + let out = step.clone().run(self); + let dur = start.elapsed(); + let deps = self.time_spent_on_dependencies.replace(parent + dur); + (out, dur - deps) + }; + + self.parent.set(prev_parent); + + if self.build.config.print_step_timings && dur > Duration::from_millis(100) { + println!("[TIMING] {:?} -- {}.{:03}", + step, + dur.as_secs(), + dur.subsec_nanos() / 1_000_000); + } + { let mut stack = self.stack.borrow_mut(); let cur_step = stack.pop().expect("step stack empty"); @@ -854,3 +907,483 @@ impl<'a> Builder<'a> { out } } + +#[cfg(test)] +mod __test { + use config::Config; + use std::thread; + use super::*; + + fn configure(host: &[&str], target: &[&str]) -> Config { + let mut config = Config::default_opts(); + // don't save toolstates + config.save_toolstates = None; + config.run_host_only = true; + config.dry_run = true; + // try to avoid spurious failures in dist where we create/delete each others file + let dir = config.out.join("tmp-rustbuild-tests") + .join(&thread::current().name().unwrap_or("unknown").replace(":", "-")); + t!(fs::create_dir_all(&dir)); + config.out = dir; + config.build = INTERNER.intern_str("A"); + config.hosts = vec![config.build].clone().into_iter() + .chain(host.iter().map(|s| INTERNER.intern_str(s))).collect::>(); + config.targets = config.hosts.clone().into_iter() + .chain(target.iter().map(|s| INTERNER.intern_str(s))).collect::>(); + config + } + + fn first(v: Vec<(A, B)>) -> Vec { + v.into_iter().map(|(a, _)| a).collect::>() + } + + #[test] + fn dist_baseline() { + let build = Build::new(configure(&[], &[])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + + assert_eq!(first(builder.cache.all::()), &[ + dist::Docs { stage: 2, host: a }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Mingw { host: a }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Rustc { compiler: Compiler { host: a, stage: 2 } }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + } + + #[test] + fn dist_with_targets() { + let build = Build::new(configure(&[], &["B"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!(first(builder.cache.all::()), &[ + dist::Docs { stage: 2, host: a }, + dist::Docs { stage: 2, host: b }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Rustc { compiler: Compiler { host: a, stage: 2 } }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + } + + #[test] + fn dist_with_hosts() { + let build = Build::new(configure(&["B"], &[])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!(first(builder.cache.all::()), &[ + dist::Docs { stage: 2, host: a }, + dist::Docs { stage: 2, host: b }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Rustc { compiler: Compiler { host: a, stage: 2 } }, + dist::Rustc { compiler: Compiler { host: b, stage: 2 } }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + } + + #[test] + fn dist_with_targets_and_hosts() { + let build = Build::new(configure(&["B"], &["C"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert_eq!(first(builder.cache.all::()), &[ + dist::Docs { stage: 2, host: a }, + dist::Docs { stage: 2, host: b }, + dist::Docs { stage: 2, host: c }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Rustc { compiler: Compiler { host: a, stage: 2 } }, + dist::Rustc { compiler: Compiler { host: b, stage: 2 } }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + } + + #[test] + fn dist_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.run_host_only = false; // as-if --target=C was passed + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert_eq!(first(builder.cache.all::()), &[ + dist::Docs { stage: 2, host: a }, + dist::Docs { stage: 2, host: b }, + dist::Docs { stage: 2, host: c }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + dist::Mingw { host: c }, + ]); + assert_eq!(first(builder.cache.all::()), &[]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[]); + } + + #[test] + fn dist_with_same_targets_and_hosts() { + let build = Build::new(configure(&["B"], &["B"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + + assert_eq!(first(builder.cache.all::()), &[ + dist::Docs { stage: 2, host: a }, + dist::Docs { stage: 2, host: b }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Mingw { host: a }, + dist::Mingw { host: b }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Rustc { compiler: Compiler { host: a, stage: 2 } }, + dist::Rustc { compiler: Compiler { host: b, stage: 2 } }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + dist::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[dist::Src]); + assert_eq!(first(builder.cache.all::()), &[ + compile::Std { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Std { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + compile::Assemble { + target_compiler: Compiler { host: a, stage: 0 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 2 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 2 }, + }, + ]); + } + + #[test] + fn build_default() { + let build = Build::new(configure(&["B"], &["C"])); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert!(!builder.cache.all::().is_empty()); + assert!(!builder.cache.all::().is_empty()); + assert_eq!(first(builder.cache.all::()), &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + ]); + + assert_eq!(first(builder.cache.all::()), &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ]); + } + + #[test] + fn build_with_target_flag() { + let mut config = configure(&["B"], &["C"]); + config.run_host_only = false; + let build = Build::new(config); + let mut builder = Builder::new(&build); + builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); + + let a = INTERNER.intern_str("A"); + let b = INTERNER.intern_str("B"); + let c = INTERNER.intern_str("C"); + + assert!(!builder.cache.all::().is_empty()); + assert_eq!(first(builder.cache.all::()), &[ + compile::Assemble { + target_compiler: Compiler { host: a, stage: 0 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 1 }, + }, + compile::Assemble { + target_compiler: Compiler { host: a, stage: 2 }, + }, + compile::Assemble { + target_compiler: Compiler { host: b, stage: 2 }, + }, + ]); + assert_eq!(first(builder.cache.all::()), &[ + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 0 }, + target: b, + }, + compile::Rustc { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + ]); + + assert_eq!(first(builder.cache.all::()), &[ + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: a, + }, + compile::Test { + compiler: Compiler { host: a, stage: 0 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 1 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: b, + }, + compile::Test { + compiler: Compiler { host: a, stage: 2 }, + target: c, + }, + compile::Test { + compiler: Compiler { host: b, stage: 2 }, + target: c, + }, + ]); + } +} diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index c27493158826..d81c6bc28e52 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -21,6 +21,7 @@ use std::mem; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::sync::Mutex; +use std::cmp::{PartialOrd, Ord, Ordering}; use builder::Step; @@ -154,6 +155,19 @@ impl AsRef for Interned { } } +impl PartialOrd> for Interned { + fn partial_cmp(&self, other: &Self) -> Option { + let l = INTERNER.strs.lock().unwrap(); + l.get(*self).partial_cmp(l.get(*other)) + } +} + +impl Ord for Interned { + fn cmp(&self, other: &Self) -> Ordering { + let l = INTERNER.strs.lock().unwrap(); + l.get(*self).cmp(l.get(*other)) + } +} struct TyIntern { items: Vec, @@ -264,4 +278,16 @@ impl Cache { .expect("invalid type mapped"); stepcache.get(step).cloned() } + + #[cfg(test)] + pub fn all(&mut self) -> Vec<(S, S::Output)> { + let cache = self.0.get_mut(); + let type_id = TypeId::of::(); + let mut v = cache.remove(&type_id) + .map(|b| b.downcast::>().expect("correct type")) + .map(|m| m.into_iter().collect::>()) + .unwrap_or_default(); + v.sort_by_key(|&(a, _)| a); + v + } } diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 9e1b1f7db2f9..8f393a4c5737 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -77,7 +77,7 @@ pub fn find(build: &mut Build) { .collect::>(); for target in targets.into_iter() { let mut cfg = cc::Build::new(); - cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false) + cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false) .target(&target).host(&build.build); if target.contains("msvc") { cfg.static_crt(true); @@ -109,7 +109,7 @@ pub fn find(build: &mut Build) { let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::>(); for host in hosts.into_iter() { let mut cfg = cc::Build::new(); - cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true) + cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true) .target(&host).host(&build.build); let config = build.config.target_config.get(&host); if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 72841cb0616c..3453933a9652 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -24,7 +24,7 @@ use Build; use config::Config; // The version number -pub const CFG_RELEASE_NUM: &str = "1.26.0"; +pub const CFG_RELEASE_NUM: &str = "1.27.0"; pub struct GitInfo { inner: Option, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 33bcfaa80ca3..a39fad67ebea 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -40,19 +40,20 @@ impl Step for Std { let target = self.target; let compiler = builder.compiler(0, build.build); - let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Checking std artifacts ({} -> {})", &compiler.host, target); - let out_dir = build.stage_out(compiler, Mode::Libstd); build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "check"); std_cargo(builder, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); + println!("Checking std artifacts ({} -> {})", &compiler.host, target); run_cargo(build, &mut cargo, &libstd_stamp(build, compiler, target), true); + let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); + add_to_sysroot(&build, &libdir, &libstd_stamp(build, compiler, target)); } } @@ -86,21 +87,22 @@ impl Step for Rustc { let compiler = builder.compiler(0, build.build); let target = self.target; - let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); - let stage_out = builder.stage_out(compiler, Mode::Librustc); build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target)); build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check"); rustc_cargo(build, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); + println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); run_cargo(build, &mut cargo, &librustc_stamp(build, compiler, target), true); + let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(&libdir, &librustc_stamp(build, compiler, target)); + add_to_sysroot(&build, &libdir, &librustc_stamp(build, compiler, target)); } } @@ -128,18 +130,20 @@ impl Step for Test { let target = self.target; let compiler = builder.compiler(0, build.build); - let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Checking test artifacts ({} -> {})", &compiler.host, target); let out_dir = build.stage_out(compiler, Mode::Libtest); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check"); test_cargo(build, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); + println!("Checking test artifacts ({} -> {})", &compiler.host, target); run_cargo(build, &mut cargo, &libtest_stamp(build, compiler, target), true); + let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(&libdir, &libtest_stamp(build, compiler, target)); + add_to_sysroot(&build, &libdir, &libtest_stamp(build, compiler, target)); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 86263c8fa073..9cc18464fea0 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -16,6 +16,7 @@ //! compiler. This module is also responsible for assembling the sysroot as it //! goes along from the output of the previous stage. +use std::borrow::Cow; use std::env; use std::fs::{self, File}; use std::io::BufReader; @@ -29,7 +30,7 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; -use util::{exe, libdir, is_dylib, copy, read_stamp_file, CiEnv}; +use util::{exe, libdir, is_dylib, CiEnv}; use {Build, Compiler, Mode}; use native; use tool; @@ -37,7 +38,7 @@ use tool; use cache::{INTERNER, Interned}; use builder::{Step, RunConfig, ShouldRun, Builder}; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { pub target: Interned, pub compiler: Compiler, @@ -76,7 +77,7 @@ impl Step for Std { compiler: from, target, }); - println!("Uplifting stage1 std ({} -> {})", from.host, target); + builder.info(&format!("Uplifting stage1 std ({} -> {})", from.host, target)); // Even if we're not building std this stage, the new sysroot must // still contain the musl startup objects. @@ -93,19 +94,19 @@ impl Step for Std { return; } - let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Building stage{} std artifacts ({} -> {})", compiler.stage, - &compiler.host, target); - if target.contains("musl") { let libdir = builder.sysroot_libdir(compiler, target); copy_musl_third_party_objects(build, target, &libdir); } - let out_dir = build.stage_out(compiler, Mode::Libstd); + let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build"); std_cargo(builder, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); + build.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage, + &compiler.host, target)); run_cargo(build, &mut cargo, &libstd_stamp(build, compiler, target), @@ -129,7 +130,7 @@ fn copy_musl_third_party_objects(build: &Build, target: Interned, into: &Path) { for &obj in &["crt1.o", "crti.o", "crtn.o"] { - copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); + build.copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); } } @@ -139,48 +140,58 @@ pub fn std_cargo(build: &Builder, compiler: &Compiler, target: Interned, cargo: &mut Command) { - let mut features = build.std_features(); - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } - // When doing a local rebuild we tell cargo that we're stage1 rather than - // stage0. This works fine if the local rust and being-built rust have the - // same view of what the default allocator is, but fails otherwise. Since - // we don't have a way to express an allocator preference yet, work - // around the issue in the case of a local rebuild with jemalloc disabled. - if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { - features.push_str(" force_alloc_system"); - } + if build.no_std(target) == Some(true) { + // for no-std targets we only compile a few no_std crates + cargo.arg("--features").arg("c mem") + .args(&["-p", "alloc"]) + .args(&["-p", "compiler_builtins"]) + .args(&["-p", "std_unicode"]) + .arg("--manifest-path") + .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); + } else { + let mut features = build.std_features(); - if compiler.stage != 0 && build.config.sanitizers { - // This variable is used by the sanitizer runtime crates, e.g. - // rustc_lsan, to build the sanitizer runtime from C code - // When this variable is missing, those crates won't compile the C code, - // so we don't set this variable during stage0 where llvm-config is - // missing - // We also only build the runtimes when --enable-sanitizers (or its - // config.toml equivalent) is used - let llvm_config = build.ensure(native::Llvm { - target: build.config.build, - emscripten: false, - }); - cargo.env("LLVM_CONFIG", llvm_config); - } - - cargo.arg("--features").arg(features) - .arg("--manifest-path") - .arg(build.src.join("src/libstd/Cargo.toml")); - - if let Some(target) = build.config.target_config.get(&target) { - if let Some(ref jemalloc) = target.jemalloc { - cargo.env("JEMALLOC_OVERRIDE", jemalloc); + // When doing a local rebuild we tell cargo that we're stage1 rather than + // stage0. This works fine if the local rust and being-built rust have the + // same view of what the default allocator is, but fails otherwise. Since + // we don't have a way to express an allocator preference yet, work + // around the issue in the case of a local rebuild with jemalloc disabled. + if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { + features.push_str(" force_alloc_system"); } - } - if target.contains("musl") { - if let Some(p) = build.musl_root(target) { - cargo.env("MUSL_ROOT", p); + + if compiler.stage != 0 && build.config.sanitizers { + // This variable is used by the sanitizer runtime crates, e.g. + // rustc_lsan, to build the sanitizer runtime from C code + // When this variable is missing, those crates won't compile the C code, + // so we don't set this variable during stage0 where llvm-config is + // missing + // We also only build the runtimes when --enable-sanitizers (or its + // config.toml equivalent) is used + let llvm_config = build.ensure(native::Llvm { + target: build.config.build, + emscripten: false, + }); + cargo.env("LLVM_CONFIG", llvm_config); + } + + cargo.arg("--features").arg(features) + .arg("--manifest-path") + .arg(build.src.join("src/libstd/Cargo.toml")); + + if let Some(target) = build.config.target_config.get(&target) { + if let Some(ref jemalloc) = target.jemalloc { + cargo.env("JEMALLOC_OVERRIDE", jemalloc); + } + } + if target.contains("musl") { + if let Some(p) = build.musl_root(target) { + cargo.env("MUSL_ROOT", p); + } } } } @@ -212,20 +223,20 @@ impl Step for StdLink { let compiler = self.compiler; let target_compiler = self.target_compiler; let target = self.target; - println!("Copying stage{} std from stage{} ({} -> {} / {})", + build.info(&format!("Copying stage{} std from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, - target); + target)); let libdir = builder.sysroot_libdir(target_compiler, target); - add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); + add_to_sysroot(&build, &libdir, &libstd_stamp(build, compiler, target)); if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { // The sanitizers are only built in stage1 or above, so the dylibs will // be missing in stage0 and causes panic. See the `std()` function above // for reason why the sanitizers are not built in stage0. - copy_apple_sanitizer_dylibs(&build.native_dir(target), "osx", &libdir); + copy_apple_sanitizer_dylibs(&build, &build.native_dir(target), "osx", &libdir); } builder.ensure(tool::CleanTools { @@ -236,7 +247,7 @@ impl Step for StdLink { } } -fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { +fn copy_apple_sanitizer_dylibs(build: &Build, native_dir: &Path, platform: &str, into: &Path) { for &sanitizer in &["asan", "tsan"] { let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform); let mut src_path = native_dir.join(sanitizer); @@ -244,7 +255,7 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { src_path.push("lib"); src_path.push("darwin"); src_path.push(&filename); - copy(&src_path, &into.join(filename)); + build.copy(&src_path, &into.join(filename)); } } @@ -300,7 +311,7 @@ impl Step for StartupObjects { .arg(src_file)); } - copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); + build.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); } for obj in ["crt2.o", "dllcrt2.o"].iter() { @@ -308,15 +319,15 @@ impl Step for StartupObjects { build.cc(target), target, obj); - copy(&src, &sysroot_dir.join(obj)); + build.copy(&src, &sysroot_dir.join(obj)); } } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Test { - pub compiler: Compiler, pub target: Interned, + pub compiler: Compiler, } impl Step for Test { @@ -351,7 +362,7 @@ impl Step for Test { compiler: builder.compiler(1, build.build), target, }); - println!("Uplifting stage1 test ({} -> {})", &build.build, target); + build.info(&format!("Uplifting stage1 test ({} -> {})", &build.build, target)); builder.ensure(TestLink { compiler: builder.compiler(1, build.build), target_compiler: compiler, @@ -360,13 +371,14 @@ impl Step for Test { return; } - let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Building stage{} test artifacts ({} -> {})", compiler.stage, - &compiler.host, target); - let out_dir = build.stage_out(compiler, Mode::Libtest); + let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build"); test_cargo(build, &compiler, target, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); + build.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage, + &compiler.host, target)); run_cargo(build, &mut cargo, &libtest_stamp(build, compiler, target), @@ -412,13 +424,13 @@ impl Step for TestLink { let compiler = self.compiler; let target_compiler = self.target_compiler; let target = self.target; - println!("Copying stage{} test from stage{} ({} -> {} / {})", + build.info(&format!("Copying stage{} test from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, - target); - add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), + target)); + add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target), &libtest_stamp(build, compiler, target)); builder.ensure(tool::CleanTools { compiler: target_compiler, @@ -428,10 +440,10 @@ impl Step for TestLink { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustc { - pub compiler: Compiler, pub target: Interned, + pub compiler: Compiler, } impl Step for Rustc { @@ -467,7 +479,7 @@ impl Step for Rustc { compiler: builder.compiler(1, build.build), target, }); - println!("Uplifting stage1 rustc ({} -> {})", &build.build, target); + build.info(&format!("Uplifting stage1 rustc ({} -> {})", &build.build, target)); builder.ensure(RustcLink { compiler: builder.compiler(1, build.build), target_compiler: compiler, @@ -481,17 +493,16 @@ impl Step for Rustc { compiler: builder.compiler(self.compiler.stage, build.build), target: build.build, }); - - let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Building stage{} compiler artifacts ({} -> {})", - compiler.stage, &compiler.host, target); - - let stage_out = builder.stage_out(compiler, Mode::Librustc); - build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target)); - build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target)); + let cargo_out = builder.cargo_out(compiler, Mode::Librustc, target); + build.clear_if_dirty(&cargo_out, &libstd_stamp(build, compiler, target)); + build.clear_if_dirty(&cargo_out, &libtest_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build"); rustc_cargo(build, &mut cargo); + + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); + build.info(&format!("Building stage{} compiler artifacts ({} -> {})", + compiler.stage, &compiler.host, target)); run_cargo(build, &mut cargo, &librustc_stamp(build, compiler, target), @@ -568,13 +579,13 @@ impl Step for RustcLink { let compiler = self.compiler; let target_compiler = self.target_compiler; let target = self.target; - println!("Copying stage{} rustc from stage{} ({} -> {} / {})", + build.info(&format!("Copying stage{} rustc from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, - target); - add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), + target)); + add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target), &librustc_stamp(build, compiler, target)); builder.ensure(tool::CleanTools { compiler: target_compiler, @@ -634,8 +645,6 @@ impl Step for CodegenBackend { .arg(build.src.join("src/librustc_trans/Cargo.toml")); rustc_cargo_env(build, &mut cargo); - let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage)); - match &*self.backend { "llvm" | "emscripten" => { // Build LLVM for our target. This will implicitly build the @@ -649,8 +658,8 @@ impl Step for CodegenBackend { features.push_str(" emscripten"); } - println!("Building stage{} codegen artifacts ({} -> {}, {})", - compiler.stage, &compiler.host, target, self.backend); + build.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", + compiler.stage, &compiler.host, target, self.backend)); // Pass down configuration from the LLVM build into the build of // librustc_llvm and librustc_trans. @@ -685,10 +694,15 @@ impl Step for CodegenBackend { let tmp_stamp = build.cargo_out(compiler, Mode::Librustc, target) .join(".tmp.stamp"); + + let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage)); let files = run_cargo(build, cargo.arg("--features").arg(features), &tmp_stamp, false); + if builder.config.dry_run { + return; + } let mut files = files.into_iter() .filter(|f| { let filename = f.file_name().unwrap().to_str().unwrap(); @@ -732,6 +746,10 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder, let dst = builder.sysroot_codegen_backends(target_compiler); t!(fs::create_dir_all(&dst)); + if builder.config.dry_run { + return; + } + for backend in builder.config.rust_codegen_backends.iter() { let stamp = codegen_backend_stamp(build, compiler, target, *backend); let mut dylib = String::new(); @@ -747,7 +765,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder, backend, &filename[dot..]) }; - copy(&file, &dst.join(target_filename)); + build.copy(&file, &dst.join(target_filename)); } } @@ -763,7 +781,7 @@ fn copy_lld_to_sysroot(builder: &Builder, t!(fs::create_dir_all(&dst)); let exe = exe("lld", &target); - copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe)); + builder.copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe)); } /// Cargo's output path for the standard library in a given stage, compiled @@ -835,7 +853,7 @@ impl Step for Sysroot { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)] pub struct Assemble { /// The compiler which we will produce in this step. Assemble itself will /// take care of ensuring that the necessary prerequisites to do so exist, @@ -915,7 +933,7 @@ impl Step for Assemble { } } - let lld_install = if build.config.lld_enabled && target_compiler.stage > 0 { + let lld_install = if build.config.lld_enabled { Some(builder.ensure(native::Lld { target: target_compiler.host, })) @@ -925,17 +943,17 @@ impl Step for Assemble { let stage = target_compiler.stage; let host = target_compiler.host; - println!("Assembling stage{} compiler ({})", stage, host); + build.info(&format!("Assembling stage{} compiler ({})", stage, host)); // Link in all dylibs to the libdir let sysroot = builder.sysroot(target_compiler); let sysroot_libdir = sysroot.join(libdir(&*host)); t!(fs::create_dir_all(&sysroot_libdir)); let src_libdir = builder.sysroot_libdir(build_compiler, host); - for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { + for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); if is_dylib(&filename) { - copy(&f.path(), &sysroot_libdir.join(&filename)); + builder.copy(&f.path(), &sysroot_libdir.join(&filename)); } } @@ -953,7 +971,7 @@ impl Step for Assemble { t!(fs::create_dir_all(&bindir)); let compiler = builder.rustc(target_compiler); let _ = fs::remove_file(&compiler); - copy(&rustc, &compiler); + builder.copy(&rustc, &compiler); target_compiler } @@ -963,10 +981,10 @@ impl Step for Assemble { /// /// For a particular stage this will link the file listed in `stamp` into the /// `sysroot_dst` provided. -pub fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { +pub fn add_to_sysroot(build: &Build, sysroot_dst: &Path, stamp: &Path) { t!(fs::create_dir_all(&sysroot_dst)); - for path in read_stamp_file(stamp) { - copy(&path, &sysroot_dst.join(path.file_name().unwrap())); + for path in build.read_stamp_file(stamp) { + build.copy(&path, &sysroot_dst.join(path.file_name().unwrap())); } } @@ -996,24 +1014,10 @@ fn stderr_isatty() -> bool { pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: bool) -> Vec { - // Instruct Cargo to give us json messages on stdout, critically leaving - // stderr as piped so we can get those pretty colors. - cargo.arg("--message-format").arg("json") - .stdout(Stdio::piped()); - - if stderr_isatty() && build.ci_env == CiEnv::None { - // since we pass message-format=json to cargo, we need to tell the rustc - // wrapper to give us colored output if necessary. This is because we - // only want Cargo's JSON output, not rustcs. - cargo.env("RUSTC_COLOR", "1"); + if build.config.dry_run { + return Vec::new(); } - build.verbose(&format!("running: {:?}", cargo)); - let mut child = match cargo.spawn() { - Ok(child) => child, - Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e), - }; - // `target_root_dir` looks like $dir/$target/release let target_root_dir = stamp.parent().unwrap(); // `target_deps_dir` looks like $dir/$target/release/deps @@ -1028,46 +1032,33 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let stdout = BufReader::new(child.stdout.take().unwrap()); - for line in stdout.lines() { - let line = t!(line); - let json: serde_json::Value = if line.starts_with("{") { - t!(serde_json::from_str(&line)) - } else { - // If this was informational, just print it out and continue - println!("{}", line); - continue + let ok = stream_cargo(build, cargo, &mut |msg| { + let filenames = match msg { + CargoMessage::CompilerArtifact { filenames, .. } => filenames, + _ => return, }; - if json["reason"].as_str() != Some("compiler-artifact") { - if build.config.rustc_error_format.as_ref().map_or(false, |e| e == "json") { - // most likely not a cargo message, so let's send it out as well - println!("{}", line); - } - continue - } - for filename in json["filenames"].as_array().unwrap() { - let filename = filename.as_str().unwrap(); + for filename in filenames { // Skip files like executables if !filename.ends_with(".rlib") && !filename.ends_with(".lib") && !is_dylib(&filename) && !(is_check && filename.ends_with(".rmeta")) { - continue + return; } - let filename = Path::new(filename); + let filename = Path::new(&*filename); // If this was an output file in the "host dir" we don't actually // worry about it, it's not relevant for us. if filename.starts_with(&host_root_dir) { - continue; + return; } // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. if filename.starts_with(&target_deps_dir) { deps.push(filename.to_path_buf()); - continue; + return; } // Otherwise this was a "top level artifact" which right now doesn't @@ -1088,15 +1079,10 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo toplevel.push((file_stem, extension, expected_len)); } - } + }); - // Make sure Cargo actually succeeded after we read all of its stdout. - let status = t!(child.wait()); - if !status.success() { - panic!("command did not execute successfully: {:?}\n\ - expected success, got: {}", - cargo, - status); + if !ok { + panic!("cargo must succeed"); } // Ok now we need to actually find all the files listed in `toplevel`. We've @@ -1155,7 +1141,7 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo let max = max.unwrap(); let max_path = max_path.unwrap(); if stamp_contents == new_contents && max <= stamp_mtime { - build.verbose(&format!("not updating {:?}; contents equal and {} <= {}", + build.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); return deps } @@ -1167,3 +1153,66 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo t!(t!(File::create(stamp)).write_all(&new_contents)); deps } + +pub fn stream_cargo( + build: &Build, + cargo: &mut Command, + cb: &mut FnMut(CargoMessage), +) -> bool { + if build.config.dry_run { + return true; + } + // Instruct Cargo to give us json messages on stdout, critically leaving + // stderr as piped so we can get those pretty colors. + cargo.arg("--message-format").arg("json") + .stdout(Stdio::piped()); + + if stderr_isatty() && build.ci_env == CiEnv::None { + // since we pass message-format=json to cargo, we need to tell the rustc + // wrapper to give us colored output if necessary. This is because we + // only want Cargo's JSON output, not rustcs. + cargo.env("RUSTC_COLOR", "1"); + } + + build.verbose(&format!("running: {:?}", cargo)); + let mut child = match cargo.spawn() { + Ok(child) => child, + Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e), + }; + + // Spawn Cargo slurping up its JSON output. We'll start building up the + // `deps` array of all files it generated along with a `toplevel` array of + // files we need to probe for later. + let stdout = BufReader::new(child.stdout.take().unwrap()); + for line in stdout.lines() { + let line = t!(line); + match serde_json::from_str::(&line) { + Ok(msg) => cb(msg), + // If this was informational, just print it out and continue + Err(_) => println!("{}", line) + } + } + + // Make sure Cargo actually succeeded after we read all of its stdout. + let status = t!(child.wait()); + if !status.success() { + eprintln!("command did not execute successfully: {:?}\n\ + expected success, got: {}", + cargo, + status); + } + status.success() +} + +#[derive(Deserialize)] +#[serde(tag = "reason", rename_all = "kebab-case")] +pub enum CargoMessage<'a> { + CompilerArtifact { + package_id: Cow<'a, str>, + features: Vec>, + filenames: Vec>, + }, + BuildScriptExecuted { + package_id: Cow<'a, str>, + } +} diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index f15d4d358583..863abd14935a 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -15,7 +15,7 @@ use std::collections::{HashMap, HashSet}; use std::env; -use std::fs::File; +use std::fs::{self, File}; use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process; @@ -45,6 +45,7 @@ pub struct Config { pub ninja: bool, pub verbose: usize, pub submodules: bool, + pub fast_submodules: bool, pub compiler_docs: bool, pub docs: bool, pub locked_deps: bool, @@ -68,6 +69,7 @@ pub struct Config { pub jobs: Option, pub cmd: Subcommand, pub incremental: bool, + pub dry_run: bool, // llvm codegen options pub llvm_enabled: bool, @@ -86,7 +88,6 @@ pub struct Config { // rust codegen options pub rust_optimize: bool, pub rust_codegen_units: Option, - pub rust_thinlto: bool, pub rust_debug_assertions: bool, pub rust_debuginfo: bool, pub rust_debuginfo_lines: bool, @@ -122,11 +123,13 @@ pub struct Config { pub quiet_tests: bool, pub test_miri: bool, pub save_toolstates: Option, + pub print_step_timings: bool, // Fallback musl-root for all targets pub musl_root: Option, pub prefix: Option, pub sysconfdir: Option, + pub datadir: Option, pub docdir: Option, pub bindir: Option, pub libdir: Option, @@ -141,6 +144,7 @@ pub struct Config { // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, + pub out: PathBuf, } /// Per-target configuration stored in the global configuration structure. @@ -157,6 +161,7 @@ pub struct Target { pub crt_static: Option, pub musl_root: Option, pub qemu_rootfs: Option, + pub no_std: bool, } /// Structure of the `config.toml` file that configuration is read from. @@ -190,6 +195,7 @@ struct Build { compiler_docs: Option, docs: Option, submodules: Option, + fast_submodules: Option, gdb: Option, locked_deps: Option, vendor: Option, @@ -204,6 +210,7 @@ struct Build { openssl_static: Option, configure_args: Option>, local_rebuild: Option, + print_step_timings: Option, } /// TOML representation of various global install decisions. @@ -212,13 +219,13 @@ struct Build { struct Install { prefix: Option, sysconfdir: Option, + datadir: Option, docdir: Option, bindir: Option, libdir: Option, mandir: Option, // standard paths, currently unused - datadir: Option, infodir: Option, localstatedir: Option, } @@ -269,7 +276,6 @@ impl Default for StringOrBool { struct Rust { optimize: Option, codegen_units: Option, - thinlto: Option, debug_assertions: Option, debuginfo: Option, debuginfo_lines: Option, @@ -314,11 +320,8 @@ struct TomlTarget { } impl Config { - pub fn parse(args: &[String]) -> Config { - let flags = Flags::parse(&args); - let file = flags.config.clone(); + pub fn default_opts() -> Config { let mut config = Config::default(); - config.exclude = flags.exclude; config.llvm_enabled = true; config.llvm_optimize = true; config.llvm_version_check = true; @@ -327,6 +330,7 @@ impl Config { config.rust_optimize = true; config.rust_optimize_tests = true; config.submodules = true; + config.fast_submodules = true; config.docs = true; config.rust_rpath = true; config.channel = "dev".to_string(); @@ -337,17 +341,40 @@ impl Config { config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")]; config.rust_codegen_backends_dir = "codegen-backends".to_owned(); + // set by bootstrap.py + config.src = env::var_os("SRC").map(PathBuf::from).expect("'SRC' to be set"); + config.build = INTERNER.intern_str(&env::var("BUILD").expect("'BUILD' to be set")); + config.out = env::var_os("BUILD_DIR").map(PathBuf::from).expect("'BUILD_DIR' set"); + + let stage0_root = config.out.join(&config.build).join("stage0/bin"); + config.initial_rustc = stage0_root.join(exe("rustc", &config.build)); + config.initial_cargo = stage0_root.join(exe("cargo", &config.build)); + + config + } + + pub fn parse(args: &[String]) -> Config { + let flags = Flags::parse(&args); + let file = flags.config.clone(); + let mut config = Config::default_opts(); + config.exclude = flags.exclude; config.rustc_error_format = flags.rustc_error_format; config.on_fail = flags.on_fail; config.stage = flags.stage; - config.src = flags.src; config.jobs = flags.jobs; config.cmd = flags.cmd; config.incremental = flags.incremental; + config.dry_run = flags.dry_run; config.keep_stage = flags.keep_stage; + if config.dry_run { + let dir = config.out.join("tmp-dry-run"); + t!(fs::create_dir_all(&dir)); + config.out = dir; + } + // If --target was specified but --host wasn't specified, don't run any host-only tests. - config.run_host_only = flags.host.is_empty() && !flags.target.is_empty(); + config.run_host_only = !(flags.host.is_empty() && !flags.target.is_empty()); let toml = file.map(|file| { let mut f = t!(File::open(&file)); @@ -364,12 +391,7 @@ impl Config { }).unwrap_or_else(|| TomlConfig::default()); let build = toml.build.clone().unwrap_or(Build::default()); - set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x))); - set(&mut config.build, flags.build); - if config.build.is_empty() { - // set by bootstrap.py - config.build = INTERNER.intern_str(&env::var("BUILD").unwrap()); - } + // set by bootstrap.py config.hosts.push(config.build.clone()); for host in build.host.iter() { let host = INTERNER.intern_str(host); @@ -403,6 +425,7 @@ impl Config { set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); set(&mut config.submodules, build.submodules); + set(&mut config.fast_submodules, build.fast_submodules); set(&mut config.locked_deps, build.locked_deps); set(&mut config.vendor, build.vendor); set(&mut config.full_bootstrap, build.full_bootstrap); @@ -414,11 +437,13 @@ impl Config { set(&mut config.openssl_static, build.openssl_static); set(&mut config.configure_args, build.configure_args); set(&mut config.local_rebuild, build.local_rebuild); + set(&mut config.print_step_timings, build.print_step_timings); config.verbose = cmp::max(config.verbose, flags.verbose); if let Some(ref install) = toml.install { config.prefix = install.prefix.clone().map(PathBuf::from); config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from); + config.datadir = install.datadir.clone().map(PathBuf::from); config.docdir = install.docdir.clone().map(PathBuf::from); config.bindir = install.bindir.clone().map(PathBuf::from); config.libdir = install.libdir.clone().map(PathBuf::from); @@ -427,7 +452,6 @@ impl Config { // Store off these values as options because if they're not provided // we'll infer default values for them later - let mut thinlto = None; let mut llvm_assertions = None; let mut debuginfo_lines = None; let mut debuginfo_only_std = None; @@ -471,7 +495,6 @@ impl Config { optimize = rust.optimize; ignore_git = rust.ignore_git; debug_jemalloc = rust.debug_jemalloc; - thinlto = rust.thinlto; set(&mut config.rust_optimize_tests, rust.optimize_tests); set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests); set(&mut config.codegen_tests, rust.codegen_tests); @@ -509,13 +532,13 @@ impl Config { let mut target = Target::default(); if let Some(ref s) = cfg.llvm_config { - target.llvm_config = Some(env::current_dir().unwrap().join(s)); + target.llvm_config = Some(config.src.join(s)); } if let Some(ref s) = cfg.jemalloc { - target.jemalloc = Some(env::current_dir().unwrap().join(s)); + target.jemalloc = Some(config.src.join(s)); } if let Some(ref s) = cfg.android_ndk { - target.ndk = Some(env::current_dir().unwrap().join(s)); + target.ndk = Some(config.src.join(s)); } target.cc = cfg.cc.clone().map(PathBuf::from); target.cxx = cfg.cxx.clone().map(PathBuf::from); @@ -536,22 +559,12 @@ impl Config { set(&mut config.rust_dist_src, t.src_tarball); } - let cwd = t!(env::current_dir()); - let out = cwd.join("build"); - - let stage0_root = out.join(&config.build).join("stage0/bin"); - config.initial_rustc = match build.rustc { - Some(s) => PathBuf::from(s), - None => stage0_root.join(exe("rustc", &config.build)), - }; - config.initial_cargo = match build.cargo { - Some(s) => PathBuf::from(s), - None => stage0_root.join(exe("cargo", &config.build)), - }; - // Now that we've reached the end of our configuration, infer the // default values for all options that we haven't otherwise stored yet. + set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); + set(&mut config.initial_rustc, build.cargo.map(PathBuf::from)); + let default = false; config.llvm_assertions = llvm_assertions.unwrap_or(default); @@ -559,7 +572,6 @@ impl Config { "stable" | "beta" | "nightly" => true, _ => false, }; - config.rust_thinlto = thinlto.unwrap_or(true); config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default); config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index e9b4a233d0af..a5c373d5d5e7 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -44,6 +44,7 @@ o("debug", "rust.debug", "debug mode; disables optimization unless `--enable-opt o("docs", "build.docs", "build standard library documentation") o("compiler-docs", "build.compiler-docs", "build compiler documentation") o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") +o("experimental-parallel-queries", "rust.experimental-parallel-queries", "build rustc with experimental parallelization") o("test-miri", "rust.test-miri", "run miri's test suite") o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata") o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests") @@ -71,7 +72,6 @@ o("full-tools", None, "enable all tools") # Optimization and debugging options. These may be overridden by the release # channel, etc. o("optimize", "rust.optimize", "build optimized rust code") -o("thinlto", "rust.thinlto", "build Rust with ThinLTO enabled") o("optimize-llvm", "llvm.optimize", "build optimized LLVM") o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index aa0a7c52246b..e1f5d34bf672 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -20,7 +20,7 @@ use std::env; use std::fs::{self, File}; -use std::io::{self, Read, Write}; +use std::io::{Read, Write}; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; @@ -28,7 +28,7 @@ use build_helper::output; use {Build, Compiler, Mode}; use channel; -use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file, exe}; +use util::{libdir, is_dylib, exe}; use builder::{Builder, RunConfig, ShouldRun, Step}; use compile; use native; @@ -61,7 +61,7 @@ fn rust_installer(builder: &Builder) -> Command { builder.tool_cmd(Tool::RustInstaller) } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Docs { pub stage: u32, pub host: Interned, @@ -70,7 +70,6 @@ pub struct Docs { impl Step for Docs { type Output = PathBuf; const DEFAULT: bool = true; - const ONLY_BUILD_TARGETS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("src/doc") @@ -90,9 +89,9 @@ impl Step for Docs { let name = pkgname(build, "rust-docs"); - println!("Dist docs ({})", host); + build.info(&format!("Dist docs ({})", host)); if !build.config.docs { - println!("\tskipping - docs disabled"); + build.info(&format!("\tskipping - docs disabled")); return distdir(build).join(format!("{}-{}.tar.gz", name, host)); } @@ -103,8 +102,8 @@ impl Step for Docs { let dst = image.join("share/doc/rust/html"); t!(fs::create_dir_all(&dst)); - let src = build.out.join(host).join("doc"); - cp_r(&src, &dst); + let src = build.doc_out(host); + build.cp_r(&src, &dst); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -119,16 +118,71 @@ impl Step for Docs { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--bulk-dirs=share/doc/rust/html"); build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + build.remove_dir(&image); - // As part of this step, *also* copy the docs directory to a directory which - // buildbot typically uploads. - if host == build.build { - let dst = distdir(build).join("doc").join(build.rust_package_vers()); - t!(fs::create_dir_all(&dst)); - cp_r(&src, &dst); + distdir(build).join(format!("{}-{}.tar.gz", name, host)) + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustcDocs { + pub stage: u32, + pub host: Interned, +} + +impl Step for RustcDocs { + type Output = PathBuf; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/librustc") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(RustcDocs { + stage: run.builder.top_stage, + host: run.target, + }); + } + + /// Builds the `rustc-docs` installer component. + fn run(self, builder: &Builder) -> PathBuf { + let build = builder.build; + let host = self.host; + + let name = pkgname(build, "rustc-docs"); + + build.info(&format!("Dist compiler docs ({})", host)); + if !build.config.compiler_docs { + build.info(&format!("\tskipping - compiler docs disabled")); + return distdir(build).join(format!("{}-{}.tar.gz", name, host)); } + builder.default_doc(None); + + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); + + let dst = image.join("share/doc/rust/html"); + t!(fs::create_dir_all(&dst)); + let src = build.compiler_doc_out(host); + build.cp_r(&src, &dst); + + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rustc-Documentation") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rustc-documentation-is-installed.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rustc-docs") + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--bulk-dirs=share/doc/rust/html"); + build.run(&mut cmd); + build.remove_dir(&image); + distdir(build).join(format!("{}-{}.tar.gz", name, host)) } } @@ -204,11 +258,14 @@ fn make_win_dist( "libbcrypt.a", "libcomctl32.a", "libcomdlg32.a", + "libcredui.a", "libcrypt32.a", + "libdbghelp.a", "libgdi32.a", "libimagehlp.a", "libiphlpapi.a", "libkernel32.a", + "libmsimg32.a", "libmsvcrt.a", "libodbc32.a", "libole32.a", @@ -216,8 +273,10 @@ fn make_win_dist( "libopengl32.a", "libpsapi.a", "librpcrt4.a", + "libsecur32.a", "libsetupapi.a", "libshell32.a", + "libsynchronization.a", "libuser32.a", "libuserenv.a", "libuuid.a", @@ -226,8 +285,6 @@ fn make_win_dist( "libwinspool.a", "libws2_32.a", "libwsock32.a", - "libdbghelp.a", - "libmsimg32.a", ]; //Find mingw artifacts we want to bundle @@ -235,43 +292,36 @@ fn make_win_dist( let rustc_dlls = find_files(&rustc_dlls, &bin_path); let target_libs = find_files(&target_libs, &lib_path); - fn copy_to_folder(src: &Path, dest_folder: &Path) { - let file_name = src.file_name().unwrap(); - let dest = dest_folder.join(file_name); - copy(src, &dest); - } - - //Copy runtime dlls next to rustc.exe + // Copy runtime dlls next to rustc.exe let dist_bin_dir = rust_root.join("bin/"); fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed"); for src in rustc_dlls { - copy_to_folder(&src, &dist_bin_dir); + build.copy_to_folder(&src, &dist_bin_dir); } //Copy platform tools to platform-specific bin directory let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin"); fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); for src in target_tools { - copy_to_folder(&src, &target_bin_dir); + build.copy_to_folder(&src, &target_bin_dir); } //Copy platform libs to platform-specific lib directory let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib"); fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); for src in target_libs { - copy_to_folder(&src, &target_lib_dir); + build.copy_to_folder(&src, &target_lib_dir); } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Mingw { - host: Interned, + pub host: Interned, } impl Step for Mingw { type Output = Option; const DEFAULT: bool = true; - const ONLY_BUILD_TARGETS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.never() @@ -293,7 +343,7 @@ impl Step for Mingw { return None; } - println!("Dist mingw ({})", host); + build.info(&format!("Dist mingw ({})", host)); let name = pkgname(build, "rust-mingw"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -322,7 +372,7 @@ impl Step for Mingw { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { pub compiler: Compiler, } @@ -331,7 +381,6 @@ impl Step for Rustc { type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - const ONLY_BUILD_TARGETS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("src/librustc") @@ -349,7 +398,7 @@ impl Step for Rustc { let compiler = self.compiler; let host = self.compiler.host; - println!("Dist rustc stage{} ({})", compiler.stage, compiler.host); + build.info(&format!("Dist rustc stage{} ({})", compiler.stage, compiler.host)); let name = pkgname(build, "rustc"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -362,7 +411,7 @@ impl Step for Rustc { // Prepare the overlay which is part of the tarball but won't actually be // installed let cp = |file: &str| { - install(&build.src.join(file), &overlay, 0o644); + build.install(&build.src.join(file), &overlay, 0o644); }; cp("COPYRIGHT"); cp("LICENSE-APACHE"); @@ -370,9 +419,9 @@ impl Step for Rustc { cp("README.md"); // tiny morsel of metadata is used by rust-packaging let version = build.rust_version(); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + build.create(&overlay.join("version"), &version); if let Some(sha) = build.rust_sha() { - t!(t!(File::create(overlay.join("git-commit-hash"))).write_all(sha.as_bytes())); + build.create(&overlay.join("git-commit-hash"), &sha); } // On MinGW we've got a few runtime DLL dependencies that we need to @@ -390,7 +439,7 @@ impl Step for Rustc { let dst = image.join("share/doc"); t!(fs::create_dir_all(&dst)); - cp_r(&build.src.join("src/etc/third-party"), &dst); + build.cp_r(&build.src.join("src/etc/third-party"), &dst); } // Finally, wrap everything up in a nice tarball! @@ -407,8 +456,8 @@ impl Step for Rustc { .arg("--component-name=rustc") .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); - t!(fs::remove_dir_all(&overlay)); + build.remove_dir(&image); + build.remove_dir(&overlay); return distdir(build).join(format!("{}-{}.tar.gz", name, host)); @@ -420,17 +469,17 @@ impl Step for Rustc { // Copy rustc/rustdoc binaries t!(fs::create_dir_all(image.join("bin"))); - cp_r(&src.join("bin"), &image.join("bin")); + build.cp_r(&src.join("bin"), &image.join("bin")); - install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755); + build.install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755); // Copy runtime DLLs needed by the compiler if libdir != "bin" { - for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) { + for entry in build.read_dir(&src.join(libdir)) { let name = entry.file_name(); if let Some(s) = name.to_str() { if is_dylib(s) { - install(&entry.path(), &image.join(libdir), 0o644); + build.install(&entry.path(), &image.join(libdir), 0o644); } } } @@ -441,7 +490,7 @@ impl Step for Rustc { let backends_rel = backends_src.strip_prefix(&src).unwrap(); let backends_dst = image.join(&backends_rel); t!(fs::create_dir_all(&backends_dst)); - cp_r(&backends_src, &backends_dst); + build.cp_r(&backends_src, &backends_dst); // Copy over lld if it's there if builder.config.lld_enabled { @@ -456,7 +505,7 @@ impl Step for Rustc { .join("bin") .join(&exe); t!(fs::create_dir_all(&dst.parent().unwrap())); - copy(&src, &dst); + build.copy(&src, &dst); } // Man pages @@ -466,13 +515,12 @@ impl Step for Rustc { let month_year = t!(time::strftime("%B %Y", &time::now())); // don't use our `bootstrap::util::{copy, cp_r}`, because those try // to hardlink, and we don't want to edit the source templates - for entry_result in t!(fs::read_dir(man_src)) { - let file_entry = t!(entry_result); + for file_entry in build.read_dir(&man_src) { let page_src = file_entry.path(); let page_dst = man_dst.join(file_entry.file_name()); t!(fs::copy(&page_src, &page_dst)); // template in month/year and version number - replace_in_file(&page_dst, + build.replace_in_file(&page_dst, &[("", &month_year), ("", channel::CFG_RELEASE_NUM)]); } @@ -485,7 +533,7 @@ impl Step for Rustc { // Misc license info let cp = |file: &str| { - install(&build.src.join(file), &image.join("share/doc/rust"), 0o644); + build.install(&build.src.join(file), &image.join("share/doc/rust"), 0o644); }; cp("COPYRIGHT"); cp("LICENSE-APACHE"); @@ -523,11 +571,11 @@ impl Step for DebuggerScripts { let dst = sysroot.join("lib/rustlib/etc"); t!(fs::create_dir_all(&dst)); let cp_debugger_script = |file: &str| { - install(&build.src.join("src/etc/").join(file), &dst, 0o644); + build.install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; if host.contains("windows-msvc") { // windbg debugger scripts - install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), + build.install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), 0o755); cp_debugger_script("natvis/intrinsic.natvis"); @@ -537,14 +585,14 @@ impl Step for DebuggerScripts { cp_debugger_script("debugger_pretty_printers_common.py"); // gdb debugger scripts - install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), + build.install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755); cp_debugger_script("gdb_load_rust_pretty_printers.py"); cp_debugger_script("gdb_rust_pretty_printing.py"); // lldb debugger scripts - install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), + build.install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755); cp_debugger_script("lldb_rust_formatters.py"); @@ -552,7 +600,7 @@ impl Step for DebuggerScripts { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, pub target: Interned, @@ -561,7 +609,6 @@ pub struct Std { impl Step for Std { type Output = PathBuf; const DEFAULT: bool = true; - const ONLY_BUILD_TARGETS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("src/libstd") @@ -569,7 +616,7 @@ impl Step for Std { fn make_run(run: RunConfig) { run.builder.ensure(Std { - compiler: run.builder.compiler(run.builder.top_stage, run.host), + compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build), target: run.target, }); } @@ -580,12 +627,12 @@ impl Step for Std { let target = self.target; let name = pkgname(build, "rust-std"); - println!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target); + build.info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target)); // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. if compiler.host != build.build { - println!("\tskipping, not a build host"); + build.info(&format!("\tskipping, not a build host")); return distdir(build).join(format!("{}-{}.tar.gz", name, target)); } @@ -595,7 +642,12 @@ impl Step for Std { if build.hosts.iter().any(|t| t == target) { builder.ensure(compile::Rustc { compiler, target }); } else { - builder.ensure(compile::Test { compiler, target }); + if build.no_std(target) == Some(true) { + // the `test` doesn't compile for no-std targets + builder.ensure(compile::Std { compiler, target }); + } else { + builder.ensure(compile::Test { compiler, target }); + } } let image = tmpdir(build).join(format!("{}-{}-image", name, target)); @@ -605,7 +657,7 @@ impl Step for Std { t!(fs::create_dir_all(&dst)); let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); src.pop(); // Remove the trailing /lib folder from the sysroot_libdir - cp_filtered(&src, &dst, &|path| { + build.cp_filtered(&src, &dst, &|path| { let name = path.file_name().and_then(|s| s.to_str()); name != Some(build.config.rust_codegen_backends_dir.as_str()) && name != Some("bin") @@ -624,7 +676,7 @@ impl Step for Std { .arg(format!("--component-name=rust-std-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + build.remove_dir(&image); distdir(build).join(format!("{}-{}.tar.gz", name, target)) } } @@ -638,7 +690,6 @@ pub struct Analysis { impl Step for Analysis { type Output = PathBuf; const DEFAULT: bool = true; - const ONLY_BUILD_TARGETS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { let builder = run.builder; @@ -647,7 +698,7 @@ impl Step for Analysis { fn make_run(run: RunConfig) { run.builder.ensure(Analysis { - compiler: run.builder.compiler(run.builder.top_stage, run.host), + compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build), target: run.target, }); } @@ -658,11 +709,11 @@ impl Step for Analysis { let compiler = self.compiler; let target = self.target; assert!(build.config.extended); - println!("Dist analysis"); + build.info(&format!("Dist analysis")); let name = pkgname(build, "rust-analysis"); if &compiler.host != build.build { - println!("\tskipping, not a build host"); + build.info(&format!("\tskipping, not a build host")); return distdir(build).join(format!("{}-{}.tar.gz", name, target)); } @@ -684,8 +735,8 @@ impl Step for Analysis { let image_src = src.join("save-analysis"); let dst = image.join("lib/rustlib").join(target).join("analysis"); t!(fs::create_dir_all(&dst)); - println!("image_src: {:?}, dst: {:?}", image_src, dst); - cp_r(&image_src, &dst); + build.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst)); + build.cp_r(&image_src, &dst); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -699,7 +750,7 @@ impl Step for Analysis { .arg(format!("--component-name=rust-analysis-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + build.remove_dir(&image); distdir(build).join(format!("{}-{}.tar.gz", name, target)) } } @@ -743,11 +794,11 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di for item in src_dirs { let dst = &dst_dir.join(item); t!(fs::create_dir_all(dst)); - cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path)); + build.cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path)); } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Src; impl Step for Src { @@ -755,8 +806,6 @@ impl Step for Src { type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - const ONLY_BUILD_TARGETS: bool = true; - const ONLY_BUILD: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("src") @@ -769,7 +818,7 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; - println!("Dist src"); + build.info(&format!("Dist src")); let name = pkgname(build, "rust-src"); let image = tmpdir(build).join(format!("{}-image", name)); @@ -819,7 +868,7 @@ impl Step for Src { copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src); for file in src_files.iter() { - copy(&build.src.join(file), &dst_src.join(file)); + build.copy(&build.src.join(file), &dst_src.join(file)); } // Create source tarball in rust-installer format @@ -836,14 +885,14 @@ impl Step for Src { .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + build.remove_dir(&image); distdir(build).join(&format!("{}.tar.gz", name)) } } const CARGO_VENDOR_VERSION: &str = "0.1.4"; -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct PlainSourceTarball; impl Step for PlainSourceTarball { @@ -851,8 +900,6 @@ impl Step for PlainSourceTarball { type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - const ONLY_BUILD_TARGETS: bool = true; - const ONLY_BUILD: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { let builder = run.builder; @@ -866,7 +913,7 @@ impl Step for PlainSourceTarball { /// Creates the plain source tarball fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; - println!("Create plain source tarball"); + build.info(&format!("Create plain source tarball")); // Make sure that the root folder of tarball has the correct name let plain_name = format!("{}-src", pkgname(build, "rustc")); @@ -894,13 +941,13 @@ impl Step for PlainSourceTarball { // Copy the files normally for item in &src_files { - copy(&build.src.join(item), &plain_dst_src.join(item)); + build.copy(&build.src.join(item), &plain_dst_src.join(item)); } // Create the version file - write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); + build.create(&plain_dst_src.join("version"), &build.rust_version()); if let Some(sha) = build.rust_sha() { - write_file(&plain_dst_src.join("git-commit-hash"), sha.as_bytes()); + build.create(&plain_dst_src.join("git-commit-hash"), &sha); } // If we're building from git sources, we need to vendor a complete distribution. @@ -941,9 +988,9 @@ impl Step for PlainSourceTarball { tarball.set_extension(""); // strip .gz tarball.set_extension(""); // strip .tar if let Some(dir) = tarball.parent() { - t!(fs::create_dir_all(dir)); + build.create_dir(&dir); } - println!("running installer"); + build.info(&format!("running installer")); let mut cmd = rust_installer(builder); cmd.arg("tarball") .arg("--input").arg(&plain_name) @@ -955,26 +1002,6 @@ impl Step for PlainSourceTarball { } } -fn install(src: &Path, dstdir: &Path, perms: u32) { - let dst = dstdir.join(src.file_name().unwrap()); - t!(fs::create_dir_all(dstdir)); - drop(fs::remove_file(&dst)); - { - let mut s = t!(fs::File::open(&src)); - let mut d = t!(fs::File::create(&dst)); - io::copy(&mut s, &mut d).expect("failed to copy"); - } - chmod(&dst, perms); -} - -#[cfg(unix)] -fn chmod(path: &Path, perms: u32) { - use std::os::unix::fs::*; - t!(fs::set_permissions(path, fs::Permissions::from_mode(perms))); -} -#[cfg(windows)] -fn chmod(_path: &Path, _perms: u32) {} - // We have to run a few shell scripts, which choke quite a bit on both `\` // characters and on `C:\` paths, so normalize both of them away. pub fn sanitize_sh(path: &Path) -> String { @@ -994,12 +1021,7 @@ pub fn sanitize_sh(path: &Path) -> String { } } -fn write_file(path: &Path, data: &[u8]) { - let mut vf = t!(fs::File::create(path)); - t!(vf.write_all(data)); -} - -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Cargo { pub stage: u32, pub target: Interned, @@ -1007,7 +1029,6 @@ pub struct Cargo { impl Step for Cargo { type Output = PathBuf; - const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { @@ -1026,7 +1047,7 @@ impl Step for Cargo { let stage = self.stage; let target = self.target; - println!("Dist cargo stage{} ({})", stage, target); + build.info(&format!("Dist cargo stage{} ({})", stage, target)); let src = build.src.join("src/tools/cargo"); let etc = src.join("src/etc"); let release_num = build.release_num("cargo"); @@ -1036,38 +1057,38 @@ impl Step for Cargo { let tmp = tmpdir(build); let image = tmp.join("cargo-image"); drop(fs::remove_dir_all(&image)); - t!(fs::create_dir_all(&image)); + build.create_dir(&image); // Prepare the image directory - t!(fs::create_dir_all(image.join("share/zsh/site-functions"))); - t!(fs::create_dir_all(image.join("etc/bash_completion.d"))); + build.create_dir(&image.join("share/zsh/site-functions")); + build.create_dir(&image.join("etc/bash_completion.d")); let cargo = builder.ensure(tool::Cargo { compiler: builder.compiler(stage, build.build), target }); - install(&cargo, &image.join("bin"), 0o755); + build.install(&cargo, &image.join("bin"), 0o755); for man in t!(etc.join("man").read_dir()) { let man = t!(man); - install(&man.path(), &image.join("share/man/man1"), 0o644); + build.install(&man.path(), &image.join("share/man/man1"), 0o644); } - install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644); - copy(&etc.join("cargo.bashcomp.sh"), + build.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644); + build.copy(&etc.join("cargo.bashcomp.sh"), &image.join("etc/bash_completion.d/cargo")); let doc = image.join("share/doc/cargo"); - install(&src.join("README.md"), &doc, 0o644); - install(&src.join("LICENSE-MIT"), &doc, 0o644); - install(&src.join("LICENSE-APACHE"), &doc, 0o644); - install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644); + build.install(&src.join("README.md"), &doc, 0o644); + build.install(&src.join("LICENSE-MIT"), &doc, 0o644); + build.install(&src.join("LICENSE-APACHE"), &doc, 0o644); + build.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644); // Prepare the overlay let overlay = tmp.join("cargo-overlay"); drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - install(&src.join("README.md"), &overlay, 0o644); - install(&src.join("LICENSE-MIT"), &overlay, 0o644); - install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + build.create_dir(&overlay); + build.install(&src.join("README.md"), &overlay, 0o644); + build.install(&src.join("LICENSE-MIT"), &overlay, 0o644); + build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644); + build.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644); + build.create(&overlay.join("version"), &version); // Generate the installer tarball let mut cmd = rust_installer(builder); @@ -1087,7 +1108,7 @@ impl Step for Cargo { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rls { pub stage: u32, pub target: Interned, @@ -1095,7 +1116,6 @@ pub struct Rls { impl Step for Rls { type Output = Option; - const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { @@ -1115,7 +1135,7 @@ impl Step for Rls { let target = self.target; assert!(build.config.extended); - println!("Dist RLS stage{} ({})", stage, target); + build.info(&format!("Dist RLS stage{} ({})", stage, target)); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); let name = pkgname(build, "rls"); @@ -1131,23 +1151,23 @@ impl Step for Rls { // state for RLS isn't testing. let rls = builder.ensure(tool::Rls { compiler: builder.compiler(stage, build.build), - target + target, extra_features: Vec::new() }).or_else(|| { println!("Unable to build RLS, skipping dist"); None })?; - install(&rls, &image.join("bin"), 0o755); + build.install(&rls, &image.join("bin"), 0o755); let doc = image.join("share/doc/rls"); - install(&src.join("README.md"), &doc, 0o644); - install(&src.join("LICENSE-MIT"), &doc, 0o644); - install(&src.join("LICENSE-APACHE"), &doc, 0o644); + build.install(&src.join("README.md"), &doc, 0o644); + build.install(&src.join("LICENSE-MIT"), &doc, 0o644); + build.install(&src.join("LICENSE-APACHE"), &doc, 0o644); // Prepare the overlay let overlay = tmp.join("rls-overlay"); drop(fs::remove_dir_all(&overlay)); t!(fs::create_dir_all(&overlay)); - install(&src.join("README.md"), &overlay, 0o644); - install(&src.join("LICENSE-MIT"), &overlay, 0o644); - install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + build.install(&src.join("README.md"), &overlay, 0o644); + build.install(&src.join("LICENSE-MIT"), &overlay, 0o644); + build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644); + build.create(&overlay.join("version"), &version); // Generate the installer tarball let mut cmd = rust_installer(builder); @@ -1169,7 +1189,7 @@ impl Step for Rls { } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustfmt { pub stage: u32, pub target: Interned, @@ -1177,7 +1197,6 @@ pub struct Rustfmt { impl Step for Rustfmt { type Output = Option; - const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { @@ -1195,9 +1214,8 @@ impl Step for Rustfmt { let build = builder.build; let stage = self.stage; let target = self.target; - assert!(build.config.extended); - println!("Dist Rustfmt stage{} ({})", stage, target); + build.info(&format!("Dist Rustfmt stage{} ({})", stage, target)); let src = build.src.join("src/tools/rustfmt"); let release_num = build.release_num("rustfmt"); let name = pkgname(build, "rustfmt"); @@ -1206,33 +1224,33 @@ impl Step for Rustfmt { let tmp = tmpdir(build); let image = tmp.join("rustfmt-image"); drop(fs::remove_dir_all(&image)); - t!(fs::create_dir_all(&image)); + build.create_dir(&image); // Prepare the image directory let rustfmt = builder.ensure(tool::Rustfmt { compiler: builder.compiler(stage, build.build), - target + target, extra_features: Vec::new() }).or_else(|| { println!("Unable to build Rustfmt, skipping dist"); None })?; let cargofmt = builder.ensure(tool::Cargofmt { compiler: builder.compiler(stage, build.build), - target + target, extra_features: Vec::new() }).or_else(|| { println!("Unable to build Cargofmt, skipping dist"); None })?; - install(&rustfmt, &image.join("bin"), 0o755); - install(&cargofmt, &image.join("bin"), 0o755); + build.install(&rustfmt, &image.join("bin"), 0o755); + build.install(&cargofmt, &image.join("bin"), 0o755); let doc = image.join("share/doc/rustfmt"); - install(&src.join("README.md"), &doc, 0o644); - install(&src.join("LICENSE-MIT"), &doc, 0o644); - install(&src.join("LICENSE-APACHE"), &doc, 0o644); + build.install(&src.join("README.md"), &doc, 0o644); + build.install(&src.join("LICENSE-MIT"), &doc, 0o644); + build.install(&src.join("LICENSE-APACHE"), &doc, 0o644); // Prepare the overlay let overlay = tmp.join("rustfmt-overlay"); drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - install(&src.join("README.md"), &overlay, 0o644); - install(&src.join("LICENSE-MIT"), &overlay, 0o644); - install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + build.create_dir(&overlay); + build.install(&src.join("README.md"), &overlay, 0o644); + build.install(&src.join("LICENSE-MIT"), &overlay, 0o644); + build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644); + build.create(&overlay.join("version"), &version); // Generate the installer tarball let mut cmd = rust_installer(builder); @@ -1253,7 +1271,7 @@ impl Step for Rustfmt { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Extended { stage: u32, host: Interned, @@ -1263,7 +1281,6 @@ pub struct Extended { impl Step for Extended { type Output = (); const DEFAULT: bool = true; - const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { @@ -1274,7 +1291,7 @@ impl Step for Extended { fn make_run(run: RunConfig) { run.builder.ensure(Extended { stage: run.builder.top_stage, - host: run.host, + host: run.builder.build.build, target: run.target, }); } @@ -1285,7 +1302,7 @@ impl Step for Extended { let stage = self.stage; let target = self.target; - println!("Dist extended stage{} ({})", stage, target); + build.info(&format!("Dist extended stage{} ({})", stage, target)); let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target), @@ -1311,15 +1328,15 @@ impl Step for Extended { let work = tmp.join("work"); let _ = fs::remove_dir_all(&overlay); - install(&build.src.join("COPYRIGHT"), &overlay, 0o644); - install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644); - install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); + build.install(&build.src.join("COPYRIGHT"), &overlay, 0o644); + build.install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644); + build.install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); let version = build.rust_version(); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + build.create(&overlay.join("version"), &version); if let Some(sha) = build.rust_sha() { - t!(t!(File::create(overlay.join("git-commit-hash"))).write_all(sha.as_bytes())); + build.create(&overlay.join("git-commit-hash"), &sha); } - install(&etc.join("README.md"), &overlay, 0o644); + build.install(&etc.join("README.md"), &overlay, 0o644); // When rust-std package split from rustc, we needed to ensure that during // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering @@ -1358,11 +1375,11 @@ impl Step for Extended { build.run(&mut cmd); let mut license = String::new(); - t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license)); + license += &build.read(&build.src.join("COPYRIGHT")); + license += &build.read(&build.src.join("LICENSE-APACHE")); + license += &build.read(&build.src.join("LICENSE-MIT")); license.push_str("\n"); - t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license)); license.push_str("\n"); - t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license)); let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18"; let mut rtf = rtf.to_string(); @@ -1419,10 +1436,10 @@ impl Step for Extended { }; let prepare = |name: &str| { - t!(fs::create_dir_all(pkg.join(name))); - cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)), + build.create_dir(&pkg.join(name)); + build.cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)), &pkg.join(name)); - install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755); + build.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755); pkgbuild(name); }; prepare("rustc"); @@ -1436,12 +1453,12 @@ impl Step for Extended { } // create an 'uninstall' package - install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); + build.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); pkgbuild("uninstall"); - t!(fs::create_dir_all(pkg.join("res"))); - t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes())); - install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); + build.create_dir(&pkg.join("res")); + build.create(&pkg.join("res/LICENSE.txt"), &license); + build.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); let mut cmd = Command::new("productbuild"); cmd.arg("--distribution").arg(xform(&etc.join("pkg/Distribution.xml"))) .arg("--resources").arg(pkg.join("res")) @@ -1457,7 +1474,7 @@ impl Step for Extended { let _ = fs::remove_dir_all(&exe); let prepare = |name: &str| { - t!(fs::create_dir_all(exe.join(name))); + build.create_dir(&exe.join(name)); let dir = if name == "rust-std" || name == "rust-analysis" { format!("{}-{}", name, target) } else if name == "rls" { @@ -1465,10 +1482,10 @@ impl Step for Extended { } else { name.to_string() }; - cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)) + build.cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)) .join(dir), &exe.join(name)); - t!(fs::remove_file(exe.join(name).join("manifest.in"))); + build.remove(&exe.join(name).join("manifest.in")); }; prepare("rustc"); prepare("cargo"); @@ -1482,11 +1499,11 @@ impl Step for Extended { prepare("rust-mingw"); } - install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644); - install(&etc.join("exe/modpath.iss"), &exe, 0o644); - install(&etc.join("exe/upgrade.iss"), &exe, 0o644); - install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); - t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes())); + build.install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644); + build.install(&etc.join("exe/modpath.iss"), &exe, 0o644); + build.install(&etc.join("exe/upgrade.iss"), &exe, 0o644); + build.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); + build.create(&exe.join("LICENSE.txt"), &license); // Generate exe installer let mut cmd = Command::new("iscc"); @@ -1497,7 +1514,7 @@ impl Step for Extended { } add_env(build, &mut cmd, target); build.run(&mut cmd); - install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)), + build.install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)), &distdir(build), 0o755); @@ -1621,9 +1638,9 @@ impl Step for Extended { candle("GccGroup.wxs".as_ref()); } - t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes())); - install(&etc.join("gfx/banner.bmp"), &exe, 0o644); - install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); + build.create(&exe.join("LICENSE.rtf"), &rtf); + build.install(&etc.join("gfx/banner.bmp"), &exe, 0o644); + build.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); let filename = format!("{}-{}.msi", pkgname(build, "rust"), target); let mut cmd = Command::new(&light); @@ -1653,7 +1670,9 @@ impl Step for Extended { build.run(&mut cmd); - t!(fs::rename(exe.join(&filename), distdir(build).join(&filename))); + if !build.config.dry_run { + t!(fs::rename(exe.join(&filename), distdir(build).join(&filename))); + } } } } @@ -1687,14 +1706,12 @@ fn add_env(build: &Build, cmd: &mut Command, target: Interned) { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct HashSign; impl Step for HashSign { type Output = (); - const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; - const ONLY_BUILD: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("hash-and-sign") @@ -1707,6 +1724,9 @@ impl Step for HashSign { fn run(self, builder: &Builder) { let build = builder.build; let mut cmd = builder.tool_cmd(Tool::BuildManifest); + if build.config.dry_run { + return; + } let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") }); @@ -1730,7 +1750,7 @@ impl Step for HashSign { cmd.arg(build.package_vers(&build.release_num("rustfmt"))); cmd.arg(addr); - t!(fs::create_dir_all(distdir(build))); + build.create_dir(&distdir(build)); let mut child = t!(cmd.stdin(Stdio::piped()).spawn()); t!(child.stdin.take().unwrap().write_all(pass.as_bytes())); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5bc582b3507b..4237ded2215c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -17,19 +17,21 @@ //! Everything here is basically just a shim around calling either `rustbook` or //! `rustdoc`. +use std::collections::HashSet; use std::fs::{self, File}; use std::io::prelude::*; use std::io; use std::path::{PathBuf, Path}; -use Mode; +use {Build, Mode}; use build_helper::up_to_date; -use util::{cp_r, symlink_dir}; +use util::symlink_dir; use builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; use tool::Tool; use compile; use cache::{INTERNER, Interned}; +use config::Config; macro_rules! book { ($($name:ident, $path:expr, $book_name:expr;)+) => { @@ -167,7 +169,7 @@ impl Step for CargoBook { let out = out.join(name); - println!("Cargo Book ({}) - {}", target, name); + build.info(&format!("Cargo Book ({}) - {}", target, name)); let _ = fs::remove_dir_all(&out); @@ -209,12 +211,13 @@ impl Step for RustbookSrc { let src = src.join(name); let index = out.join("index.html"); let rustbook = builder.tool_exe(Tool::Rustbook); + let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { return } - println!("Rustbook ({}) - {}", target, name); + build.info(&format!("Rustbook ({}) - {}", target, name)); let _ = fs::remove_dir_all(&out); - build.run(builder.tool_cmd(Tool::Rustbook) + build.run(rustbook_cmd .arg("build") .arg(&src) .arg("-d") @@ -280,11 +283,11 @@ impl Step for TheBook { // build the index page let index = format!("{}/index.md", name); - println!("Documenting book index ({})", target); + build.info(&format!("Documenting book index ({})", target)); invoke_rustdoc(builder, compiler, target, &index); // build the redirect pages - println!("Documenting book redirect pages ({})", target); + build.info(&format!("Documenting book redirect pages ({})", target)); for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) { let file = t!(file); let path = file.path(); @@ -357,7 +360,7 @@ impl Step for Standalone { let build = builder.build; let target = self.target; let compiler = self.compiler; - println!("Documenting standalone ({})", target); + build.info(&format!("Documenting standalone ({})", target)); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); @@ -369,7 +372,7 @@ impl Step for Standalone { let version_input = build.src.join("src/doc/version_info.html.template"); let version_info = out.join("version_info.html"); - if !up_to_date(&version_input, &version_info) { + if !build.config.dry_run && !up_to_date(&version_input, &version_info) { let mut info = String::new(); t!(t!(File::open(&version_input)).read_to_string(&mut info)); let info = info.replace("VERSION", &build.rust_release()) @@ -393,7 +396,7 @@ impl Step for Standalone { up_to_date(&favicon, &html) && up_to_date(&full_toc, &html) && up_to_date(&version_info, &html) && - up_to_date(&rustdoc, &html) { + (build.config.dry_run || up_to_date(&rustdoc, &html)) { continue } @@ -448,7 +451,7 @@ impl Step for Std { let build = builder.build; let stage = self.stage; let target = self.target; - println!("Documenting stage{} std ({})", stage, target); + build.info(&format!("Documenting stage{} std ({})", stage, target)); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, build.build); @@ -478,28 +481,24 @@ impl Step for Std { // will also directly handle merging. let my_out = build.crate_doc_out(target); build.clear_if_dirty(&my_out, &rustdoc); - t!(symlink_dir_force(&my_out, &out_dir)); + t!(symlink_dir_force(&build.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc"); compile::std_cargo(builder, &compiler, target, &mut cargo); - // We don't want to build docs for internal std dependencies unless - // in compiler-docs mode. When not in that mode, we whitelist the crates - // for which docs must be built. - if !build.config.compiler_docs { - cargo.arg("--no-deps"); - for krate in &["alloc", "core", "std", "std_unicode"] { - cargo.arg("-p").arg(krate); - // Create all crate output directories first to make sure rustdoc uses - // relative links. - // FIXME: Cargo should probably do this itself. - t!(fs::create_dir_all(out_dir.join(krate))); - } + // Keep a whitelist so we do not build internal stdlib crates, these will be + // build by the rustc step later if enabled. + cargo.arg("--no-deps"); + for krate in &["alloc", "core", "std", "std_unicode"] { + cargo.arg("-p").arg(krate); + // Create all crate output directories first to make sure rustdoc uses + // relative links. + // FIXME: Cargo should probably do this itself. + t!(fs::create_dir_all(out_dir.join(krate))); } - build.run(&mut cargo); - cp_r(&my_out, &out); + build.cp_r(&my_out, &out); } } @@ -533,7 +532,7 @@ impl Step for Test { let build = builder.build; let stage = self.stage; let target = self.target; - println!("Documenting stage{} test ({})", stage, target); + build.info(&format!("Documenting stage{} test ({})", stage, target)); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, build.build); @@ -554,12 +553,87 @@ impl Step for Test { // See docs in std above for why we symlink let my_out = build.crate_doc_out(target); build.clear_if_dirty(&my_out, &rustdoc); - t!(symlink_dir_force(&my_out, &out_dir)); + t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "doc"); compile::test_cargo(build, &compiler, target, &mut cargo); build.run(&mut cargo); - cp_r(&my_out, &out); + build.cp_r(&my_out, &out); + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct WhitelistedRustc { + stage: u32, + target: Interned, +} + +impl Step for WhitelistedRustc { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + let builder = run.builder; + run.krate("rustc-main").default_condition(builder.build.config.docs) + } + + fn make_run(run: RunConfig) { + run.builder.ensure(WhitelistedRustc { + stage: run.builder.top_stage, + target: run.target, + }); + } + + /// Generate whitelisted compiler crate documentation. + /// + /// This will generate all documentation for crates that are whitelisted + /// to be included in the standard documentation. This documentation is + /// included in the standard Rust documentation, so we should always + /// document it and symlink to merge with the rest of the std and test + /// documentation. We don't build other compiler documentation + /// here as we want to be able to keep it separate from the standard + /// documentation. This is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + build.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + let compiler = builder.compiler(stage, build.build); + let rustdoc = builder.rustdoc(compiler.host); + let compiler = if build.force_use_stage1(compiler, target) { + builder.compiler(1, compiler.host) + } else { + compiler + }; + + // Build libstd docs so that we generate relative links + builder.ensure(Std { stage, target }); + + builder.ensure(compile::Rustc { compiler, target }); + let out_dir = build.stage_out(compiler, Mode::Librustc) + .join(target).join("doc"); + + // See docs in std above for why we symlink + let my_out = build.crate_doc_out(target); + build.clear_if_dirty(&my_out, &rustdoc); + t!(symlink_dir_force(&builder.config, &my_out, &out_dir)); + + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc"); + compile::rustc_cargo(build, &mut cargo); + + // We don't want to build docs for internal compiler dependencies in this + // step (there is another step for that). Therefore, we whitelist the crates + // for which docs must be built. + cargo.arg("--no-deps"); + for krate in &["proc_macro"] { + cargo.arg("-p").arg(krate); + } + + build.run(&mut cargo); + build.cp_r(&my_out, &out); } } @@ -586,16 +660,18 @@ impl Step for Rustc { }); } - /// Generate all compiler documentation. + /// Generate compiler documentation. /// - /// This will generate all documentation for the compiler libraries and their - /// dependencies. This is largely just a wrapper around `cargo doc`. + /// This will generate all documentation for compiler and dependencies. + /// Compiler documentation is distributed separately, so we make sure + /// we do not merge it with the other documentation from std, test and + /// proc_macros. This is largely just a wrapper around `cargo doc`. fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let target = self.target; - println!("Documenting stage{} compiler ({})", stage, target); - let out = build.doc_out(target); + build.info(&format!("Documenting stage{} compiler ({})", stage, target)); + let out = build.compiler_doc_out(target); t!(fs::create_dir_all(&out)); let compiler = builder.compiler(stage, build.build); let rustdoc = builder.rustdoc(compiler.host); @@ -605,36 +681,57 @@ impl Step for Rustc { compiler }; + if !build.config.compiler_docs { + build.info(&format!("\tskipping - compiler docs disabled")); + return; + } + // Build libstd docs so that we generate relative links builder.ensure(Std { stage, target }); builder.ensure(compile::Rustc { compiler, target }); let out_dir = build.stage_out(compiler, Mode::Librustc) .join(target).join("doc"); - - // See docs in std above for why we symlink - let my_out = build.crate_doc_out(target); - build.clear_if_dirty(&my_out, &rustdoc); - t!(symlink_dir_force(&my_out, &out_dir)); + // We do not symlink to the same shared folder that already contains std library + // documentation from previous steps as we do not want to include that. + build.clear_if_dirty(&out, &rustdoc); + t!(symlink_dir_force(&builder.config, &out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc"); + cargo.env("RUSTDOCFLAGS", "--document-private-items"); compile::rustc_cargo(build, &mut cargo); - if build.config.compiler_docs { - // src/rustc/Cargo.toml contains a bin crate called rustc which - // would otherwise overwrite the docs for the real rustc lib crate. - cargo.arg("-p").arg("rustc_driver"); - } else { - // Like with libstd above if compiler docs aren't enabled then we're not - // documenting internal dependencies, so we have a whitelist. - cargo.arg("--no-deps"); - for krate in &["proc_macro"] { - cargo.arg("-p").arg(krate); - } + // Only include compiler crates, no dependencies of those, such as `libc`. + cargo.arg("--no-deps"); + + // Find dependencies for top level crates. + let mut compiler_crates = HashSet::new(); + for root_crate in &["rustc", "rustc_driver"] { + let interned_root_crate = INTERNER.intern_str(root_crate); + find_compiler_crates(&build, &interned_root_crate, &mut compiler_crates); + } + + for krate in &compiler_crates { + cargo.arg("-p").arg(krate); } build.run(&mut cargo); - cp_r(&my_out, &out); + } +} + +fn find_compiler_crates( + build: &Build, + name: &Interned, + crates: &mut HashSet> +) { + // Add current crate. + crates.insert(*name); + + // Look for dependencies. + for dep in build.crates.get(name).unwrap().deps.iter() { + if build.crates.get(dep).unwrap().is_local(build) { + find_compiler_crates(build, dep, crates); + } } } @@ -665,7 +762,7 @@ impl Step for ErrorIndex { let build = builder.build; let target = self.target; - println!("Documenting error index ({})", target); + build.info(&format!("Documenting error index ({})", target)); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let mut index = builder.tool_cmd(Tool::ErrorIndex); @@ -710,10 +807,10 @@ impl Step for UnstableBookGen { target, }); - println!("Generating unstable book md files ({})", target); + build.info(&format!("Generating unstable book md files ({})", target)); let out = build.md_doc_out(target).join("unstable-book"); - t!(fs::create_dir_all(&out)); - t!(fs::remove_dir_all(&out)); + build.create_dir(&out); + build.remove_dir(&out); let mut cmd = builder.tool_cmd(Tool::UnstableBookGen); cmd.arg(build.src.join("src")); cmd.arg(out); @@ -722,7 +819,10 @@ impl Step for UnstableBookGen { } } -fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> { +fn symlink_dir_force(config: &Config, src: &Path, dst: &Path) -> io::Result<()> { + if config.dry_run { + return Ok(()); + } if let Ok(m) = fs::symlink_metadata(dst) { if m.file_type().is_dir() { try!(fs::remove_dir_all(dst)); @@ -735,5 +835,5 @@ fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> { } } - symlink_dir(src, dst) + symlink_dir(config, src, dst) } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index af50ad1e96b9..cd304fb26e0b 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -13,7 +13,6 @@ //! This module implements the command-line parsing of the build system which //! has various flags to configure how it's run. -use std::env; use std::fs; use std::path::PathBuf; use std::process; @@ -29,21 +28,20 @@ use cache::{Interned, INTERNER}; /// Deserialized version of all flags for this compile. pub struct Flags { - pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose + pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo pub on_fail: Option, pub stage: Option, pub keep_stage: Option, - pub build: Option>, pub host: Vec>, pub target: Vec>, pub config: Option, - pub src: PathBuf, pub jobs: Option, pub cmd: Subcommand, pub incremental: bool, pub exclude: Vec, pub rustc_error_format: Option, + pub dry_run: bool, } pub enum Subcommand { @@ -114,6 +112,7 @@ To learn more about a subcommand, run `./x.py -h`"); opts.optmulti("", "target", "target targets to build", "TARGET"); opts.optmulti("", "exclude", "build paths to exclude", "PATH"); opts.optopt("", "on-fail", "command to run on failure", "CMD"); + opts.optflag("", "dry-run", "dry run; don't build anything"); opts.optopt("", "stage", "stage to build", "N"); opts.optopt("", "keep-stage", "stage to keep without recompiling", "N"); opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); @@ -278,10 +277,6 @@ Arguments: _ => { } }; // Get any optional paths which occur after the subcommand - let cwd = t!(env::current_dir()); - let src = matches.opt_str("src").map(PathBuf::from) - .or_else(|| env::var_os("SRC").map(PathBuf::from)) - .unwrap_or(cwd.clone()); let paths = matches.free[1..].iter().map(|p| p.into()).collect::>(); let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| { @@ -371,10 +366,10 @@ Arguments: Flags { verbose: matches.opt_count("verbose"), stage, + 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_str("keep-stage").map(|j| j.parse().unwrap()), - build: matches.opt_str("build").map(|s| INTERNER.intern_string(s)), host: split(matches.opt_strs("host")) .into_iter().map(|x| INTERNER.intern_string(x)).collect::>(), target: split(matches.opt_strs("target")) @@ -385,7 +380,6 @@ Arguments: incremental: matches.opt_present("incremental"), exclude: split(matches.opt_strs("exclude")) .into_iter().map(|p| p.into()).collect::>(), - src, } } } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 20f7d379a696..4b05cac1ce69 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -63,22 +63,25 @@ fn install_sh( host: Option> ) { let build = builder.build; - println!("Install {} stage{} ({:?})", package, stage, host); + build.info(&format!("Install {} stage{} ({:?})", package, stage, host)); let prefix_default = PathBuf::from("/usr/local"); let sysconfdir_default = PathBuf::from("/etc"); - let docdir_default = PathBuf::from("share/doc/rust"); + let datadir_default = PathBuf::from("share"); + let docdir_default = datadir_default.join("doc/rust"); let bindir_default = PathBuf::from("bin"); let libdir_default = PathBuf::from("lib"); - let mandir_default = PathBuf::from("share/man"); + let mandir_default = datadir_default.join("man"); let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default); let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default); + let datadir = build.config.datadir.as_ref().unwrap_or(&datadir_default); let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default); let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default); let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default); let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default); let sysconfdir = prefix.join(sysconfdir); + let datadir = prefix.join(datadir); let docdir = prefix.join(docdir); let bindir = prefix.join(bindir); let libdir = prefix.join(libdir); @@ -88,6 +91,7 @@ fn install_sh( let prefix = add_destdir(&prefix, &destdir); let sysconfdir = add_destdir(&sysconfdir, &destdir); + let datadir = add_destdir(&datadir, &destdir); let docdir = add_destdir(&docdir, &destdir); let bindir = add_destdir(&bindir, &destdir); let libdir = add_destdir(&libdir, &destdir); @@ -107,6 +111,7 @@ fn install_sh( .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh"))) .arg(format!("--prefix={}", sanitize_sh(&prefix))) .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir))) + .arg(format!("--datadir={}", sanitize_sh(&datadir))) .arg(format!("--docdir={}", sanitize_sh(&docdir))) .arg(format!("--bindir={}", sanitize_sh(&bindir))) .arg(format!("--libdir={}", sanitize_sh(&libdir))) @@ -161,7 +166,6 @@ macro_rules! install { impl Step for $name { type Output = (); const DEFAULT: bool = true; - const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = $only_hosts; $(const $c: bool = true;)* @@ -174,7 +178,7 @@ macro_rules! install { run.builder.ensure($name { stage: run.builder.top_stage, target: run.target, - host: run.host, + host: run.builder.build.build, }); } @@ -208,7 +212,7 @@ install!((self, builder, _config), Self::should_install(builder) { install_rls(builder, self.stage, self.target); } else { - println!("skipping Install RLS stage{} ({})", self.stage, self.target); + builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target)); } }; Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, { @@ -216,7 +220,8 @@ install!((self, builder, _config), Self::should_install(builder) { install_rustfmt(builder, self.stage, self.target); } else { - println!("skipping Install Rustfmt stage{} ({})", self.stage, self.target); + builder.info( + &format!("skipping Install Rustfmt stage{} ({})", self.stage, self.target)); } }; Analysis, "analysis", Self::should_build(_config), only_hosts: false, { @@ -226,10 +231,6 @@ install!((self, builder, _config), }); install_analysis(builder, self.stage, self.target); }; - Src, "src", Self::should_build(_config) , only_hosts: true, { - builder.ensure(dist::Src); - install_src(builder, self.stage); - }, ONLY_BUILD; Rustc, "src/librustc", true, only_hosts: true, { builder.ensure(dist::Rustc { compiler: builder.compiler(self.stage, self.target), @@ -237,3 +238,32 @@ install!((self, builder, _config), install_rustc(builder, self.stage, self.target); }; ); + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Src { + pub stage: u32, +} + +impl Step for Src { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + let config = &run.builder.config; + let cond = config.extended && + config.tools.as_ref().map_or(true, |t| t.contains("src")); + run.path("src").default_condition(cond) + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Src { + stage: run.builder.top_stage, + }); + } + + fn run(self, builder: &Builder) { + builder.ensure(dist::Src); + install_src(builder, self.stage); + } +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 43f0c9473081..ea4368c0323f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -113,8 +113,9 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. -//#![deny(warnings)] -#![feature(core_intrinsics)] +#![deny(warnings)] +#![feature(conservative_impl_trait, fs_read_write, core_intrinsics)] +#![feature(slice_concat_ext)] #[macro_use] extern crate build_helper; @@ -130,6 +131,11 @@ extern crate getopts; extern crate num_cpus; extern crate toml; extern crate time; +extern crate petgraph; + +#[cfg(test)] +#[macro_use] +extern crate pretty_assertions; #[cfg(unix)] extern crate libc; @@ -137,13 +143,15 @@ extern crate libc; use std::cell::{RefCell, Cell}; use std::collections::{HashSet, HashMap}; use std::env; -use std::fs::{self, File}; -use std::io::Read; +use std::fs::{self, OpenOptions, File}; +use std::io::{self, Seek, SeekFrom, Write, Read}; use std::path::{PathBuf, Path}; use std::process::{self, Command}; use std::slice; +use std::str; use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; +use filetime::FileTime; use util::{exe, libdir, OutputFolder, CiEnv}; @@ -197,7 +205,7 @@ use toolstate::ToolState; /// Each compiler has a `stage` that it is associated with and a `host` that /// corresponds to the platform the compiler runs on. This structure is used as /// a parameter to many methods below. -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +#[derive(Eq, PartialOrd, Ord, PartialEq, Clone, Copy, Hash, Debug)] pub struct Compiler { stage: u32, host: Interned, @@ -253,6 +261,10 @@ pub struct Build { ci_env: CiEnv, delayed_failures: RefCell>, prerelease_version: Cell>, + tool_artifacts: RefCell, + HashMap)> + >>, } #[derive(Debug)] @@ -304,9 +316,8 @@ impl Build { /// /// By default all build output will be placed in the current directory. pub fn new(config: Config) -> Build { - let cwd = t!(env::current_dir()); let src = config.src.clone(); - let out = cwd.join("build"); + let out = config.out.clone(); let is_sudo = match env::var_os("SUDO_USER") { Some(sudo_user) => { @@ -322,7 +333,7 @@ impl Build { let rls_info = channel::GitInfo::new(&config, &src.join("src/tools/rls")); let rustfmt_info = channel::GitInfo::new(&config, &src.join("src/tools/rustfmt")); - Build { + let mut build = Build { initial_rustc: config.initial_rustc.clone(), initial_cargo: config.initial_cargo.clone(), local_rebuild: config.local_rebuild, @@ -352,7 +363,31 @@ impl Build { ci_env: CiEnv::current(), delayed_failures: RefCell::new(Vec::new()), prerelease_version: Cell::new(None), + tool_artifacts: Default::default(), + }; + + build.verbose("finding compilers"); + cc_detect::find(&mut build); + build.verbose("running sanity check"); + sanity::check(&mut build); + + // If local-rust is the same major.minor as the current version, then force a + // local-rebuild + let local_version_verbose = output( + Command::new(&build.initial_rustc).arg("--version").arg("--verbose")); + let local_release = local_version_verbose + .lines().filter(|x| x.starts_with("release:")) + .next().unwrap().trim_left_matches("release:").trim(); + let my_version = channel::CFG_RELEASE_NUM; + if local_release.split('.').take(2).eq(my_version.split('.').take(2)) { + build.verbose(&format!("auto-detected local-rebuild {}", local_release)); + build.local_rebuild = true; } + + build.verbose("learning about cargo"); + metadata::build(&mut build); + + build } pub fn build_triple(&self) -> &[Interned] { @@ -371,25 +406,28 @@ impl Build { return clean::clean(self, all); } - self.verbose("finding compilers"); - cc_detect::find(self); - self.verbose("running sanity check"); - sanity::check(self); - // If local-rust is the same major.minor as the current version, then force a local-rebuild - let local_version_verbose = output( - Command::new(&self.initial_rustc).arg("--version").arg("--verbose")); - let local_release = local_version_verbose - .lines().filter(|x| x.starts_with("release:")) - .next().unwrap().trim_left_matches("release:").trim(); - let my_version = channel::CFG_RELEASE_NUM; - if local_release.split('.').take(2).eq(my_version.split('.').take(2)) { - self.verbose(&format!("auto-detected local-rebuild {}", local_release)); - self.local_rebuild = true; + { + let builder = builder::Builder::new(&self); + if let Some(path) = builder.paths.get(0) { + if path == Path::new("nonexistent/path/to/trigger/cargo/metadata") { + return; + } + } } - self.verbose("learning about cargo"); - metadata::build(self); - builder::Builder::run(&self); + if !self.config.dry_run { + { + self.config.dry_run = true; + let builder = builder::Builder::new(&self); + builder.execute_cli(); + } + self.config.dry_run = false; + let builder = builder::Builder::new(&self); + builder.execute_cli(); + } else { + let builder = builder::Builder::new(&self); + let _ = builder.execute_cli(); + } // Check for postponed failures from `test --no-fail-fast`. let failures = self.delayed_failures.borrow(); @@ -510,6 +548,11 @@ impl Build { self.out.join(&*target).join("doc") } + /// Output directory for all documentation for a target + fn compiler_doc_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("compiler-doc") + } + /// Output directory for some generated md crate documentation for a target (temporary) fn md_doc_out(&self, target: Interned) -> Interned { INTERNER.intern_path(self.out.join(&*target).join("md-doc")) @@ -575,12 +618,14 @@ impl Build { /// Runs a command, printing out nice contextual information if it fails. fn run(&self, cmd: &mut Command) { + if self.config.dry_run { return; } self.verbose(&format!("running: {:?}", cmd)); run_silent(cmd) } /// Runs a command, printing out nice contextual information if it fails. fn run_quiet(&self, cmd: &mut Command) { + if self.config.dry_run { return; } self.verbose(&format!("running: {:?}", cmd)); run_suppressed(cmd) } @@ -589,6 +634,7 @@ impl Build { /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. fn try_run(&self, cmd: &mut Command) -> bool { + if self.config.dry_run { return true; } self.verbose(&format!("running: {:?}", cmd)); try_run_silent(cmd) } @@ -597,6 +643,7 @@ impl Build { /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. fn try_run_quiet(&self, cmd: &mut Command) -> bool { + if self.config.dry_run { return true; } self.verbose(&format!("running: {:?}", cmd)); try_run_suppressed(cmd) } @@ -605,10 +652,6 @@ impl Build { self.verbosity > 0 } - pub fn is_very_verbose(&self) -> bool { - self.verbosity > 1 - } - /// Prints a message if this build is configured in verbose mode. fn verbose(&self, msg: &str) { if self.is_verbose() { @@ -616,6 +659,11 @@ impl Build { } } + fn info(&self, msg: &str) { + if self.config.dry_run { return; } + println!("{}", msg); + } + /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { @@ -702,6 +750,12 @@ impl Build { .map(|p| &**p) } + /// Returns true if this is a no-std `target`, if defined + fn no_std(&self, target: Interned) -> Option { + self.config.target_config.get(&target) + .map(|t| t.no_std) + } + /// Returns whether the target will be tested using the `remote-test-client` /// and `remote-test-server` binaries. fn remote_tested(&self, target: Interned) -> bool { @@ -923,7 +977,7 @@ impl Build { pub fn fold_output(&self, name: F) -> Option where D: Into, F: FnOnce() -> D { - if self.ci_env == CiEnv::Travis { + if !self.config.dry_run && self.ci_env == CiEnv::Travis { Some(OutputFolder::new(name().into())) } else { None @@ -971,8 +1025,173 @@ impl Build { } ret } + + fn read_stamp_file(&self, stamp: &Path) -> Vec { + if self.config.dry_run { + return Vec::new(); + } + + let mut paths = Vec::new(); + let mut contents = Vec::new(); + t!(t!(File::open(stamp)).read_to_end(&mut contents)); + // This is the method we use for extracting paths from the stamp file passed to us. See + // run_cargo for more information (in compile.rs). + for part in contents.split(|b| *b == 0) { + if part.is_empty() { + continue + } + let path = PathBuf::from(t!(str::from_utf8(part))); + paths.push(path); + } + paths + } + + /// Copies a file from `src` to `dst` + pub fn copy(&self, src: &Path, dst: &Path) { + if self.config.dry_run { return; } + let _ = fs::remove_file(&dst); + // Attempt to "easy copy" by creating a hard link (symlinks don't work on + // windows), but if that fails just fall back to a slow `copy` operation. + if let Ok(()) = fs::hard_link(src, dst) { + return + } + if let Err(e) = fs::copy(src, dst) { + panic!("failed to copy `{}` to `{}`: {}", src.display(), + dst.display(), e) + } + let metadata = t!(src.metadata()); + t!(fs::set_permissions(dst, metadata.permissions())); + let atime = FileTime::from_last_access_time(&metadata); + let mtime = FileTime::from_last_modification_time(&metadata); + t!(filetime::set_file_times(dst, atime, mtime)); + } + + /// Search-and-replaces within a file. (Not maximally efficiently: allocates a + /// new string for each replacement.) + pub fn replace_in_file(&self, path: &Path, replacements: &[(&str, &str)]) { + if self.config.dry_run { return; } + let mut contents = String::new(); + let mut file = t!(OpenOptions::new().read(true).write(true).open(path)); + t!(file.read_to_string(&mut contents)); + for &(target, replacement) in replacements { + contents = contents.replace(target, replacement); + } + t!(file.seek(SeekFrom::Start(0))); + t!(file.set_len(0)); + t!(file.write_all(contents.as_bytes())); + } + + /// Copies the `src` directory recursively to `dst`. Both are assumed to exist + /// when this function is called. + pub fn cp_r(&self, src: &Path, dst: &Path) { + if self.config.dry_run { return; } + for f in t!(fs::read_dir(src)) { + let f = t!(f); + let path = f.path(); + let name = path.file_name().unwrap(); + let dst = dst.join(name); + if t!(f.file_type()).is_dir() { + t!(fs::create_dir_all(&dst)); + self.cp_r(&path, &dst); + } else { + let _ = fs::remove_file(&dst); + self.copy(&path, &dst); + } + } + } + + /// Copies the `src` directory recursively to `dst`. Both are assumed to exist + /// when this function is called. Unwanted files or directories can be skipped + /// by returning `false` from the filter function. + pub fn cp_filtered(&self, src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) { + // Immediately recurse with an empty relative path + self.recurse_(src, dst, Path::new(""), filter) + } + + // Inner function does the actual work + fn recurse_(&self, src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) { + for f in self.read_dir(src) { + let path = f.path(); + let name = path.file_name().unwrap(); + let dst = dst.join(name); + let relative = relative.join(name); + // Only copy file or directory if the filter function returns true + if filter(&relative) { + if t!(f.file_type()).is_dir() { + let _ = fs::remove_dir_all(&dst); + self.create_dir(&dst); + self.recurse_(&path, &dst, &relative, filter); + } else { + let _ = fs::remove_file(&dst); + self.copy(&path, &dst); + } + } + } + } + + fn copy_to_folder(&self, src: &Path, dest_folder: &Path) { + let file_name = src.file_name().unwrap(); + let dest = dest_folder.join(file_name); + self.copy(src, &dest); + } + + fn install(&self, src: &Path, dstdir: &Path, perms: u32) { + if self.config.dry_run { return; } + let dst = dstdir.join(src.file_name().unwrap()); + t!(fs::create_dir_all(dstdir)); + drop(fs::remove_file(&dst)); + { + let mut s = t!(fs::File::open(&src)); + let mut d = t!(fs::File::create(&dst)); + io::copy(&mut s, &mut d).expect("failed to copy"); + } + chmod(&dst, perms); + } + + fn create(&self, path: &Path, s: &str) { + if self.config.dry_run { return; } + t!(fs::write(path, s)); + } + + fn read(&self, path: &Path) -> String { + if self.config.dry_run { return String::new(); } + t!(fs::read_string(path)) + } + + fn create_dir(&self, dir: &Path) { + if self.config.dry_run { return; } + t!(fs::create_dir_all(dir)) + } + + fn remove_dir(&self, dir: &Path) { + if self.config.dry_run { return; } + t!(fs::remove_dir_all(dir)) + } + + fn read_dir(&self, dir: &Path) -> impl Iterator { + let iter = match fs::read_dir(dir) { + Ok(v) => v, + Err(_) if self.config.dry_run => return vec![].into_iter(), + Err(err) => panic!("could not read dir {:?}: {:?}", dir, err), + }; + iter.map(|e| t!(e)).collect::>().into_iter() + } + + fn remove(&self, f: &Path) { + if self.config.dry_run { return; } + fs::remove_file(f).unwrap_or_else(|_| panic!("failed to remove {:?}", f)); + } } +#[cfg(unix)] +fn chmod(path: &Path, perms: u32) { + use std::os::unix::fs::*; + t!(fs::set_permissions(path, fs::Permissions::from_mode(perms))); +} +#[cfg(windows)] +fn chmod(_path: &Path, _perms: u32) {} + + impl<'a> Compiler { pub fn with_stage(mut self, stage: u32) -> Compiler { self.stage = stage; diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 7897af4f7247..bcf2f6a675e0 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -85,5 +85,12 @@ check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu: check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu: $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl +TESTS_IN_2 := src/test/run-pass src/test/compile-fail src/test/run-pass-fulldeps + +appveyor-subset-1: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %) +appveyor-subset-2: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) + .PHONY: dist diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f923ad46bcba..db5891afd6b1 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -106,8 +106,8 @@ impl Step for Llvm { let _folder = build.fold_output(|| "llvm"); let descriptor = if emscripten { "Emscripten " } else { "" }; - println!("Building {}LLVM for {}", descriptor, target); - let _time = util::timeit(); + build.info(&format!("Building {}LLVM for {}", descriptor, target)); + let _time = util::timeit(&build); t!(fs::create_dir_all(&out_dir)); // http://llvm.org/docs/CMake.html @@ -217,6 +217,11 @@ impl Step for Llvm { // libraries here, e.g. we just want a few components and a few // tools. Figure out how to filter them down and only build the right // tools and libs on all platforms. + + if builder.config.dry_run { + return build_llvm_config; + } + cfg.build(); t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes())); @@ -230,6 +235,10 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { return } + if build.config.dry_run { + return; + } + let mut cmd = Command::new(llvm_config); let version = output(cmd.arg("--version")); let mut parts = version.split('.').take(2) @@ -336,6 +345,9 @@ impl Step for Lld { /// Compile LLVM for `target`. fn run(self, builder: &Builder) -> PathBuf { + if builder.config.dry_run { + return PathBuf::from("lld-out-dir-test-gen"); + } let target = self.target; let build = builder.build; @@ -351,8 +363,8 @@ impl Step for Lld { } let _folder = build.fold_output(|| "lld"); - println!("Building LLD for {}", target); - let _time = util::timeit(); + build.info(&format!("Building LLD for {}", target)); + let _time = util::timeit(&build); t!(fs::create_dir_all(&out_dir)); let mut cfg = cmake::Config::new(build.src.join("src/tools/lld")); @@ -389,6 +401,9 @@ impl Step for TestHelpers { /// Compiles the `rust_test_helpers.c` library which we used in various /// `run-pass` test suites for ABI testing. fn run(self, builder: &Builder) { + if builder.config.dry_run { + return; + } let build = builder.build; let target = self.target; let dst = build.test_helpers_out(target); @@ -398,7 +413,7 @@ impl Step for TestHelpers { } let _folder = build.fold_output(|| "build_test_helpers"); - println!("Building test helpers"); + build.info(&format!("Building test helpers")); t!(fs::create_dir_all(&dst)); let mut cfg = cc::Build::new(); @@ -441,6 +456,9 @@ impl Step for Openssl { } fn run(self, builder: &Builder) { + if builder.config.dry_run { + return; + } let build = builder.build; let target = self.target; let out = match build.openssl_dir(target) { @@ -591,11 +609,11 @@ impl Step for Openssl { configure.arg("no-asm"); } configure.current_dir(&obj); - println!("Configuring openssl for {}", target); + build.info(&format!("Configuring openssl for {}", target)); build.run_quiet(&mut configure); - println!("Building openssl for {}", target); + build.info(&format!("Building openssl for {}", target)); build.run_quiet(Command::new("make").arg("-j1").current_dir(&obj)); - println!("Installing openssl for {}", target); + build.info(&format!("Installing openssl for {}", target)); build.run_quiet(Command::new("make").arg("install").arg("-j1").current_dir(&obj)); let mut f = t!(File::create(&stamp)); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 5184cca653c4..1b1cec5f18c0 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -169,6 +169,19 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } + if target.contains("-none-") { + if build.no_std(*target).is_none() { + let target = build.config.target_config.entry(target.clone()) + .or_insert(Default::default()); + + target.no_std = true; + } + + if build.no_std(*target) == Some(false) { + panic!("All the *-none-* targets are no-std targets") + } + } + // Make sure musl-root is valid if target.contains("musl") { // If this is a native target (host is also musl) and no musl-root is given, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index cf88916ea709..c175d2c69016 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -109,11 +109,11 @@ impl Step for Linkcheck { let build = builder.build; let host = self.host; - println!("Linkcheck ({})", host); + build.info(&format!("Linkcheck ({})", host)); builder.default_doc(None); - let _time = util::timeit(); + let _time = util::timeit(&build); try_run(build, builder.tool_cmd(Tool::Linkchecker) .arg(build.out.join(host).join("doc"))); } @@ -164,7 +164,7 @@ impl Step for Cargotest { let out_dir = build.out.join("ct"); t!(fs::create_dir_all(&out_dir)); - let _time = util::timeit(); + let _time = util::timeit(&build); let mut cmd = builder.tool_cmd(Tool::CargoTest); try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) @@ -245,7 +245,7 @@ impl Step for Rls { let host = self.host; let compiler = builder.compiler(stage, host); - builder.ensure(tool::Rls { compiler, target: self.host }); + builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() }); let mut cargo = tool::prepare_tool_cargo(builder, compiler, host, @@ -291,7 +291,7 @@ impl Step for Rustfmt { let host = self.host; let compiler = builder.compiler(stage, host); - builder.ensure(tool::Rustfmt { compiler, target: self.host }); + builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() }); let mut cargo = tool::prepare_tool_cargo(builder, compiler, host, @@ -339,7 +339,12 @@ impl Step for Miri { let host = self.host; let compiler = builder.compiler(stage, host); - if let Some(miri) = builder.ensure(tool::Miri { compiler, target: self.host }) { + let miri = builder.ensure(tool::Miri { + compiler, + target: self.host, + extra_features: Vec::new(), + }); + if let Some(miri) = miri { let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml")); @@ -391,7 +396,12 @@ impl Step for Clippy { let host = self.host; let compiler = builder.compiler(stage, host); - if let Some(clippy) = builder.ensure(tool::Clippy { compiler, target: self.host }) { + let clippy = builder.ensure(tool::Clippy { + compiler, + target: self.host, + extra_features: Vec::new(), + }); + if let Some(clippy) = clippy { let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml")); @@ -499,33 +509,27 @@ impl Step for RustdocJS { }); builder.run(&mut command); } else { - println!("No nodejs found, skipping \"src/test/rustdoc-js\" tests"); + builder.info(&format!("No nodejs found, skipping \"src/test/rustdoc-js\" tests")); } } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Tidy { - host: Interned, -} +pub struct Tidy; impl Step for Tidy { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - const ONLY_BUILD: bool = true; - /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. + /// Runs the `tidy` tool. /// /// This tool in `src/tools` checks up on various bits and pieces of style and /// otherwise just implements a few lint-like checks that are specific to the /// compiler itself. fn run(self, builder: &Builder) { let build = builder.build; - let host = self.host; - let _folder = build.fold_output(|| "tidy"); - println!("tidy check ({})", host); let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(build.src.join("src")); cmd.arg(&build.initial_cargo); @@ -535,6 +539,9 @@ impl Step for Tidy { if build.config.quiet_tests { cmd.arg("--quiet"); } + + let _folder = build.fold_output(|| "tidy"); + builder.info(&format!("tidy check")); try_run(build, &mut cmd); } @@ -543,9 +550,7 @@ impl Step for Tidy { } fn make_run(run: RunConfig) { - run.builder.ensure(Tidy { - host: run.builder.build.build, - }); + run.builder.ensure(Tidy); } } @@ -755,12 +760,18 @@ test!(RunFailFullDepsPretty { host: true }); -host_test!(RunMake { +default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" }); +host_test!(RunMakeFullDeps { + path: "src/test/run-make-fulldeps", + mode: "run-make", + suite: "run-make-fulldeps" +}); + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct Compiletest { compiler: Compiler, @@ -823,8 +834,7 @@ impl Step for Compiletest { // FIXME: Does pretty need librustc compiled? Note that there are // fulldeps test suites with mode = pretty as well. mode == "pretty" || - mode == "rustdoc" || - mode == "run-make" { + mode == "rustdoc" { builder.ensure(compile::Rustc { compiler, target }); } @@ -832,9 +842,6 @@ impl Step for Compiletest { builder.ensure(native::TestHelpers { target }); builder.ensure(RemoteCopyLibs { compiler, target }); - let _folder = build.fold_output(|| format!("test_{}", suite)); - println!("Check compiletest suite={} mode={} ({} -> {})", - suite, mode, &compiler.host, target); let mut cmd = builder.tool_cmd(Tool::Compiletest); // compiletest currently has... a lot of arguments, so let's just pass all @@ -845,7 +852,7 @@ impl Step for Compiletest { cmd.arg("--rustc-path").arg(builder.rustc(compiler)); // Avoid depending on rustdoc when we don't need it. - if mode == "rustdoc" || mode == "run-make" { + if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host)); } @@ -919,15 +926,17 @@ impl Step for Compiletest { target: build.config.build, emscripten: false, }); - let llvm_version = output(Command::new(&llvm_config).arg("--version")); - cmd.arg("--llvm-version").arg(llvm_version); + if !build.config.dry_run { + let llvm_version = output(Command::new(&llvm_config).arg("--version")); + cmd.arg("--llvm-version").arg(llvm_version); + } if !build.is_rust_llvm(target) { cmd.arg("--system-llvm"); } // Only pass correct values for these flags for the `run-make` suite as it // requires that a C++ compiler was configured which isn't always the case. - if suite == "run-make" { + if !build.config.dry_run && suite == "run-make-fulldeps" { let llvm_components = output(Command::new(&llvm_config).arg("--components")); let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags")); cmd.arg("--cc").arg(build.cc(target)) @@ -940,12 +949,13 @@ impl Step for Compiletest { } } } - if suite == "run-make" && !build.config.llvm_enabled { - println!("Ignoring run-make test suite as they generally don't work without LLVM"); + if suite == "run-make-fulldeps" && !build.config.llvm_enabled { + builder.info( + &format!("Ignoring run-make test suite as they generally don't work without LLVM")); return; } - if suite != "run-make" { + if suite != "run-make-fulldeps" { cmd.arg("--cc").arg("") .arg("--cxx").arg("") .arg("--cflags").arg("") @@ -994,7 +1004,10 @@ impl Step for Compiletest { build.ci_env.force_coloring_in_ci(&mut cmd); - let _time = util::timeit(); + let _folder = build.fold_output(|| format!("test_{}", suite)); + builder.info(&format!("Check compiletest suite={} mode={} ({} -> {})", + suite, mode, &compiler.host, target)); + let _time = util::timeit(&build); try_run(build, &mut cmd); } } @@ -1029,9 +1042,10 @@ impl Step for DocTest { // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` let mut stack = vec![build.src.join(self.path)]; - let _time = util::timeit(); + let _time = util::timeit(&build); let _folder = build.fold_output(|| format!("test_{}", self.name)); + let mut files = Vec::new(); while let Some(p) = stack.pop() { if p.is_dir() { stack.extend(t!(p.read_dir()).map(|p| t!(p).path())); @@ -1048,7 +1062,13 @@ impl Step for DocTest { continue; } - let test_result = markdown_test(builder, compiler, &p); + files.push(p); + } + + files.sort(); + + for file in files { + let test_result = markdown_test(builder, compiler, &file); if self.is_ext_doc { let toolstate = if test_result { ToolState::TestPass @@ -1138,34 +1158,39 @@ impl Step for ErrorIndex { builder.ensure(compile::Std { compiler, target: compiler.host }); - let _folder = build.fold_output(|| "test_error_index"); - println!("Testing error-index stage{}", compiler.stage); - let dir = testdir(build, compiler.host); t!(fs::create_dir_all(&dir)); let output = dir.join("error-index.md"); - let _time = util::timeit(); - build.run(builder.tool_cmd(Tool::ErrorIndex) - .arg("markdown") - .arg(&output) - .env("CFG_BUILD", &build.build) - .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir())); + let mut tool = builder.tool_cmd(Tool::ErrorIndex); + tool.arg("markdown") + .arg(&output) + .env("CFG_BUILD", &build.build) + .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir()); + + let _folder = build.fold_output(|| "test_error_index"); + build.info(&format!("Testing error-index stage{}", compiler.stage)); + let _time = util::timeit(&build); + build.run(&mut tool); markdown_test(builder, compiler, &output); } } fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool { let build = builder.build; - let mut file = t!(File::open(markdown)); - let mut contents = String::new(); - t!(file.read_to_string(&mut contents)); - if !contents.contains("```") { - return true; + match File::open(markdown) { + Ok(mut file) => { + let mut contents = String::new(); + t!(file.read_to_string(&mut contents)); + if !contents.contains("```") { + return true; + } + } + Err(_) => {}, } - println!("doc tests for: {}", markdown.display()); + build.info(&format!("doc tests for: {}", markdown.display())); let mut cmd = builder.rustdoc_cmd(compiler.host); build.add_rust_test_threads(&mut cmd); cmd.arg("--test"); @@ -1396,11 +1421,6 @@ impl Step for Crate { } _ => panic!("can only test libraries"), }; - let _folder = build.fold_output(|| { - format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate) - }); - println!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage, - &compiler.host, target); // Build up the base `cargo test` command. // @@ -1432,8 +1452,6 @@ impl Step for Crate { cargo.arg("--quiet"); } - let _time = util::timeit(); - if target.contains("emscripten") { cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), build.config.nodejs.as_ref().expect("nodejs not configured")); @@ -1442,8 +1460,8 @@ impl Step for Crate { // The javascript shim implements the syscall interface so that test // output can be correctly reported. if !build.config.wasm_syscall { - println!("Libstd was built without `wasm_syscall` feature enabled: \ - test output may not be visible."); + build.info(&format!("Libstd was built without `wasm_syscall` feature enabled: \ + test output may not be visible.")); } // On the wasm32-unknown-unknown target we're using LTO which is @@ -1461,6 +1479,13 @@ impl Step for Crate { format!("{} run", builder.tool_exe(Tool::RemoteTestClient).display())); } + + let _folder = build.fold_output(|| { + format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate) + }); + build.info(&format!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage, + &compiler.host, target)); + let _time = util::timeit(&build); try_run(build, &mut cargo); } } @@ -1509,12 +1534,6 @@ impl Step for CrateRustdoc { target, test_kind.subcommand(), "src/tools/rustdoc"); - let _folder = build.fold_output(|| { - format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage) - }); - println!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage, - &compiler.host, target); - if test_kind.subcommand() == "test" && !build.fail_fast { cargo.arg("--no-fail-fast"); } @@ -1528,7 +1547,12 @@ impl Step for CrateRustdoc { cargo.arg("--quiet"); } - let _time = util::timeit(); + let _folder = build.fold_output(|| { + format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage) + }); + build.info(&format!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage, + &compiler.host, target)); + let _time = util::timeit(&build); try_run(build, &mut cargo); } @@ -1575,7 +1599,7 @@ impl Step for RemoteCopyLibs { builder.ensure(compile::Test { compiler, target }); - println!("REMOTE copy libs to emulator ({})", target); + build.info(&format!("REMOTE copy libs to emulator ({})", target)); t!(fs::create_dir_all(build.out.join("tmp"))); let server = builder.ensure(tool::RemoteTestServer { compiler, target }); @@ -1610,7 +1634,6 @@ pub struct Distcheck; impl Step for Distcheck { type Output = (); - const ONLY_BUILD: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { run.path("distcheck") @@ -1624,7 +1647,7 @@ impl Step for Distcheck { fn run(self, builder: &Builder) { let build = builder.build; - println!("Distcheck"); + build.info(&format!("Distcheck")); let dir = build.out.join("tmp").join("distcheck"); let _ = fs::remove_dir_all(&dir); t!(fs::create_dir_all(&dir)); @@ -1648,7 +1671,7 @@ impl Step for Distcheck { .current_dir(&dir)); // Now make sure that rust-src has all of libstd's dependencies - println!("Distcheck rust-src"); + build.info(&format!("Distcheck rust-src")); let dir = build.out.join("tmp").join("distcheck-src"); let _ = fs::remove_dir_all(&dir); t!(fs::create_dir_all(&dir)); @@ -1676,7 +1699,6 @@ impl Step for Bootstrap { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - const ONLY_BUILD: bool = true; /// Test the build system itself fn run(self, builder: &Builder) { @@ -1684,9 +1706,16 @@ impl Step for Bootstrap { let mut cmd = Command::new(&build.initial_cargo); cmd.arg("test") .current_dir(build.src.join("src/bootstrap")) + .env("RUSTFLAGS", "-Cdebuginfo=2") .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) .env("RUSTC_BOOTSTRAP", "1") .env("RUSTC", &build.initial_rustc); + if let Some(flags) = option_env!("RUSTFLAGS") { + // Use the same rustc flags for testing as for "normal" compilation, + // so that Cargo doesn’t recompile the entire dependency graph every time: + // https://github.com/rust-lang/rust/issues/49215 + cmd.env("RUSTFLAGS", flags); + } if !build.fail_fast { cmd.arg("--no-fail-fast"); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9036eb044b5a..93b6153fcb2f 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -12,11 +12,12 @@ use std::fs; use std::env; use std::path::PathBuf; use std::process::{Command, exit}; +use std::slice::SliceConcatExt; use Mode; use Compiler; use builder::{Step, RunConfig, ShouldRun, Builder}; -use util::{copy, exe, add_lib_path}; +use util::{exe, add_lib_path}; use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp}; use native; use channel::GitInfo; @@ -74,7 +75,7 @@ impl Step for CleanTools { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] struct ToolBuild { compiler: Compiler, target: Interned, @@ -82,6 +83,7 @@ struct ToolBuild { path: &'static str, mode: Mode, is_ext_tool: bool, + extra_features: Vec, } impl Step for ToolBuild { @@ -110,11 +112,85 @@ impl Step for ToolBuild { Mode::Tool => panic!("unexpected Mode::Tool for tool build") } - let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); - println!("Building stage{} tool {} ({})", compiler.stage, tool, target); - let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path); - let is_expected = build.try_run(&mut cargo); + cargo.arg("--features").arg(self.extra_features.join(" ")); + + let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); + build.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); + let mut duplicates = Vec::new(); + let is_expected = compile::stream_cargo(build, &mut cargo, &mut |msg| { + // Only care about big things like the RLS/Cargo for now + if tool != "rls" && tool != "cargo" { + return + } + let (id, features, filenames) = match msg { + compile::CargoMessage::CompilerArtifact { + package_id, + features, + filenames + } => { + (package_id, features, filenames) + } + _ => return, + }; + let features = features.iter().map(|s| s.to_string()).collect::>(); + + for path in filenames { + let val = (tool, PathBuf::from(&*path), features.clone()); + // we're only interested in deduplicating rlibs for now + if val.1.extension().and_then(|s| s.to_str()) != Some("rlib") { + continue + } + + // Don't worry about libs that turn out to be host dependencies + // or build scripts, we only care about target dependencies that + // are in `deps`. + if let Some(maybe_target) = val.1 + .parent() // chop off file name + .and_then(|p| p.parent()) // chop off `deps` + .and_then(|p| p.parent()) // chop off `release` + .and_then(|p| p.file_name()) + .and_then(|p| p.to_str()) + { + if maybe_target != &*target { + continue + } + } + + let mut artifacts = build.tool_artifacts.borrow_mut(); + let prev_artifacts = artifacts + .entry(target) + .or_insert_with(Default::default); + if let Some(prev) = prev_artifacts.get(&*id) { + if prev.1 != val.1 { + duplicates.push(( + id.to_string(), + val, + prev.clone(), + )); + } + return + } + prev_artifacts.insert(id.to_string(), val); + } + }); + + if is_expected && duplicates.len() != 0 { + println!("duplicate artfacts found when compiling a tool, this \ + typically means that something was recompiled because \ + a transitive dependency has different features activated \ + than in a previous build:\n"); + for (id, cur, prev) in duplicates { + println!(" {}", id); + println!(" `{}` enabled features {:?} at {:?}", + cur.0, cur.2, cur.1); + println!(" `{}` enabled features {:?} at {:?}", + prev.0, prev.2, prev.1); + } + println!(""); + panic!("tools should not compile multiple copies of the same crate"); + } + build.save_toolstate(tool, if is_expected { ToolState::TestFail } else { @@ -131,7 +207,7 @@ impl Step for ToolBuild { let cargo_out = build.cargo_out(compiler, Mode::Tool, target) .join(exe(tool, &compiler.host)); let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host)); - copy(&cargo_out, &bin); + build.copy(&cargo_out, &bin); Some(bin) } } @@ -242,6 +318,7 @@ macro_rules! tool { mode: $mode, path: $path, is_ext_tool: false, + extra_features: Vec::new(), }).expect("expected to build -- essential tool") } } @@ -291,6 +368,7 @@ impl Step for RemoteTestServer { mode: Mode::Libstd, path: "src/tools/remote-test-server", is_ext_tool: false, + extra_features: Vec::new(), }).expect("expected to build -- essential tool") } } @@ -333,9 +411,10 @@ impl Step for Rustdoc { }; builder.ensure(compile::Rustc { compiler: build_compiler, target }); - - let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage)); - println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host); + builder.ensure(compile::Rustc { + compiler: build_compiler, + target: builder.build.build, + }); let mut cargo = prepare_tool_cargo(builder, build_compiler, @@ -347,7 +426,11 @@ impl Step for Rustdoc { cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string()) .env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string()); + let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage)); + build.info(&format!("Building rustdoc for stage{} ({})", + target_compiler.stage, target_compiler.host)); build.run(&mut cargo); + // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" // rustdoc a different name. @@ -361,7 +444,7 @@ impl Step for Rustdoc { t!(fs::create_dir_all(&bindir)); let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host)); let _ = fs::remove_file(&bin_rustdoc); - copy(&tool_rustdoc, &bin_rustdoc); + build.copy(&tool_rustdoc, &bin_rustdoc); bin_rustdoc } else { tool_rustdoc @@ -409,6 +492,7 @@ impl Step for Cargo { mode: Mode::Librustc, path: "src/tools/cargo", is_ext_tool: false, + extra_features: Vec::new(), }).expect("expected to build -- essential tool") } } @@ -421,10 +505,11 @@ macro_rules! tool_extended { $tool_name:expr, $extra_deps:block;)+) => { $( - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $name { pub compiler: Compiler, pub target: Interned, + pub extra_features: Vec, } impl Step for $name { @@ -441,10 +526,12 @@ macro_rules! tool_extended { run.builder.ensure($name { compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build), target: run.target, + extra_features: Vec::new(), }); } - fn run($sel, $builder: &Builder) -> Option { + #[allow(unused_mut)] + fn run(mut $sel, $builder: &Builder) -> Option { $extra_deps $builder.ensure(ToolBuild { compiler: $sel.compiler, @@ -452,6 +539,7 @@ macro_rules! tool_extended { tool: $tool_name, mode: Mode::Librustc, path: $path, + extra_features: $sel.extra_features, is_ext_tool: true, }) } @@ -472,6 +560,14 @@ tool_extended!((self, builder), }; Miri, miri, "src/tools/miri", "miri", {}; Rls, rls, "src/tools/rls", "rls", { + let clippy = builder.ensure(Clippy { + compiler: self.compiler, + target: self.target, + extra_features: Vec::new(), + }); + if clippy.is_some() { + self.extra_features.push("clippy".to_owned()); + } builder.ensure(native::Openssl { target: self.target, }); diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 07941e588387..f8c703236989 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -15,13 +15,14 @@ use std::env; use std::str; -use std::fs::{self, File, OpenOptions}; -use std::io::{self, Read, Write, Seek, SeekFrom}; +use std::fs; +use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{SystemTime, Instant}; -use filetime::{self, FileTime}; +use config::Config; +use Build; /// Returns the `name` as the filename of a static library for `target`. pub fn staticlib(name: &str, target: &str) -> String { @@ -32,102 +33,6 @@ pub fn staticlib(name: &str, target: &str) -> String { } } -/// Copies a file from `src` to `dst` -pub fn copy(src: &Path, dst: &Path) { - let _ = fs::remove_file(&dst); - // Attempt to "easy copy" by creating a hard link (symlinks don't work on - // windows), but if that fails just fall back to a slow `copy` operation. - if let Ok(()) = fs::hard_link(src, dst) { - return - } - if let Err(e) = fs::copy(src, dst) { - panic!("failed to copy `{}` to `{}`: {}", src.display(), - dst.display(), e) - } - let metadata = t!(src.metadata()); - t!(fs::set_permissions(dst, metadata.permissions())); - let atime = FileTime::from_last_access_time(&metadata); - let mtime = FileTime::from_last_modification_time(&metadata); - t!(filetime::set_file_times(dst, atime, mtime)); -} - -/// Search-and-replaces within a file. (Not maximally efficiently: allocates a -/// new string for each replacement.) -pub fn replace_in_file(path: &Path, replacements: &[(&str, &str)]) { - let mut contents = String::new(); - let mut file = t!(OpenOptions::new().read(true).write(true).open(path)); - t!(file.read_to_string(&mut contents)); - for &(target, replacement) in replacements { - contents = contents.replace(target, replacement); - } - t!(file.seek(SeekFrom::Start(0))); - t!(file.set_len(0)); - t!(file.write_all(contents.as_bytes())); -} - -pub fn read_stamp_file(stamp: &Path) -> Vec { - let mut paths = Vec::new(); - let mut contents = Vec::new(); - t!(t!(File::open(stamp)).read_to_end(&mut contents)); - // This is the method we use for extracting paths from the stamp file passed to us. See - // run_cargo for more information (in compile.rs). - for part in contents.split(|b| *b == 0) { - if part.is_empty() { - continue - } - let path = PathBuf::from(t!(str::from_utf8(part))); - paths.push(path); - } - paths -} - -/// Copies the `src` directory recursively to `dst`. Both are assumed to exist -/// when this function is called. -pub fn cp_r(src: &Path, dst: &Path) { - for f in t!(fs::read_dir(src)) { - let f = t!(f); - let path = f.path(); - let name = path.file_name().unwrap(); - let dst = dst.join(name); - if t!(f.file_type()).is_dir() { - t!(fs::create_dir_all(&dst)); - cp_r(&path, &dst); - } else { - let _ = fs::remove_file(&dst); - copy(&path, &dst); - } - } -} - -/// Copies the `src` directory recursively to `dst`. Both are assumed to exist -/// when this function is called. Unwanted files or directories can be skipped -/// by returning `false` from the filter function. -pub fn cp_filtered(src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) { - // Inner function does the actual work - fn recurse(src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) { - for f in t!(fs::read_dir(src)) { - let f = t!(f); - let path = f.path(); - let name = path.file_name().unwrap(); - let dst = dst.join(name); - let relative = relative.join(name); - // Only copy file or directory if the filter function returns true - if filter(&relative) { - if t!(f.file_type()).is_dir() { - let _ = fs::remove_dir_all(&dst); - t!(fs::create_dir(&dst)); - recurse(&path, &dst, &relative, filter); - } else { - let _ = fs::remove_file(&dst); - copy(&path, &dst); - } - } - } - } - // Immediately recurse with an empty relative path - recurse(src, dst, Path::new(""), filter) -} - /// Given an executable called `name`, return the filename for the /// executable for a particular target. pub fn exe(name: &str, target: &str) -> String { @@ -196,25 +101,28 @@ pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { buf } -pub struct TimeIt(Instant); +pub struct TimeIt(bool, Instant); /// Returns an RAII structure that prints out how long it took to drop. -pub fn timeit() -> TimeIt { - TimeIt(Instant::now()) +pub fn timeit(build: &Build) -> TimeIt { + TimeIt(build.config.dry_run, Instant::now()) } impl Drop for TimeIt { fn drop(&mut self) { - let time = self.0.elapsed(); - println!("\tfinished in {}.{:03}", - time.as_secs(), - time.subsec_nanos() / 1_000_000); + let time = self.1.elapsed(); + if !self.0 { + println!("\tfinished in {}.{:03}", + time.as_secs(), + time.subsec_nanos() / 1_000_000); + } } } /// Symlinks two directories, using junctions on Windows and normal symlinks on /// Unix. -pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> { +pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { + if config.dry_run { return Ok(()); } let _ = fs::remove_dir(dest); return symlink_dir_inner(src, dest); @@ -288,6 +196,7 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> { nOutBufferSize: DWORD, lpBytesReturned: LPDWORD, lpOverlapped: LPOVERLAPPED) -> BOOL; + fn CloseHandle(hObject: HANDLE) -> BOOL; } fn to_u16s>(s: S) -> io::Result> { @@ -341,11 +250,13 @@ pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> { &mut ret, ptr::null_mut()); - if res == 0 { + let out = if res == 0 { Err(io::Error::last_os_error()) } else { Ok(()) - } + }; + CloseHandle(h); + out } } } diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml index f8ade0616a57..01d704f816bb 100644 --- a/src/build_helper/Cargo.toml +++ b/src/build_helper/Cargo.toml @@ -6,6 +6,3 @@ authors = ["The Rust Project Developers"] [lib] name = "build_helper" path = "lib.rs" - -[dependencies] -filetime = "0.1" diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 363bbd795442..5a12afd03e13 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -10,14 +10,11 @@ #![deny(warnings)] -extern crate filetime; - use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::{fs, env}; - -use filetime::FileTime; +use std::time::{SystemTime, UNIX_EPOCH}; /// A helper macro to `unwrap` a result except also print out details like: /// @@ -137,10 +134,8 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path) { } /// Returns the last-modified time for `path`, or zero if it doesn't exist. -pub fn mtime(path: &Path) -> FileTime { - fs::metadata(path).map(|f| { - FileTime::from_last_modification_time(&f) - }).unwrap_or(FileTime::zero()) +pub fn mtime(path: &Path) -> SystemTime { + fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH) } /// Returns whether `dst` is up to date given that the file or files in `src` @@ -157,9 +152,9 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool { Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), }; if meta.is_dir() { - dir_up_to_date(src, &threshold) + dir_up_to_date(src, threshold) } else { - FileTime::from_last_modification_time(&meta) <= threshold + meta.modified().unwrap_or(UNIX_EPOCH) <= threshold } } @@ -226,13 +221,13 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result bool { +fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { let meta = t!(e.metadata()); if meta.is_dir() { dir_up_to_date(&e.path(), threshold) } else { - FileTime::from_last_modification_time(&meta) < *threshold + meta.modified().unwrap_or(UNIX_EPOCH) < threshold } }) } diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 2a0901691a55..cb85cf3d9e9f 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -29,6 +29,11 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=asmjs-unknown-emscripten -ENV RUST_CONFIGURE_ARGS --enable-emscripten +ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests -ENV SCRIPT python2.7 ../x.py test --target $TARGETS +ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ + src/test/run-pass \ + src/test/run-fail \ + src/libstd \ + src/liballoc \ + src/libcore diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index dbc319312aa9..cddfa557f6ae 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \ ENV HOSTS=aarch64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index aa5da136758a..e00c23dac89b 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -26,7 +26,8 @@ ENV RUST_CONFIGURE_ARGS \ --armv7-linux-androideabi-ndk=/android/ndk/arm-14 \ --i686-linux-android-ndk=/android/ndk/x86-14 \ --aarch64-linux-android-ndk=/android/ndk/arm64-21 \ - --x86_64-linux-android-ndk=/android/ndk/x86_64-21 + --x86_64-linux-android-ndk=/android/ndk/x86_64-21 \ + --disable-docs ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index 89f7f85cb3b1..6ddc5c1e04ae 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \ ENV HOSTS=arm-unknown-linux-gnueabi -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile index e0c1b9a9e858..e4d4b2feeec4 100644 --- a/src/ci/docker/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/dist-armhf-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \ ENV HOSTS=arm-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index e7d4f464ffcd..99fe7bd7b8f7 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \ ENV HOSTS=armv7-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile index 7bcc649f4aa5..e12bed3abc5a 100644 --- a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile @@ -32,7 +32,8 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-i586=/musl-i586 \ --musl-root-i686=/musl-i686 \ - --enable-extended + --enable-extended \ + --disable-docs # Newer binutils broke things on some vms/distros (i.e., linking against # unknown relocs disabled by the following flag), so we need to go out of our diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile index 1f595ba7a290..6f6a663a3309 100644 --- a/src/ci/docker/dist-i686-freebsd/Dockerfile +++ b/src/ci/docker/dist-i686-freebsd/Dockerfile @@ -29,5 +29,5 @@ ENV \ ENV HOSTS=i686-unknown-freebsd -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-i686-linux/build-gcc.sh b/src/ci/docker/dist-i686-linux/build-gcc.sh index 6b991bb59e4b..08020e533ff1 100755 --- a/src/ci/docker/dist-i686-linux/build-gcc.sh +++ b/src/ci/docker/dist-i686-linux/build-gcc.sh @@ -17,6 +17,23 @@ GCC=4.8.5 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf - cd gcc-$GCC + +# FIXME(#49246): Remove the `sed` below. +# +# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this +# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue: +# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection +# timed out" error, and even when the download completed, the file is usually corrupted. This causes +# nothing to be landed that day. +# +# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability +# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third +# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the +# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server +# instead here. +# +sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites + ./contrib/download_prerequisites mkdir ../gcc-build cd ../gcc-build diff --git a/src/ci/docker/dist-i686-linux/build-git.sh b/src/ci/docker/dist-i686-linux/build-git.sh index ff62a68629a8..aa31f50ba034 100755 --- a/src/ci/docker/dist-i686-linux/build-git.sh +++ b/src/ci/docker/dist-i686-linux/build-git.sh @@ -12,7 +12,7 @@ set -ex source shared.sh -curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf - +curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf - cd git-2.10.0 make configure diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile index 37ab5bdcce55..466def1f80fb 100644 --- a/src/ci/docker/dist-mips-linux/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mips-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile index a5180780b225..2205b733e99f 100644 --- a/src/ci/docker/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mips64-unknown-linux-gnuabi64 -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile index d38ed24f6255..f1d9dad46ea3 100644 --- a/src/ci/docker/dist-mips64el-linux/Dockerfile +++ b/src/ci/docker/dist-mips64el-linux/Dockerfile @@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mips64el-unknown-linux-gnuabi64 -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile index 491c57ba6773..ee73e29c76e3 100644 --- a/src/ci/docker/dist-mipsel-linux/Dockerfile +++ b/src/ci/docker/dist-mipsel-linux/Dockerfile @@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh ENV HOSTS=mipsel-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index c503f2af9cda..f03aff060c10 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -34,7 +34,7 @@ ENV \ ENV HOSTS=powerpc-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # FIXME(#36150) this will fail the bootstrap. Probably means something bad is diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile index 4a3691777360..bb30210c0563 100644 --- a/src/ci/docker/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -35,5 +35,5 @@ ENV \ ENV HOSTS=powerpc64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile index bf6c8b4b7121..ee9e45504835 100644 --- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile @@ -32,5 +32,5 @@ ENV \ ENV HOSTS=powerpc64le-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile index a2ebf590bab7..7ba6fe643c2a 100644 --- a/src/ci/docker/dist-s390x-linux/Dockerfile +++ b/src/ci/docker/dist-s390x-linux/Dockerfile @@ -34,5 +34,5 @@ ENV \ ENV HOSTS=s390x-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index a23153645cde..00366301aa17 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -20,7 +20,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ bzip2 \ patch \ libssl-dev \ - pkg-config + pkg-config \ + gcc-arm-none-eabi \ + libnewlib-arm-none-eabi WORKDIR /build @@ -66,6 +68,14 @@ RUN env \ bash musl.sh mipsel && \ rm -rf /build/* +# FIXME(mozilla/sccache#235) this shouldn't be necessary but is currently +# necessary to disambiguate the mips compiler with the mipsel compiler. We want +# to give these two wrapper scripts (currently identical ones) different hashes +# to ensure that sccache understands that they're different compilers. +RUN \ + echo "# a" >> /usr/local/mips-linux-musl/bin/mips-openwrt-linux-musl-wrapper.sh && \ + echo "# b" >> /usr/local/mipsel-linux-musl/bin/mipsel-openwrt-linux-musl-wrapper.sh + ENV TARGETS=asmjs-unknown-emscripten ENV TARGETS=$TARGETS,wasm32-unknown-emscripten ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd @@ -78,6 +88,10 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu ENV TARGETS=$TARGETS,x86_64-unknown-redox +ENV TARGETS=$TARGETS,thumbv6m-none-eabi +ENV TARGETS=$TARGETS,thumbv7m-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabihf # FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 # get fixed and cc update @@ -95,7 +109,8 @@ ENV RUST_CONFIGURE_ARGS \ --musl-root-aarch64=/musl-aarch64 \ --musl-root-mips=/musl-mips \ --musl-root-mipsel=/musl-mipsel \ - --enable-emscripten + --enable-emscripten \ + --disable-docs ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index 4505a60e4639..e8d6c12de447 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -55,5 +55,5 @@ ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile index dd595a192051..698b81a92e93 100644 --- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile @@ -29,5 +29,5 @@ ENV \ ENV HOSTS=x86_64-unknown-freebsd -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 3b98b0aa926b..28c97e8c6dbf 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -84,7 +84,8 @@ ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-sanitizers \ - --enable-profiler + --enable-profiler \ + --enable-compiler-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/dist-x86_64-linux/build-gcc.sh index 6b991bb59e4b..08020e533ff1 100755 --- a/src/ci/docker/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/dist-x86_64-linux/build-gcc.sh @@ -17,6 +17,23 @@ GCC=4.8.5 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf - cd gcc-$GCC + +# FIXME(#49246): Remove the `sed` below. +# +# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this +# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue: +# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection +# timed out" error, and even when the download completed, the file is usually corrupted. This causes +# nothing to be landed that day. +# +# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability +# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third +# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the +# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server +# instead here. +# +sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites + ./contrib/download_prerequisites mkdir ../gcc-build cd ../gcc-build diff --git a/src/ci/docker/dist-x86_64-linux/build-git.sh b/src/ci/docker/dist-x86_64-linux/build-git.sh index ff62a68629a8..aa31f50ba034 100755 --- a/src/ci/docker/dist-x86_64-linux/build-git.sh +++ b/src/ci/docker/dist-x86_64-linux/build-git.sh @@ -12,7 +12,7 @@ set -ex source shared.sh -curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf - +curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf - cd git-2.10.0 make configure diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index 3a9ad178c639..06f8a2fbba83 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -31,7 +31,8 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/musl-x86_64 \ - --enable-extended + --enable-extended \ + --disable-docs # Newer binutils broke things on some vms/distros (i.e., linking against # unknown relocs disabled by the following flag), so we need to go out of our diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile index 06298a12fc70..a17a7ebc03dd 100644 --- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile @@ -33,5 +33,5 @@ ENV \ ENV HOSTS=x86_64-unknown-netbsd -ENV RUST_CONFIGURE_ARGS --enable-extended +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index f743c976f91a..ea2387b67dbc 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -27,6 +27,21 @@ travis_fold start build_docker travis_time_start if [ -f "$docker_dir/$image/Dockerfile" ]; then + if [ "$CI" != "" ]; then + cksum=$(find $docker_dir/$image $docker_dir/scripts -type f | \ + sort | \ + xargs cat | \ + sha512sum | \ + awk '{print $1}') + s3url="s3://$SCCACHE_BUCKET/docker/$cksum" + url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" + echo "Attempting to download $s3url" + set +e + loaded_images=$(curl $url | docker load | sed 's/.* sha/sha/') + set -e + echo "Downloaded containers:\n$loaded_images" + fi + dockerfile="$docker_dir/$image/Dockerfile" if [ -x /usr/bin/cygpath ]; then context="`cygpath -w $docker_dir`" @@ -40,6 +55,23 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then -t rust-ci \ -f "$dockerfile" \ "$context" + + if [ "$s3url" != "" ]; then + digest=$(docker inspect rust-ci --format '{{.Id}}') + echo "Built container $digest" + if ! grep -q "$digest" <(echo "$loaded_images"); then + echo "Uploading finished image to $s3url" + set +e + docker history -q rust-ci | \ + grep -v missing | \ + xargs docker save | \ + gzip | \ + aws s3 cp - $s3url + set -e + else + echo "Looks like docker image is the same as before, not uploading" + fi + fi elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then if [ -n "$TRAVIS_OS_NAME" ]; then echo Cannot run disabled images on travis! @@ -72,8 +104,6 @@ if [ "$SCCACHE_BUCKET" != "" ]; then args="$args --env SCCACHE_REGION" args="$args --env AWS_ACCESS_KEY_ID" args="$args --env AWS_SECRET_ACCESS_KEY" - args="$args --env SCCACHE_ERROR_LOG=/tmp/sccache/sccache.log" - args="$args --volume $objdir/tmp:/tmp/sccache" else mkdir -p $HOME/.cache/sccache args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index ce2d45563f7b..da52d0831811 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -13,6 +13,6 @@ set -ex curl -fo /usr/local/bin/sccache \ - https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl + https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl chmod +x /usr/local/bin/sccache diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index 0972eb85191a..6c0ec1ad9d4e 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -26,6 +26,7 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.lld ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \ + src/test/run-make \ src/test/ui \ src/test/run-pass \ src/test/compile-fail \ diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index 95d41028595f..ff6ab1013b4c 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -16,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +ENV PARALLEL_CHECK 1 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-debug \ diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile deleted file mode 100644 index 7304ed6015cc..000000000000 --- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python2.7 \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu -ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache -ENV RUST_CHECK_TARGET check -ENV CARGO_INCREMENTAL 0 diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 8ab4276fa3b0..f2664e6d196c 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -17,6 +17,7 @@ ci_dir=$(cd $(dirname $0) && pwd) . "$ci_dir/shared.sh" travis_fold start init_repo +travis_time_start REPO_DIR="$1" CACHE_DIR="$2" @@ -42,54 +43,39 @@ if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then git fetch origin --unshallow beta master fi -travis_fold start update_cache -travis_time_start +function fetch_submodule { + local module=$1 + local cached="download-${module//\//-}.tar.gz" + retry sh -c "rm -f $cached && \ + curl -sSL -o $cached $2" + mkdir $module + touch "$module/.git" + tar -C $module --strip-components=1 -xf $cached + rm $cached +} -# Update the cache (a pristine copy of the rust source master) -retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \ - git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir" -if [ -d $cache_src_dir/src/llvm ]; then - (cd $cache_src_dir && git rm src/llvm) -fi -if [ -d $cache_src_dir/src/llvm-emscripten ]; then - (cd $cache_src_dir && git rm src/llvm-emscripten) -fi -retry sh -c "cd $cache_src_dir && \ - git submodule deinit -f . && git submodule sync && git submodule update --init" - -travis_fold end update_cache -travis_time_finish - -travis_fold start update_submodules -travis_time_start - -# Update the submodules of the repo we're in, using the pristine repo as -# a cache for any object files -# No, `git submodule foreach` won't work: -# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository +included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" -for module in $modules; do - if [ "$module" = src/llvm ] || [ "$module" = src/llvm-emscripten ]; then +modules=($modules) +use_git="" +urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)" +urls=($urls) +for i in ${!modules[@]}; do + module=${modules[$i]} + if [[ " $included " = *" $module "* ]]; then commit="$(git ls-tree HEAD $module | awk '{print $3}')" git rm $module - retry sh -c "rm -f $commit.tar.gz && \ - curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz" - tar -C src/ -xf "$commit.tar.gz" - rm "$commit.tar.gz" - mv "src/llvm-$commit" $module + url=${urls[$i]} + url=${url/\.git/} + fetch_submodule $module "$url/archive/$commit.tar.gz" & continue + else + use_git="$use_git $module" fi - if [ ! -e "$cache_src_dir/$module/.git" ]; then - echo "WARNING: $module not found in pristine repo" - retry sh -c "git submodule deinit -f $module && \ - git submodule update --init --recursive $module" - continue - fi - retry sh -c "git submodule deinit -f $module && \ - git submodule update --init --recursive --reference $cache_src_dir/$module $module" done - -travis_fold end update_submodules -travis_time_finish - +retry sh -c "git submodule deinit -f $use_git && \ + git submodule sync && \ + git submodule update -j 16 --init --recursive $use_git" +wait travis_fold end init_repo +travis_time_finish diff --git a/src/ci/run.sh b/src/ci/run.sh index 79300e08a7d3..44eae0d18004 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -25,6 +25,8 @@ source "$ci_dir/shared.sh" if [ "$TRAVIS" == "true" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-quiet-tests" +else + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings" fi RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache" @@ -46,7 +48,6 @@ export RUST_RELEASE_CHANNEL=nightly if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-thinlto" if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" @@ -73,6 +74,13 @@ fi # sccache server at the start of the build, but no need to worry if this fails. SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true +if [ "$PARALLEL_CHECK" != "" ]; then + $SRC/configure --enable-experimental-parallel-queries + python2.7 ../x.py check + rm -f config.toml + rm -rf build +fi + travis_fold start configure travis_time_start $SRC/configure $RUST_CONFIGURE_ARGS @@ -91,11 +99,19 @@ make check-bootstrap travis_fold end check-bootstrap travis_time_finish +# Display the CPU and memory information. This helps us know why the CI timing +# is fluctuating. +travis_fold start log-system-info if [ "$TRAVIS_OS_NAME" = "osx" ]; then + system_profiler SPHardwareDataType || true + sysctl hw || true ncpus=$(sysctl -n hw.ncpu) else + cat /proc/cpuinfo || true + cat /proc/meminfo || true ncpus=$(grep processor /proc/cpuinfo | wc -l) fi +travis_fold end log-system-info if [ ! -z "$SCRIPT" ]; then sh -x -c "$SCRIPT" diff --git a/src/doc/book b/src/doc/book index 98921e9de849..b889e1e30c5e 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 98921e9de849acdaeaed08cfad6758bb89769b7d +Subproject commit b889e1e30c5e9953834aa9fa6c982bb28df46ac9 diff --git a/src/doc/index.md b/src/doc/index.md index 3add2774105e..2e36831d7e86 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -6,55 +6,72 @@ nav { } -This page is an overview of the documentation included with your Rust install. -Other unofficial documentation may exist elsewhere; for example, the [Rust -Learning] project collects documentation from the community, and [Docs.rs] -builds documentation for individual Rust packages. +Welcome to an overview of the documentation provided by the Rust project. +All of these projects are managed by the Docs Team; there are other +unofficial documentation resources as well! -# API Documentation +Many of these resources take the form of "books"; we collectively call these +"The Rust Bookshelf." Some are large, some are small. -Rust provides a standard library with a number of features; [we host its -documentation here][api]. +## Learn Rust -# Extended Error Documentation +If you'd like to learn Rust, this is the spot for you! All of these resources +assume that you have programmed before, but not in any specific language: + +### The Rust Programming Language + +Affectionately nicknamed "the book," [The Rust Programming +Language](book/index.html) will give you an overview of the language from +first principles. You'll build a few projects along the way, and by the end, +you'll have a solid grasp of the language. + +### Rust By Example + +If reading multiple hundreds of pages about a language isn't your style, then +[Rust By Example](rust-by-example/index.html) has you covered. While the book talks about code with +a lot of words, RBE shows off a bunch of code, and keeps the talking to a +minimum. It also includes exercises! + +## Use Rust + +Once you've gotten familliar with the language, these resources can help you +when you're actually using it day-to-day. + +### The Standard Library + +Rust's standard library has [extensive API documentation](std/index.html), +with explanations of how to use various things, as well as example code for +accomplishing various tasks. + +### The Cargo Book + +[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager. + +### The Rustdoc Book + +[The Rustdoc Book](rustdoc/index.html) describes our documentation tool, `rustdoc`. + +### Extended Error Listing Many of Rust's errors come with error codes, and you can request extended -diagnostics from the compiler on those errors. We also [have the text of those -extended errors on the web][err], if you prefer to read them that way. +diagnostics from the compiler on those errors. You can also [read them +here](error-index.html), if you prefer to read them that way. -# The Rust Bookshelf +## Master Rust -Rust provides a number of book-length sets of documentation, collectively -nicknamed 'The Rust Bookshelf.' +Once you're quite familiar with the language, you may find these advanced +resources useful. -* [The Rust Programming Language][book] teaches you how to program in Rust. -* [Rust By Example][rbe] teaches you how to program in Rust using editable examples. -* [The Cargo Book][cargo-book] is a guide to Cargo, Rust's build tool and dependency manager. -* [The Unstable Book][unstable-book] has documentation for unstable features. -* [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust. -* [The Reference][ref] is not a formal spec, but is more detailed and comprehensive than the book. -* [The Rustdoc Book][rustdoc-book] describes our documentation tool, `rustdoc`. +### The Reference -Initially, documentation lands in the Unstable Book, and then, as part of the -stabilization process, is moved into the Book, Nomicon, or Reference. +[The Reference](reference/index.html) is not a formal spec, but is more detailed and +comprehensive than the book. -Another few words about the reference: it is guaranteed to be accurate, but not -complete. We have a policy that features must have documentation to be stabilized, -but we did not always have this policy, and so there are some stable things that -are not yet in the reference. We're working on back-filling things that landed -before this policy was put into place. That work is being tracked -[here][refchecklist]. +### The Rustonomicon -[Rust Learning]: https://github.com/ctjhoa/rust-learning -[Docs.rs]: https://docs.rs/ -[api]: std/index.html -[ref]: reference/index.html -[refchecklist]: https://github.com/rust-lang-nursery/reference/issues/9 -[err]: error-index.html -[book]: book/index.html -[rbe]: rust-by-example/index.html -[nomicon]: nomicon/index.html -[unstable-book]: unstable-book/index.html -[rustdoc-book]: rustdoc/index.html -[cargo-book]: cargo/index.html +[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe +Rust. It's also sometimes called "the 'nomicon." +### The Unstable Book + +[The Unstable Book](unstable-book/index.html) has documentation for unstable features. diff --git a/src/doc/nomicon b/src/doc/nomicon index ad5ddd62c098..6a8f0a27e9a5 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit ad5ddd62c098d5b424151beda574ae7df2154df1 +Subproject commit 6a8f0a27e9a58c55c89d07bc43a176fdae5e051c diff --git a/src/doc/reference b/src/doc/reference index 254df654a9b7..76296346e97c 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 254df654a9b75abf6ca08806535dbe1fad41be3f +Subproject commit 76296346e97c3702974d3398fdb94af9e10111a2 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ebb28c95b2ea..d5ec87eabe57 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ebb28c95b2ea68b96eddb9e71aff4d32eacc74f0 +Subproject commit d5ec87eabe5733cc2348c7dada89fc67c086f391 diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 6315cb81a849..46528187c117 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -5,3 +5,4 @@ - [The `#[doc]` attribute](the-doc-attribute.md) - [Documentation tests](documentation-tests.md) - [Passes](passes.md) +- [Unstable features](unstable-features.md) diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index e5a603a3709f..fea8685a605d 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -19,18 +19,38 @@ running `rustdoc --test foo.rs` will extract this example, and then run it as a Please note that by default, if no language is set for the block code, `rustdoc` assumes it is `Rust` code. So the following: +``````markdown ```rust let x = 5; ``` +`````` is strictly equivalent to: +``````markdown ``` let x = 5; ``` +`````` There's some subtlety though! Read on for more details. +## Passing or failing a doctest + +Like regular unit tests, regular doctests are considered to "pass" +if they compile and run without panicking. +So if you want to demonstrate that some computation gives a certain result, +the `assert!` family of macros works the same as other Rust code: + +```rust +let foo = "foo"; + +assert_eq!(foo, "foo"); +``` + +This way, if the computation ever returns something different, +the code panics and the doctest fails. + ## Pre-processing examples In the example above, you'll note something strange: there's no `main` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md new file mode 100644 index 000000000000..bf97fb468618 --- /dev/null +++ b/src/doc/rustdoc/src/unstable-features.md @@ -0,0 +1,375 @@ +# Unstable features + +Rustdoc is under active developement, and like the Rust compiler, some features are only available +on the nightly releases. Some of these are new and need some more testing before they're able to get +released to the world at large, and some of them are tied to features in the Rust compiler that are +themselves unstable. Several features here require a matching `#![feature(...)]` attribute to +enable, and thus are more fully documented in the [Unstable Book]. Those sections will link over +there as necessary. + +[Unstable Book]: ../unstable-book/index.html + +## Nightly-gated functionality + +These features just require a nightly build to operate. Unlike the other features on this page, +these don't need to be "turned on" with a command-line flag or a `#![feature(...)]` attribute in +your crate. This can give them some subtle fallback modes when used on a stable release, so be +careful! + +### Error numbers for `compile-fail` doctests + +As detailed in [the chapter on documentation tests][doctest-attributes], you can add a +`compile_fail` attribute to a doctest to state that the test should fail to compile. However, on +nightly, you can optionally add an error number to state that a doctest should emit a specific error +number: + +[doctest-attributes]: documentation-tests.html#attributes + +``````markdown +```compile_fail,E0044 +extern { fn some_func(x: T); } +``` +`````` + +This is used by the error index to ensure that the samples that correspond to a given error number +properly emit that error code. However, these error codes aren't guaranteed to be the only thing +that a piece of code emits from version to version, so this is unlikely to be stabilized in the +future. + +Attempting to use these error numbers on stable will result in the code sample being interpreted as +plain text. + +### Linking to items by type + +As designed in [RFC 1946], Rustdoc can parse paths to items when you use them as links. To resolve +these type names, it uses the items currently in-scope, either by declaration or by `use` statement. +For modules, the "active scope" depends on whether the documentation is written outside the module +(as `///` comments on the `mod` statement) or inside the module (at `//!` comments inside the file +or block). For all other items, it uses the enclosing module's scope. + +[RFC 1946]: https://github.com/rust-lang/rfcs/pull/1946 + +For example, in the following code: + +```rust +/// Does the thing. +pub fn do_the_thing(_: SomeType) { + println!("Let's do the thing!"); +} + +/// Token you use to [`do_the_thing`]. +pub struct SomeType; +``` + +The link to ``[`do_the_thing`]`` in `SomeType`'s docs will properly link to the page for `fn +do_the_thing`. Note that here, rustdoc will insert the link target for you, but manually writing the +target out also works: + +```rust +pub mod some_module { + /// Token you use to do the thing. + pub struct SomeStruct; +} + +/// Does the thing. Requires one [`SomeStruct`] for the thing to work. +/// +/// [`SomeStruct`]: some_module::SomeStruct +pub fn do_the_thing(_: some_module::SomeStruct) { + println!("Let's do the thing!"); +} +``` + +For more details, check out [the RFC][RFC 1946], and see [the tracking issue][43466] for more +information about what parts of the feature are available. + +[43466]: https://github.com/rust-lang/rust/issues/43466 + +## Extensions to the `#[doc]` attribute + +These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler +and enabled with a `#![feature(...)]` attribute in your crate. + +### Documenting platform-/feature-specific information + +Because of the way Rustdoc documents a crate, the documentation it creates is specific to the target +rustc compiles for. Anything that's specific to any other target is dropped via `#[cfg]` attribute +processing early in the compilation process. However, Rustdoc has a trick up its sleeve to handle +platform-specific code if it *does* receive it. + +Because Rustdoc doesn't need to fully compile a crate to binary, it replaces function bodies with +`loop {}` to prevent having to process more than necessary. This means that any code within a +function that requires platform-specific pieces is ignored. Combined with a special attribute, +`#[doc(cfg(...))]`, you can tell Rustdoc exactly which platform something is supposed to run on, +ensuring that doctests are only run on the appropriate platforms. + +The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders documentation for that +item, it will be accompanied by a banner explaining that the item is only available on certain +platforms. + +As mentioned earlier, getting the items to Rustdoc requires some extra preparation. The standard +library adds a `--cfg dox` flag to every Rustdoc command, but the same thing can be accomplished by +adding a feature to your Cargo.toml and adding `--feature dox` (or whatever you choose to name the +feature) to your `cargo doc` calls. + +Either way, once you create an environment for the documentation, you can start to augment your +`#[cfg]` attributes to allow both the target platform *and* the documentation configuration to leave +the item in. For example, `#[cfg(any(windows, feature = "dox"))]` will preserve the item either on +Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` +will tell Rustdoc that the item is supposed to be used on Windows. For example: + +```rust +#![feature(doc_cfg)] + +/// Token struct that can only be used on Windows. +#[cfg(any(windows, feature = "dox"))] +#[doc(cfg(windows))] +pub struct WindowsToken; + +/// Token struct that can only be used on Unix. +#[cfg(any(unix, feature = "dox"))] +#[doc(cfg(unix))] +pub struct UnixToken; +``` + +In this sample, the tokens will only appear on their respective platforms, but they will both appear +in documentation. + +`#[doc(cfg(...))]` was introduced to be used by the standard library and currently requires the +`#![feature(doc_cfg)]` feature gate. For more information, see [its chapter in the Unstable +Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. + +[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html +[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781 + +### Adding your trait to the "Important Traits" dialog + +Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when +implemented on it. These traits are intended to be the primary interface for their types, and are +often the only thing available to be documented on their types. For this reason, Rustdoc will track +when a given type implements one of these traits and call special attention to it when a function +returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next +to the function, which, when clicked, shows the dialog. + +In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and +`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a +special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this +attribute to your own trait to include it in the "Important Traits" dialog in documentation. + +The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate. +For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking +issue][issue-spotlight]. + +[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html +[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040 + +### Exclude certain dependencies from documentation + +The standard library uses several dependencies which, in turn, use several types and traits from the +standard library. In addition, there are several compiler-internal crates that are not considered to +be part of the official standard library, and thus would be a distraction to include in +documentation. It's not enough to exclude their crate documentation, since information about trait +implementations appears on the pages for both the type and the trait, which can be in different +crates! + +To prevent internal types from being included in documentation, the standard library adds an +attribute to their `extern crate` declarations: `#[doc(masked)]`. This causes Rustdoc to "mask out" +types from these crates when building lists of trait implementations. + +The `#[doc(masked)]` attribute is intended to be used internally, and requires the +`#![feature(doc_masked)]` feature gate. For more information, see [its chapter in the Unstable +Book][unstable-masked] and [its tracking issue][issue-masked]. + +[unstable-masked]: ../unstable-book/language-features/doc-masked.html +[issue-masked]: https://github.com/rust-lang/rust/issues/44027 + +### Include external files as API documentation + +As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This +is useful if certain documentation is so long that it would break the flow of reading the source. +Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` (where `sometype.md` is +a file adjacent to the `lib.rs` for the crate) will ask Rustdoc to instead read that file and use it +as if it were written inline. + +[RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990 + +`#[doc(include = "...")]` currently requires the `#![feature(external_doc)]` feature gate. For more +information, see [its chapter in the Unstable Book][unstable-include] and [its tracking +issue][issue-include]. + +[unstable-include]: ../unstable-book/language-features/external-doc.html +[issue-include]: https://github.com/rust-lang/rust/issues/44732 + +## Unstable command-line arguments + +These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are +themselves marked as unstable. To use any of these options, pass `-Z unstable-options` as well as +the flag in question to Rustdoc on the command-line. To do this from Cargo, you can either use the +`RUSTDOCFLAGS` environment variable or the `cargo rustdoc` command. + +### `--markdown-before-content`: include rendered Markdown before the content + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --markdown-before-content extra.md +$ rustdoc README.md -Z unstable-options --markdown-before-content extra.md +``` + +Just like `--html-before-content`, this allows you to insert extra content inside the `` tag +but before the other content `rustdoc` would normally produce in the rendered documentation. +However, instead of directly inserting the file verbatim, `rustdoc` will pass the files through a +Markdown renderer before inserting the result into the file. + +### `--markdown-after-content`: include rendered Markdown after the content + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --markdown-after-content extra.md +$ rustdoc README.md -Z unstable-options --markdown-after-content extra.md +``` + +Just like `--html-after-content`, this allows you to insert extra content before the `` tag +but after the other content `rustdoc` would normally produce in the rendered documentation. +However, instead of directly inserting the file verbatim, `rustdoc` will pass the files through a +Markdown renderer before inserting the result into the file. + +### `--playground-url`: control the location of the playground + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --playground-url https://play.rust-lang.org/ +``` + +When rendering a crate's docs, this flag gives the base URL of the Rust Playground, to use for +generating `Run` buttons. Unlike `--markdown-playground-url`, this argument works for standalone +Markdown files *and* Rust crates. This works the same way as adding `#![doc(html_playground_url = +"url")]` to your crate root, as mentioned in [the chapter about the `#[doc]` +attribute][doc-playground]. Please be aware that the official Rust Playground at +https://play.rust-lang.org does not have every crate available, so if your examples require your +crate, make sure the playground you provide has your crate available. + +[doc-playground]: the-doc-attribute.html#html_playground_url + +If both `--playground-url` and `--markdown-playground-url` are present when rendering a standalone +Markdown file, the URL given to `--markdown-playground-url` will take precedence. If both +`--playground-url` and `#![doc(html_playground_url = "url")]` are present when rendering crate docs, +the attribute will take precedence. + +### `--crate-version`: control the crate version + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --crate-version 1.3.37 +``` + +When `rustdoc` receives this flag, it will print an extra "Version (version)" into the sidebar of +the crate root's docs. You can use this flag to differentiate between different versions of your +library's documentation. + +### `--linker`: control the linker used for documentation tests + +Using this flag looks like this: + +```bash +$ rustdoc --test src/lib.rs -Z unstable-options --linker foo +$ rustdoc --test README.md -Z unstable-options --linker foo +``` + +When `rustdoc` runs your documentation tests, it needs to compile and link the tests as executables +before running them. This flag can be used to change the linker used on these executables. It's +equivalent to passing `-C linker=foo` to `rustc`. + +### `--sort-modules-by-appearance`: control how items on module pages are sorted + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --sort-modules-by-appearance +``` + +Ordinarily, when `rustdoc` prints items in module pages, it will sort them alphabetically (taking +some consideration for their stability, and names that end in a number). Giving this flag to +`rustdoc` will disable this sorting and instead make it print the items in the order they appear in +the source. + +### `--themes`: provide additional themes + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --themes theme.css +``` + +Giving this flag to `rustdoc` will make it copy your theme into the generated crate docs and enable +it in the theme selector. Note that `rustdoc` will reject your theme file if it doesn't style +everything the "light" theme does. See `--theme-checker` below for details. + +### `--theme-checker`: verify theme CSS for validity + +Using this flag looks like this: + +```bash +$ rustdoc -Z unstable-options --theme-checker theme.css +``` + +Before including your theme in crate docs, `rustdoc` will compare all the CSS rules it contains +against the "light" theme included by default. Using this flag will allow you to see which rules are +missing if `rustdoc` rejects your theme. + +### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --resource-suffix suf +``` + +When rendering docs, `rustdoc` creates several CSS and JavaScript files as part of the output. Since +all these files are linked from every page, changing where they are can be cumbersome if you need to +specially cache them. This flag will rename all these files in the output to include the suffix in +the filename. For example, `light.css` would become `light-suf.css` with the above command. + +### `--display-warnings`: display warnings when documenting or running documentation tests + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --display-warnings +$ rustdoc --test src/lib.rs -Z unstable-options --display-warnings +``` + +The intent behind this flag is to allow the user to see warnings that occur within their library or +their documentation tests, which are usually suppressed. However, [due to a +bug][issue-display-warnings], this flag doesn't 100% work as intended. See the linked issue for +details. + +[issue-display-warnings]: https://github.com/rust-lang/rust/issues/41574 + +### `--edition`: control the edition of docs and doctests + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --edition 2018 +$ rustdoc --test src/lib.rs -Z unstable-options --edition 2018 +``` + +This flag allows rustdoc to treat your rust code as the given edition. It will compile doctests with +the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015` +(the first edition). + +### `-Z force-unstable-if-unmarked` + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z force-unstable-if-unmarked +``` + +This is an internal flag intended for the standard library and compiler that applies an +`#[unstable]` attribute to any dependent crate that doesn't have another stability attribute. This +allows `rustdoc` to be able to generate documentation for the compiler crates and the standard +library, as an equivalent command-line argument is provided to `rustc` when building those crates. diff --git a/src/doc/unstable-book/src/language-features/advanced-slice-patterns.md b/src/doc/unstable-book/src/language-features/advanced-slice-patterns.md deleted file mode 100644 index e8256469b145..000000000000 --- a/src/doc/unstable-book/src/language-features/advanced-slice-patterns.md +++ /dev/null @@ -1,35 +0,0 @@ -# `advanced_slice_patterns` - -The tracking issue for this feature is: [#23121] - -[#23121]: https://github.com/rust-lang/rust/issues/23121 - -See also [`slice_patterns`](language-features/slice-patterns.html). - ------------------------- - - -The `advanced_slice_patterns` gate lets you use `..` to indicate any number of -elements inside a pattern matching a slice. This wildcard can only be used once -for a given array. If there's an identifier before the `..`, the result of the -slice will be bound to that name. For example: - -```rust -#![feature(advanced_slice_patterns, slice_patterns)] - -fn is_symmetric(list: &[u32]) -> bool { - match list { - &[] | &[_] => true, - &[x, ref inside.., y] if x == y => is_symmetric(inside), - _ => false - } -} - -fn main() { - let sym = &[0, 1, 4, 2, 4, 1, 0]; - assert!(is_symmetric(sym)); - - let not_sym = &[0, 1, 7, 2, 4, 1, 0]; - assert!(!is_symmetric(not_sym)); -} -``` diff --git a/src/doc/unstable-book/src/language-features/conservative-impl-trait.md b/src/doc/unstable-book/src/language-features/conservative-impl-trait.md deleted file mode 100644 index 0be6a321103f..000000000000 --- a/src/doc/unstable-book/src/language-features/conservative-impl-trait.md +++ /dev/null @@ -1,66 +0,0 @@ -# `conservative_impl_trait` - -The tracking issue for this feature is: [#34511] - -[#34511]: https://github.com/rust-lang/rust/issues/34511 - ------------------------- - -The `conservative_impl_trait` feature allows a conservative form of abstract -return types. - -Abstract return types allow a function to hide a concrete return type behind a -trait interface similar to trait objects, while still generating the same -statically dispatched code as with concrete types. - -## Examples - -```rust -#![feature(conservative_impl_trait)] - -fn even_iter() -> impl Iterator { - (0..).map(|n| n * 2) -} - -fn main() { - let first_four_even_numbers = even_iter().take(4).collect::>(); - assert_eq!(first_four_even_numbers, vec![0, 2, 4, 6]); -} -``` - -## Background - -In today's Rust, you can write function signatures like: - -````rust,ignore -fn consume_iter_static>(iter: I) { } - -fn consume_iter_dynamic(iter: Box>) { } -```` - -In both cases, the function does not depend on the exact type of the argument. -The type held is "abstract", and is assumed only to satisfy a trait bound. - -* In the `_static` version using generics, each use of the function is - specialized to a concrete, statically-known type, giving static dispatch, - inline layout, and other performance wins. -* In the `_dynamic` version using trait objects, the concrete argument type is - only known at runtime using a vtable. - -On the other hand, while you can write: - -````rust,ignore -fn produce_iter_dynamic() -> Box> { } -```` - -...but you _cannot_ write something like: - -````rust,ignore -fn produce_iter_static() -> Iterator { } -```` - -That is, in today's Rust, abstract return types can only be written using trait -objects, which can be a significant performance penalty. This RFC proposes -"unboxed abstract types" as a way of achieving signatures like -`produce_iter_static`. Like generics, unboxed abstract types guarantee static -dispatch and inline data layout. diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md index e8e2132dca25..8e888de90a95 100644 --- a/src/doc/unstable-book/src/language-features/generators.md +++ b/src/doc/unstable-book/src/language-features/generators.md @@ -36,11 +36,11 @@ fn main() { return "foo" }; - match generator.resume() { + match unsafe { generator.resume() } { GeneratorState::Yielded(1) => {} _ => panic!("unexpected value from resume"), } - match generator.resume() { + match unsafe { generator.resume() } { GeneratorState::Complete("foo") => {} _ => panic!("unexpected value from resume"), } @@ -69,9 +69,9 @@ fn main() { }; println!("1"); - generator.resume(); + unsafe { generator.resume() }; println!("3"); - generator.resume(); + unsafe { generator.resume() }; println!("5"); } ``` @@ -92,7 +92,7 @@ The `Generator` trait in `std::ops` currently looks like: pub trait Generator { type Yield; type Return; - fn resume(&mut self) -> GeneratorState; + unsafe fn resume(&mut self) -> GeneratorState; } ``` @@ -175,8 +175,8 @@ fn main() { return ret }; - generator.resume(); - generator.resume(); + unsafe { generator.resume() }; + unsafe { generator.resume() }; } ``` @@ -200,7 +200,7 @@ fn main() { type Yield = i32; type Return = &'static str; - fn resume(&mut self) -> GeneratorState { + unsafe fn resume(&mut self) -> GeneratorState { use std::mem; match mem::replace(self, __Generator::Done) { __Generator::Start(s) => { @@ -223,8 +223,8 @@ fn main() { __Generator::Start(ret) }; - generator.resume(); - generator.resume(); + unsafe { generator.resume() }; + unsafe { generator.resume() }; } ``` diff --git a/src/doc/unstable-book/src/language-features/i128-type.md b/src/doc/unstable-book/src/language-features/i128-type.md deleted file mode 100644 index a850b7644c3a..000000000000 --- a/src/doc/unstable-book/src/language-features/i128-type.md +++ /dev/null @@ -1,25 +0,0 @@ -# `i128_type` - -The tracking issue for this feature is: [#35118] - -[#35118]: https://github.com/rust-lang/rust/issues/35118 - ------------------------- - -The `i128_type` feature adds support for 128 bit signed and unsigned integer -types. - -```rust -#![feature(i128_type)] - -fn main() { - assert_eq!(1u128 + 1u128, 2u128); - assert_eq!(u128::min_value(), 0); - assert_eq!(u128::max_value(), 340282366920938463463374607431768211455); - - assert_eq!(1i128 - 2i128, -1i128); - assert_eq!(i128::min_value(), -170141183460469231731687303715884105728); - assert_eq!(i128::max_value(), 170141183460469231731687303715884105727); -} -``` - diff --git a/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md b/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md deleted file mode 100644 index 56f58803150c..000000000000 --- a/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md +++ /dev/null @@ -1,20 +0,0 @@ -# `inclusive_range_syntax` - -The tracking issue for this feature is: [#28237] - -[#28237]: https://github.com/rust-lang/rust/issues/28237 - ------------------------- - -To get a range that goes from 0 to 10 and includes the value 10, you -can write `0..=10`: - -```rust -#![feature(inclusive_range_syntax)] - -fn main() { - for i in 0..=10 { - println!("{}", i); - } -} -``` diff --git a/src/doc/unstable-book/src/language-features/match-default-bindings.md b/src/doc/unstable-book/src/language-features/match-default-bindings.md deleted file mode 100644 index cc542931cbe1..000000000000 --- a/src/doc/unstable-book/src/language-features/match-default-bindings.md +++ /dev/null @@ -1,58 +0,0 @@ -# `match_default_bindings` - -The tracking issue for this feature is: [#42640] - -[#42640]: https://github.com/rust-lang/rust/issues/42640 - ------------------------- - -Match default bindings (also called "default binding modes in match") improves ergonomics for -pattern-matching on references by introducing automatic dereferencing (and a corresponding shift -in binding modes) for large classes of patterns that would otherwise not compile. - -For example, under match default bindings, - -```rust -#![feature(match_default_bindings)] - -fn main() { - let x: &Option<_> = &Some(0); - - match x { - Some(y) => { - println!("y={}", *y); - }, - None => {}, - } -} -``` - -compiles and is equivalent to either of the below: - -```rust -fn main() { - let x: &Option<_> = &Some(0); - - match *x { - Some(ref y) => { - println!("y={}", *y); - }, - None => {}, - } -} -``` - -or - -```rust -fn main() { - let x: &Option<_> = &Some(0); - - match x { - &Some(ref y) => { - println!("y={}", *y); - }, - &None => {}, - } -} -``` diff --git a/src/doc/unstable-book/src/language-features/repr128.md b/src/doc/unstable-book/src/language-features/repr128.md new file mode 100644 index 000000000000..0858988952c1 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/repr128.md @@ -0,0 +1,18 @@ +# `repr128` + +The tracking issue for this feature is: [#35118] + +[#35118]: https://github.com/rust-lang/rust/issues/35118 + +------------------------ + +The `repr128` feature adds support for `#[repr(u128)]` on `enum`s. + +```rust +#![feature(repr128)] + +#[repr(u128)] +enum Foo { + Bar(u64), +} +``` diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md index 69857297582d..133174268ef9 100644 --- a/src/doc/unstable-book/src/language-features/slice-patterns.md +++ b/src/doc/unstable-book/src/language-features/slice-patterns.md @@ -4,25 +4,29 @@ The tracking issue for this feature is: [#23121] [#23121]: https://github.com/rust-lang/rust/issues/23121 -See also -[`advanced_slice_patterns`](language-features/advanced-slice-patterns.html). - ------------------------ - -If you want to match against a slice or array, you can use `&` with the -`slice_patterns` feature: +The `slice_patterns` feature gate lets you use `..` to indicate any number of +elements inside a pattern matching a slice. This wildcard can only be used once +for a given array. If there's an pattern before the `..`, the subslice will be +matched against that pattern. For example: ```rust #![feature(slice_patterns)] -fn main() { - let v = vec!["match_this", "1"]; - - match &v[..] { - &["match_this", second] => println!("The second element is {}", second), - _ => {}, +fn is_symmetric(list: &[u32]) -> bool { + match list { + &[] | &[_] => true, + &[x, ref inside.., y] if x == y => is_symmetric(inside), + &[..] => false, } } -``` +fn main() { + let sym = &[0, 1, 4, 2, 4, 1, 0]; + assert!(is_symmetric(sym)); + + let not_sym = &[0, 1, 7, 2, 4, 1, 0]; + assert!(!is_symmetric(not_sym)); +} +``` diff --git a/src/doc/unstable-book/src/language-features/universal-impl-trait.md b/src/doc/unstable-book/src/language-features/universal-impl-trait.md deleted file mode 100644 index 6b3c5e92720d..000000000000 --- a/src/doc/unstable-book/src/language-features/universal-impl-trait.md +++ /dev/null @@ -1,32 +0,0 @@ -# `universal_impl_trait` - -The tracking issue for this feature is: [#34511]. - -[#34511]: https://github.com/rust-lang/rust/issues/34511 - --------------------- - -The `universal_impl_trait` feature extends the [`conservative_impl_trait`] -feature allowing the `impl Trait` syntax in arguments (universal -quantification). - -[`conservative_impl_trait`]: ./language-features/conservative-impl-trait.html - -## Examples - -```rust -#![feature(universal_impl_trait)] -use std::ops::Not; - -fn any_zero(values: impl IntoIterator) -> bool { - for val in values { if val == 0 { return true; } } - false -} - -fn main() { - let test1 = -5..; - let test2 = vec![1, 8, 42, -87, 60]; - assert!(any_zero(test1)); - assert!(bool::not(any_zero(test2))); -} -``` diff --git a/src/doc/unstable-book/src/library-features/splice.md b/src/doc/unstable-book/src/library-features/splice.md deleted file mode 100644 index 2e4bb1a5257c..000000000000 --- a/src/doc/unstable-book/src/library-features/splice.md +++ /dev/null @@ -1,22 +0,0 @@ -# `splice` - -The tracking issue for this feature is: [#44643] - -[#44643]: https://github.com/rust-lang/rust/issues/44643 - ------------------------- - -The `splice()` method on `String` allows you to replace a range -of values in a string with another range of values. - -A simple example: - -```rust -#![feature(splice)] -let mut s = String::from("α is alpha, β is beta"); -let beta_offset = s.find('β').unwrap_or(s.len()); - -// Replace the range up until the β from the string -s.splice(..beta_offset, "Α is capital alpha; "); -assert_eq!(s, "Α is capital alpha; β is beta"); -``` diff --git a/src/doc/unstable-book/src/library-features/string-retain.md b/src/doc/unstable-book/src/library-features/string-retain.md deleted file mode 100644 index 049444aa49bd..000000000000 --- a/src/doc/unstable-book/src/library-features/string-retain.md +++ /dev/null @@ -1,23 +0,0 @@ -# `string_retain` - -The tracking issue for this feature is: [#43874] - -[#43874]: https://github.com/rust-lang/rust/issues/43874 - ------------------------- - -Retains only the characters specified by the predicate. - -In other words, remove all characters `c` such that `f(c)` returns `false`. -This method operates in place and preserves the order of the retained -characters. - -```rust -#![feature(string_retain)] - -let mut s = String::from("f_o_ob_ar"); - -s.retain(|c| c != '_'); - -assert_eq!(s, "foobar"); -``` diff --git a/src/etc/cat-and-grep.sh b/src/etc/cat-and-grep.sh index ef9884d2e980..361e8d8e60ee 100755 --- a/src/etc/cat-and-grep.sh +++ b/src/etc/cat-and-grep.sh @@ -63,6 +63,11 @@ done shift $((OPTIND - 1)) +# use gnu version of tool if available (for bsd) +if command -v "g${GREPPER}"; then + GREPPER="g${GREPPER}" +fi + LOG=$(mktemp -t cgrep.XXXXXX) trap "rm -f $LOG" EXIT diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y index de1f96aac504..a7da69f65faf 100644 --- a/src/grammar/parser-lalr.y +++ b/src/grammar/parser-lalr.y @@ -1400,7 +1400,6 @@ nonblock_expr | BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); } | YIELD { $$ = mk_node("ExprYield", 0); } | YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| nonblock_expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); } | nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } | nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } | nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } @@ -1463,7 +1462,6 @@ expr | BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } | YIELD { $$ = mk_node("ExprYield", 0); } | YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); } | expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } | expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } | expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } @@ -1527,7 +1525,6 @@ expr_nostruct | BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } | YIELD { $$ = mk_node("ExprYield", 0); } | YIELD expr { $$ = mk_node("ExprYield", 1, $2); } -| expr_nostruct LARROW expr_nostruct { $$ = mk_node("ExprInPlace", 2, $1, $3); } | expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); } | expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); } | expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); } diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index 0a265ee1376a..3bf919b0c001 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -12,7 +12,7 @@ core = { path = "../libcore" } std_unicode = { path = "../libstd_unicode" } [dev-dependencies] -rand = "0.3" +rand = "0.4" [[test]] name = "collectionstests" diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 6a77bf64baee..ccf2e2768d1a 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -21,6 +21,7 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; use core::fmt; use core::cmp::Ordering; +use core::heap::{Alloc, Layout}; use core::intrinsics::abort; use core::mem::{self, align_of_val, size_of_val, uninitialized}; use core::ops::Deref; @@ -31,7 +32,7 @@ use core::hash::{Hash, Hasher}; use core::{isize, usize}; use core::convert::From; -use heap::{Heap, Alloc, Layout, box_free}; +use heap::{Heap, box_free}; use boxed::Box; use string::String; use vec::Vec; diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 2de0ffb4b261..a43aadfe9a23 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -10,9 +10,10 @@ #![deny(warnings)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(rand)] #![feature(repr_simd)] +#![feature(slice_sort_by_cached_key)] #![feature(test)] extern crate rand; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index ee5182a1d466..a699ff9c0a76 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -284,6 +284,17 @@ macro_rules! sort_expensive { } } +macro_rules! sort_lexicographic { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + b.iter(|| v.clone().$f(|x| x.to_string())); + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; + } + } +} + sort!(sort, sort_small_ascending, gen_ascending, 10); sort!(sort, sort_small_descending, gen_descending, 10); sort!(sort, sort_small_random, gen_random, 10); @@ -312,6 +323,10 @@ sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); +sort_lexicographic!(sort_by_key, sort_by_key_lexicographic, gen_random, 10000); +sort_lexicographic!(sort_unstable_by_key, sort_unstable_by_key_lexicographic, gen_random, 10000); +sort_lexicographic!(sort_by_cached_key, sort_by_cached_key_lexicographic, gen_random, 10000); + macro_rules! reverse { ($name:ident, $ty:ty, $f:expr) => { #[bench] diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 8aaac5d6e08a..668b61c51d8b 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -155,7 +155,7 @@ #![allow(missing_docs)] #![stable(feature = "rust1", since = "1.0.0")] -use core::ops::{Deref, DerefMut, Place, Placer, InPlace}; +use core::ops::{Deref, DerefMut}; use core::iter::{FromIterator, FusedIterator}; use core::mem::{swap, size_of}; use core::ptr; @@ -509,6 +509,31 @@ impl BinaryHeap { self.data.shrink_to_fit(); } + /// Discards capacity with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to(10); + /// assert!(heap.capacity() >= 10); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.data.shrink_to(min_capacity) + } + /// Removes the greatest item from the binary heap and returns it, or `None` if it /// is empty. /// @@ -1170,67 +1195,3 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap { self.extend(iter.into_iter().cloned()); } } - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -pub struct BinaryHeapPlace<'a, T: 'a> -where T: Clone + Ord { - heap: *mut BinaryHeap, - place: vec::PlaceBack<'a, T>, -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T: Clone + Ord + fmt::Debug> fmt::Debug for BinaryHeapPlace<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("BinaryHeapPlace") - .field(&self.place) - .finish() - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T: 'a> Placer for &'a mut BinaryHeap -where T: Clone + Ord { - type Place = BinaryHeapPlace<'a, T>; - - fn make_place(self) -> Self::Place { - let ptr = self as *mut BinaryHeap; - let place = Placer::make_place(self.data.place_back()); - BinaryHeapPlace { - heap: ptr, - place, - } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, T> Place for BinaryHeapPlace<'a, T> -where T: Clone + Ord { - fn pointer(&mut self) -> *mut T { - self.place.pointer() - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> InPlace for BinaryHeapPlace<'a, T> -where T: Clone + Ord { - type Owner = &'a T; - - unsafe fn finalize(self) -> &'a T { - self.place.finalize(); - - let heap: &mut BinaryHeap = &mut *self.heap; - let len = heap.len(); - let i = heap.sift_up(0, len - 1); - heap.data.get_unchecked(i) - } -} diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index acae0daa86b6..c6741ddb822d 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -59,6 +59,7 @@ pub trait ToOwned { /// let vv: Vec = v.to_owned(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] fn to_owned(&self) -> Self::Owned; /// Uses borrowed data to replace owned data, usually by cloning. diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b776556d59f1..4f9dc61ce196 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -55,54 +55,21 @@ #![stable(feature = "rust1", since = "1.0.0")] -use heap::{Heap, Layout, Alloc}; use raw_vec::RawVec; use core::any::Any; use core::borrow; use core::cmp::Ordering; use core::fmt; -use core::hash::{self, Hash, Hasher}; +use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; -use core::marker::{self, Unsize}; -use core::mem; +use core::marker::{Unpin, Unsize}; +use core::mem::{self, Pin}; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; -use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer}; use core::ptr::{self, NonNull, Unique}; use core::convert::From; use str::from_boxed_utf8_unchecked; -/// A value that represents the heap. This is the default place that the `box` -/// keyword allocates into when no place is supplied. -/// -/// The following two examples are equivalent: -/// -/// ``` -/// #![feature(box_heap)] -/// -/// #![feature(box_syntax, placement_in_syntax)] -/// use std::boxed::HEAP; -/// -/// fn main() { -/// let foo: Box = in HEAP { 5 }; -/// let foo = box 5; -/// } -/// ``` -#[unstable(feature = "box_heap", - reason = "may be renamed; uncertain about custom allocator design", - issue = "27779")] -pub const HEAP: ExchangeHeapSingleton = ExchangeHeapSingleton { _force_singleton: () }; - -/// This the singleton type used solely for `boxed::HEAP`. -#[unstable(feature = "box_heap", - reason = "may be renamed; uncertain about custom allocator design", - issue = "27779")] -#[allow(missing_debug_implementations)] -#[derive(Copy, Clone)] -pub struct ExchangeHeapSingleton { - _force_singleton: (), -} - /// A pointer type for heap allocation. /// /// See the [module-level documentation](../../std/boxed/index.html) for more. @@ -111,121 +78,6 @@ pub struct ExchangeHeapSingleton { #[stable(feature = "rust1", since = "1.0.0")] pub struct Box(Unique); -/// `IntermediateBox` represents uninitialized backing storage for `Box`. -/// -/// FIXME (pnkfelix): Ideally we would just reuse `Box` instead of -/// introducing a separate `IntermediateBox`; but then you hit -/// issues when you e.g. attempt to destructure an instance of `Box`, -/// since it is a lang item and so it gets special handling by the -/// compiler. Easier just to make this parallel type for now. -/// -/// FIXME (pnkfelix): Currently the `box` protocol only supports -/// creating instances of sized types. This IntermediateBox is -/// designed to be forward-compatible with a future protocol that -/// supports creating instances of unsized types; that is why the type -/// parameter has the `?Sized` generalization marker, and is also why -/// this carries an explicit size. However, it probably does not need -/// to carry the explicit alignment; that is just a work-around for -/// the fact that the `align_of` intrinsic currently requires the -/// input type to be Sized (which I do not think is strictly -/// necessary). -#[unstable(feature = "placement_in", - reason = "placement box design is still being worked out.", - issue = "27779")] -#[allow(missing_debug_implementations)] -pub struct IntermediateBox { - ptr: *mut u8, - layout: Layout, - marker: marker::PhantomData<*mut T>, -} - -#[unstable(feature = "placement_in", - reason = "placement box design is still being worked out.", - issue = "27779")] -unsafe impl Place for IntermediateBox { - fn pointer(&mut self) -> *mut T { - self.ptr as *mut T - } -} - -unsafe fn finalize(b: IntermediateBox) -> Box { - let p = b.ptr as *mut T; - mem::forget(b); - Box::from_raw(p) -} - -fn make_place() -> IntermediateBox { - let layout = Layout::new::(); - - let p = if layout.size() == 0 { - mem::align_of::() as *mut u8 - } else { - unsafe { - Heap.alloc(layout.clone()).unwrap_or_else(|err| { - Heap.oom(err) - }) - } - }; - - IntermediateBox { - ptr: p, - layout, - marker: marker::PhantomData, - } -} - -#[unstable(feature = "placement_in", - reason = "placement box design is still being worked out.", - issue = "27779")] -impl BoxPlace for IntermediateBox { - fn make_place() -> IntermediateBox { - make_place() - } -} - -#[unstable(feature = "placement_in", - reason = "placement box design is still being worked out.", - issue = "27779")] -impl InPlace for IntermediateBox { - type Owner = Box; - unsafe fn finalize(self) -> Box { - finalize(self) - } -} - -#[unstable(feature = "placement_new_protocol", issue = "27779")] -impl Boxed for Box { - type Data = T; - type Place = IntermediateBox; - unsafe fn finalize(b: IntermediateBox) -> Box { - finalize(b) - } -} - -#[unstable(feature = "placement_in", - reason = "placement box design is still being worked out.", - issue = "27779")] -impl Placer for ExchangeHeapSingleton { - type Place = IntermediateBox; - - fn make_place(self) -> IntermediateBox { - make_place() - } -} - -#[unstable(feature = "placement_in", - reason = "placement box design is still being worked out.", - issue = "27779")] -impl Drop for IntermediateBox { - fn drop(&mut self) { - if self.layout.size() > 0 { - unsafe { - Heap.dealloc(self.ptr, self.layout.clone()) - } - } - } -} - impl Box { /// Allocates memory on the heap and then places `x` into it. /// @@ -508,7 +360,7 @@ impl Eq for Box {} #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Box { - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { (**self).hash(state); } } @@ -892,7 +744,104 @@ impl Generator for Box { type Yield = T::Yield; type Return = T::Return; - fn resume(&mut self) -> GeneratorState { + unsafe fn resume(&mut self) -> GeneratorState { (**self).resume() } } + +/// A pinned, heap allocated reference. +#[unstable(feature = "pin", issue = "49150")] +#[fundamental] +pub struct PinBox { + inner: Box, +} + +#[unstable(feature = "pin", issue = "49150")] +impl PinBox { + /// Allocate memory on the heap, move the data into it and pin it. + #[unstable(feature = "pin", issue = "49150")] + pub fn new(data: T) -> PinBox { + PinBox { inner: Box::new(data) } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl PinBox { + /// Get a pinned reference to the data in this PinBox. + pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> { + unsafe { Pin::new_unchecked(&mut *self.inner) } + } + + /// Get a mutable reference to the data inside this PinBox. + /// + /// This function is unsafe. Users must guarantee that the data is never + /// moved out of this reference. + pub unsafe fn get_mut<'a>(this: &'a mut PinBox) -> &'a mut T { + &mut *this.inner + } + + /// Convert this PinBox into an unpinned Box. + /// + /// This function is unsafe. Users must guarantee that the data is never + /// moved out of the box. + pub unsafe fn unpin(this: PinBox) -> Box { + this.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl From> for PinBox { + fn from(boxed: Box) -> PinBox { + PinBox { inner: boxed } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl From> for Box { + fn from(pinned: PinBox) -> Box { + pinned.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl Deref for PinBox { + type Target = T; + + fn deref(&self) -> &T { + &*self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl DerefMut for PinBox { + fn deref_mut(&mut self) -> &mut T { + &mut *self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Display for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&*self.inner, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Debug for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&*self.inner, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Pointer for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // It's not possible to extract the inner Uniq directly from the Box, + // instead we cast it to a *const which aliases the Unique + let ptr: *const T = &*self.inner; + fmt::Pointer::fmt(&ptr, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl, U: ?Sized> CoerceUnsized> for PinBox {} diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index ed9c8c18f0d6..c604df7049e0 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -13,12 +13,12 @@ use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; +use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::Index; +use core::ops::RangeBounds; use core::{fmt, intrinsics, mem, ptr}; use borrow::Borrow; -use Bound::{Excluded, Included, Unbounded}; -use range::RangeArgument; use super::node::{self, Handle, NodeRef, marker}; use super::search; @@ -576,6 +576,33 @@ impl BTreeMap { } } + /// Returns the key-value pair corresponding to the supplied key. + /// + /// The supplied key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_get_key_value)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); + /// assert_eq!(map.get_key_value(&2), None); + /// ``` + #[unstable(feature = "map_get_key_value", issue = "49347")] + pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> + where K: Borrow, + Q: Ord + { + match search::search_tree(self.root.as_ref(), k) { + Found(handle) => Some(handle.into_kv()), + GoDown(_) => None, + } + } + /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but the ordering @@ -777,7 +804,7 @@ impl BTreeMap { /// /// ``` /// use std::collections::BTreeMap; - /// use std::collections::Bound::Included; + /// use std::ops::Bound::Included; /// /// let mut map = BTreeMap::new(); /// map.insert(3, "a"); @@ -790,7 +817,7 @@ impl BTreeMap { /// ``` #[stable(feature = "btree_range", since = "1.17.0")] pub fn range(&self, range: R) -> Range - where T: Ord, K: Borrow, R: RangeArgument + where T: Ord, K: Borrow, R: RangeBounds { let root1 = self.root.as_ref(); let root2 = self.root.as_ref(); @@ -830,7 +857,7 @@ impl BTreeMap { /// ``` #[stable(feature = "btree_range", since = "1.17.0")] pub fn range_mut(&mut self, range: R) -> RangeMut - where T: Ord, K: Borrow, R: RangeArgument + where T: Ord, K: Borrow, R: RangeBounds { let root1 = self.root.as_mut(); let root2 = unsafe { ptr::read(&root1) }; @@ -1785,7 +1812,7 @@ fn last_leaf_edge } } -fn range_search>( +fn range_search>( root1: NodeRef, root2: NodeRef, range: R diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs index c1618043ce66..49109d522e96 100644 --- a/src/liballoc/btree/node.rs +++ b/src/liballoc/btree/node.rs @@ -41,14 +41,14 @@ // - A node of length `n` has `n` keys, `n` values, and (in an internal node) `n + 1` edges. // This implies that even an empty internal node has at least one edge. +use core::heap::{Alloc, Layout}; use core::marker::PhantomData; use core::mem; -use core::nonzero::NonZero; -use core::ptr::{self, Unique}; +use core::ptr::{self, Unique, NonNull}; use core::slice; use boxed::Box; -use heap::{Heap, Alloc, Layout}; +use heap::Heap; const B: usize = 6; pub const MIN_LEN: usize = B - 1; @@ -149,14 +149,12 @@ impl BoxedNode { } } - unsafe fn from_ptr(ptr: NonZero<*const LeafNode>) -> Self { - BoxedNode { ptr: Unique::new_unchecked(ptr.get() as *mut LeafNode) } + unsafe fn from_ptr(ptr: NonNull>) -> Self { + BoxedNode { ptr: Unique::from(ptr) } } - fn as_ptr(&self) -> NonZero<*const LeafNode> { - unsafe { - NonZero::from(self.ptr.as_ref()) - } + fn as_ptr(&self) -> NonNull> { + NonNull::from(self.ptr) } } @@ -276,7 +274,7 @@ impl Root { /// `NodeRef` could be pointing to either type of node. pub struct NodeRef { height: usize, - node: NonZero<*const LeafNode>, + node: NonNull>, // This is null unless the borrow type is `Mut` root: *const Root, _marker: PhantomData<(BorrowType, Type)> @@ -302,7 +300,7 @@ unsafe impl Send impl NodeRef { fn as_internal(&self) -> &InternalNode { unsafe { - &*(self.node.get() as *const InternalNode) + &*(self.node.as_ptr() as *mut InternalNode) } } } @@ -310,7 +308,7 @@ impl NodeRef { impl<'a, K, V> NodeRef, K, V, marker::Internal> { fn as_internal_mut(&mut self) -> &mut InternalNode { unsafe { - &mut *(self.node.get() as *mut InternalNode) + &mut *(self.node.as_ptr() as *mut InternalNode) } } } @@ -352,7 +350,7 @@ impl NodeRef { fn as_leaf(&self) -> &LeafNode { unsafe { - &*self.node.get() + self.node.as_ref() } } @@ -382,7 +380,8 @@ impl NodeRef { >, Self > { - if let Some(non_zero) = NonZero::new(self.as_leaf().parent as *const LeafNode) { + let parent_as_leaf = self.as_leaf().parent as *const LeafNode; + if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) { Ok(Handle { node: NodeRef { height: self.height + 1, @@ -498,7 +497,7 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { fn as_leaf_mut(&mut self) -> &mut LeafNode { unsafe { - &mut *(self.node.get() as *mut LeafNode) + self.node.as_mut() } } @@ -1241,12 +1240,12 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: } Heap.dealloc( - right_node.node.get() as *mut u8, + right_node.node.as_ptr() as *mut u8, Layout::new::>(), ); } else { Heap.dealloc( - right_node.node.get() as *mut u8, + right_node.node.as_ptr() as *mut u8, Layout::new::>(), ); } diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index 2e3157147a08..2aad476d3153 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -16,12 +16,11 @@ use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; use core::iter::{Peekable, FromIterator, FusedIterator}; -use core::ops::{BitOr, BitAnd, BitXor, Sub}; +use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds}; use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use super::Recover; -use range::RangeArgument; // FIXME(conventions): implement bounded iterators @@ -240,7 +239,7 @@ impl BTreeSet { /// /// ``` /// use std::collections::BTreeSet; - /// use std::collections::Bound::Included; + /// use std::ops::Bound::Included; /// /// let mut set = BTreeSet::new(); /// set.insert(3); @@ -253,7 +252,7 @@ impl BTreeSet { /// ``` #[stable(feature = "btree_range", since = "1.17.0")] pub fn range(&self, range: R) -> Range - where K: Ord, T: Borrow, R: RangeArgument + where K: Ord, T: Borrow, R: RangeBounds { Range { iter: self.map.range(range) } } diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index a092bfb3b0a8..b2c4582e8406 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -113,6 +113,8 @@ //! //! * *nothing* ⇒ [`Display`] //! * `?` ⇒ [`Debug`] +//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers +//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers //! * `o` ⇒ [`Octal`](trait.Octal.html) //! * `x` ⇒ [`LowerHex`](trait.LowerHex.html) //! * `X` ⇒ [`UpperHex`](trait.UpperHex.html) @@ -324,7 +326,7 @@ //! sign := '+' | '-' //! width := count //! precision := count | '*' -//! type := identifier | '' +//! type := identifier | '?' | '' //! count := parameter | integer //! parameter := argument '$' //! ``` @@ -514,17 +516,17 @@ pub use core::fmt::rt; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Formatter, Result, Write}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{Octal, Binary}; +pub use core::fmt::{Binary, Octal}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{Display, Debug}; +pub use core::fmt::{Debug, Display}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{LowerHex, UpperHex, Pointer}; +pub use core::fmt::{LowerHex, Pointer, UpperHex}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{LowerExp, UpperExp}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::Error; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{ArgumentV1, Arguments, write}; +pub use core::fmt::{write, ArgumentV1, Arguments}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; @@ -561,7 +563,8 @@ use string; pub fn format(args: Arguments) -> string::String { let capacity = args.estimated_capacity(); let mut output = string::String::with_capacity(capacity); - output.write_fmt(args) - .expect("a formatting trait implementation returned an error"); + output + .write_fmt(args) + .expect("a formatting trait implementation returned an error"); output } diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 372d606e4572..9296a1130718 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -19,7 +19,7 @@ use core::intrinsics::{min_align_of_val, size_of_val}; use core::mem::{self, ManuallyDrop}; use core::usize; -pub use allocator::*; +pub use core::heap::*; #[doc(hidden)] pub mod __core { pub use core::*; @@ -228,14 +228,6 @@ unsafe impl Alloc for Heap { } } -/// An arbitrary non-null address to represent zero-size allocations. -/// -/// This preserves the non-null invariant for types like `Box`. The address -/// may overlap with non-zero-size memory allocations. -#[rustc_deprecated(since = "1.19.0", reason = "Use Unique/NonNull::empty() instead")] -#[unstable(feature = "heap_api", issue = "27700")] -pub const EMPTY: *mut () = 1 as *mut (); - /// The allocator for unique pointers. // This function must not unwind. If it does, MIR trans will fail. #[cfg(not(test))] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 3f3067845588..6ce2547ef6e6 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -76,11 +76,11 @@ #![deny(missing_debug_implementations)] #![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(test, feature(placement_in))] #![cfg_attr(not(test), feature(core_float))] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(rand, test))] +#![feature(allocator_api)] #![feature(allow_internal_unstable)] #![feature(ascii_ctype)] #![feature(box_into_raw_non_null)] @@ -88,6 +88,7 @@ #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] +#![feature(collections_range)] #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(custom_attribute)] @@ -96,27 +97,24 @@ #![feature(fmt_internals)] #![feature(from_ref)] #![feature(fundamental)] -#![feature(generic_param_attrs)] -#![feature(i128_type)] -#![feature(inclusive_range)] -#![feature(iter_rfold)] +#![cfg_attr(stage0, feature(generic_param_attrs))] +#![cfg_attr(stage0, feature(i128_type))] #![feature(lang_items)] #![feature(needs_allocator)] #![feature(nonzero)] #![feature(offset_to)] #![feature(optin_builtin_traits)] #![feature(pattern)] -#![feature(placement_in_syntax)] -#![feature(placement_new_protocol)] +#![feature(pin)] #![feature(ptr_internals)] #![feature(rustc_attrs)] #![feature(slice_get_slice)] -#![feature(slice_patterns)] #![feature(slice_rsplit)] #![feature(specialization)] #![feature(staged_api)] #![feature(str_internals)] #![feature(trusted_len)] +#![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unsize)] @@ -124,9 +122,10 @@ #![feature(on_unimplemented)] #![feature(exact_chunks)] #![feature(pointer_methods)] +#![feature(inclusive_range_fields)] -#![cfg_attr(not(test), feature(fn_traits, placement_new_protocol, swap_with_slice, i128))] -#![cfg_attr(test, feature(test, box_heap))] +#![cfg_attr(not(test), feature(fn_traits, swap_with_slice, i128))] +#![cfg_attr(test, feature(test))] // Allow testing this library @@ -144,9 +143,9 @@ extern crate std_unicode; #[macro_use] mod macros; -// Allocator trait and helper struct definitions - -pub mod allocator; +#[rustc_deprecated(since = "1.27.0", reason = "use the heap module in core, alloc, or std instead")] +#[unstable(feature = "allocator_api", issue = "32838")] +pub use core::heap as allocator; // Heaps provided for low-level allocation strategies @@ -156,13 +155,12 @@ pub mod heap; // Need to conditionally define the mod from `boxed.rs` to avoid // duplicating the lang-items when building in test cfg; but also need -// to allow code to have `use boxed::HEAP;` -// and `use boxed::Box;` declarations. +// to allow code to have `use boxed::Box;` declarations. #[cfg(not(test))] pub mod boxed; #[cfg(test)] mod boxed { - pub use std::boxed::{Box, IntermediateBox, HEAP}; + pub use std::boxed::Box; } #[cfg(test)] mod boxed_test; @@ -177,7 +175,6 @@ mod btree; pub mod borrow; pub mod fmt; pub mod linked_list; -pub mod range; pub mod slice; pub mod str; pub mod string; @@ -203,57 +200,6 @@ mod std { pub use core::ops; // RangeFull } -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} - /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] trait SpecExtend { diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index 097d2e414f5c..129b3bc67643 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -28,10 +28,9 @@ use core::hash::{Hasher, Hash}; use core::iter::{FromIterator, FusedIterator}; use core::marker::PhantomData; use core::mem; -use core::ops::{BoxPlace, InPlace, Place, Placer}; -use core::ptr::{self, NonNull}; +use core::ptr::NonNull; -use boxed::{Box, IntermediateBox}; +use boxed::Box; use super::SpecExtend; /// A doubly-linked list with owned nodes. @@ -786,62 +785,6 @@ impl LinkedList { old_len: old_len, } } - - /// Returns a place for insertion at the front of the list. - /// - /// Using this method with placement syntax is equivalent to - /// [`push_front`](#method.push_front), but may be more efficient. - /// - /// # Examples - /// - /// ``` - /// #![feature(collection_placement)] - /// #![feature(placement_in_syntax)] - /// - /// use std::collections::LinkedList; - /// - /// let mut list = LinkedList::new(); - /// list.front_place() <- 2; - /// list.front_place() <- 4; - /// assert!(list.iter().eq(&[4, 2])); - /// ``` - #[unstable(feature = "collection_placement", - reason = "method name and placement protocol are subject to change", - issue = "30172")] - pub fn front_place(&mut self) -> FrontPlace { - FrontPlace { - list: self, - node: IntermediateBox::make_place(), - } - } - - /// Returns a place for insertion at the back of the list. - /// - /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back), - /// but may be more efficient. - /// - /// # Examples - /// - /// ``` - /// #![feature(collection_placement)] - /// #![feature(placement_in_syntax)] - /// - /// use std::collections::LinkedList; - /// - /// let mut list = LinkedList::new(); - /// list.back_place() <- 2; - /// list.back_place() <- 4; - /// assert!(list.iter().eq(&[2, 4])); - /// ``` - #[unstable(feature = "collection_placement", - reason = "method name and placement protocol are subject to change", - issue = "30172")] - pub fn back_place(&mut self) -> BackPlace { - BackPlace { - list: self, - node: IntermediateBox::make_place(), - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1242,123 +1185,6 @@ impl Hash for LinkedList { } } -unsafe fn finalize(node: IntermediateBox>) -> Box> { - let mut node = node.finalize(); - ptr::write(&mut node.next, None); - ptr::write(&mut node.prev, None); - node -} - -/// A place for insertion at the front of a `LinkedList`. -/// -/// See [`LinkedList::front_place`](struct.LinkedList.html#method.front_place) for details. -#[must_use = "places do nothing unless written to with `<-` syntax"] -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -pub struct FrontPlace<'a, T: 'a> { - list: &'a mut LinkedList, - node: IntermediateBox>, -} - -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -impl<'a, T: 'a + fmt::Debug> fmt::Debug for FrontPlace<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("FrontPlace") - .field(&self.list) - .finish() - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> Placer for FrontPlace<'a, T> { - type Place = Self; - - fn make_place(self) -> Self { - self - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, T> Place for FrontPlace<'a, T> { - fn pointer(&mut self) -> *mut T { - unsafe { &mut (*self.node.pointer()).element } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> InPlace for FrontPlace<'a, T> { - type Owner = (); - - unsafe fn finalize(self) { - let FrontPlace { list, node } = self; - list.push_front_node(finalize(node)); - } -} - -/// A place for insertion at the back of a `LinkedList`. -/// -/// See [`LinkedList::back_place`](struct.LinkedList.html#method.back_place) for details. -#[must_use = "places do nothing unless written to with `<-` syntax"] -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -pub struct BackPlace<'a, T: 'a> { - list: &'a mut LinkedList, - node: IntermediateBox>, -} - -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -impl<'a, T: 'a + fmt::Debug> fmt::Debug for BackPlace<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("BackPlace") - .field(&self.list) - .finish() - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> Placer for BackPlace<'a, T> { - type Place = Self; - - fn make_place(self) -> Self { - self - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, T> Place for BackPlace<'a, T> { - fn pointer(&mut self) -> *mut T { - unsafe { &mut (*self.node.pointer()).element } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> InPlace for BackPlace<'a, T> { - type Owner = (); - - unsafe fn finalize(self) { - let BackPlace { list, node } = self; - list.push_back_node(finalize(node)); - } -} - // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters. #[allow(dead_code)] fn assert_covariance() { diff --git a/src/liballoc/range.rs b/src/liballoc/range.rs deleted file mode 100644 index f862da0d61e0..000000000000 --- a/src/liballoc/range.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![unstable(feature = "collections_range", - reason = "waiting for dust to settle on inclusive ranges", - issue = "30877")] - -//! Range syntax. - -use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; -use Bound::{self, Excluded, Included, Unbounded}; - -/// `RangeArgument` is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -pub trait RangeArgument { - /// Start index bound. - /// - /// Returns the start value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((..10).start(), Unbounded); - /// assert_eq!((3..10).start(), Included(&3)); - /// # } - /// ``` - fn start(&self) -> Bound<&T>; - - /// End index bound. - /// - /// Returns the end value as a `Bound`. - /// - /// # Examples - /// - /// ``` - /// #![feature(alloc)] - /// #![feature(collections_range)] - /// - /// extern crate alloc; - /// - /// # fn main() { - /// use alloc::range::RangeArgument; - /// use alloc::Bound::*; - /// - /// assert_eq!((3..).end(), Unbounded); - /// assert_eq!((3..10).end(), Excluded(&10)); - /// # } - /// ``` - fn end(&self) -> Bound<&T>; -} - -// FIXME add inclusive ranges to RangeArgument - -impl RangeArgument for RangeFull { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeFrom { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Unbounded - } -} - -impl RangeArgument for RangeTo { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -impl RangeArgument for Range { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Excluded(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeInclusive { - fn start(&self) -> Bound<&T> { - Included(&self.start) - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl RangeArgument for RangeToInclusive { - fn start(&self) -> Bound<&T> { - Unbounded - } - fn end(&self) -> Bound<&T> { - Included(&self.end) - } -} - -impl RangeArgument for (Bound, Bound) { - fn start(&self) -> Bound<&T> { - match *self { - (Included(ref start), _) => Included(start), - (Excluded(ref start), _) => Excluded(start), - (Unbounded, _) => Unbounded, - } - } - - fn end(&self) -> Bound<&T> { - match *self { - (_, Included(ref end)) => Included(end), - (_, Excluded(ref end)) => Excluded(end), - (_, Unbounded) => Unbounded, - } - } -} - -impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { - fn start(&self) -> Bound<&T> { - self.0 - } - - fn end(&self) -> Bound<&T> { - self.1 - } -} diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 621e19069613..3edce8aebdf3 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -9,12 +9,15 @@ // except according to those terms. use core::cmp; +use core::heap::{Alloc, Layout}; use core::mem; use core::ops::Drop; use core::ptr::{self, Unique}; use core::slice; -use heap::{Alloc, Layout, Heap}; +use heap::Heap; use super::boxed::Box; +use super::allocator::CollectionAllocErr; +use super::allocator::CollectionAllocErr::*; /// A low-level utility for more ergonomically allocating, reallocating, and deallocating /// a buffer of memory on the heap without having to worry about all the corner cases @@ -84,7 +87,7 @@ impl RawVec { let elem_size = mem::size_of::(); let alloc_size = cap.checked_mul(elem_size).expect("capacity overflow"); - alloc_guard(alloc_size); + alloc_guard(alloc_size).expect("capacity overflow"); // handles ZSTs and `cap = 0` alike let ptr = if alloc_size == 0 { @@ -308,7 +311,7 @@ impl RawVec { let new_cap = 2 * self.cap; let new_size = new_cap * elem_size; let new_layout = Layout::from_size_align_unchecked(new_size, cur.align()); - alloc_guard(new_size); + alloc_guard(new_size).expect("capacity overflow"); let ptr_res = self.a.realloc(self.ptr.as_ptr() as *mut u8, cur, new_layout); @@ -367,7 +370,7 @@ impl RawVec { // overflow and the alignment is sufficiently small. let new_cap = 2 * self.cap; let new_size = new_cap * elem_size; - alloc_guard(new_size); + alloc_guard(new_size).expect("capacity overflow"); let ptr = self.ptr() as *mut _; let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align()); match self.a.grow_in_place(ptr, old_layout, new_layout) { @@ -403,7 +406,9 @@ impl RawVec { /// # Aborts /// /// Aborts on OOM - pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { + pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) + -> Result<(), CollectionAllocErr> { + unsafe { // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. @@ -413,16 +418,15 @@ impl RawVec { // Don't actually need any more capacity. // Wrapping in case they gave a bad `used_cap`. if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { - return; + return Ok(()); } // Nothing we can really do about these checks :( - let new_cap = used_cap.checked_add(needed_extra_cap).expect("capacity overflow"); - let new_layout = match Layout::array::(new_cap) { - Some(layout) => layout, - None => panic!("capacity overflow"), - }; - alloc_guard(new_layout.size()); + let new_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?; + let new_layout = Layout::array::(new_cap).ok_or(CapacityOverflow)?; + + alloc_guard(new_layout.size())?; + let res = match self.current_layout() { Some(layout) => { let old_ptr = self.ptr.as_ptr() as *mut u8; @@ -430,26 +434,34 @@ impl RawVec { } None => self.a.alloc(new_layout), }; - let uniq = match res { - Ok(ptr) => Unique::new_unchecked(ptr as *mut T), - Err(e) => self.a.oom(e), - }; - self.ptr = uniq; + + self.ptr = Unique::new_unchecked(res? as *mut T); self.cap = new_cap; + + Ok(()) } } + pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { + match self.try_reserve_exact(used_cap, needed_extra_cap) { + Err(CapacityOverflow) => panic!("capacity overflow"), + Err(AllocErr(e)) => self.a.oom(e), + Ok(()) => { /* yay */ } + } + } + /// Calculates the buffer's new size given that it'll hold `used_cap + /// needed_extra_cap` elements. This logic is used in amortized reserve methods. /// Returns `(new_capacity, new_alloc_size)`. - fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize) -> usize { + fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize) + -> Result { + // Nothing we can really do about these checks :( - let required_cap = used_cap.checked_add(needed_extra_cap) - .expect("capacity overflow"); + let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?; // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. let double_cap = self.cap * 2; // `double_cap` guarantees exponential growth. - cmp::max(double_cap, required_cap) + Ok(cmp::max(double_cap, required_cap)) } /// Ensures that the buffer contains at least enough space to hold @@ -504,8 +516,9 @@ impl RawVec { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` - pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { - unsafe { + pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize) + -> Result<(), CollectionAllocErr> { + unsafe { // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to @@ -514,17 +527,15 @@ impl RawVec { // Don't actually need any more capacity. // Wrapping in case they give a bad `used_cap` if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { - return; + return Ok(()); } - let new_cap = self.amortized_new_size(used_cap, needed_extra_cap); + let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)?; + let new_layout = Layout::array::(new_cap).ok_or(CapacityOverflow)?; + + // FIXME: may crash and burn on over-reserve + alloc_guard(new_layout.size())?; - let new_layout = match Layout::array::(new_cap) { - Some(layout) => layout, - None => panic!("capacity overflow"), - }; - // FIXME: may crash and burn on over-reserve - alloc_guard(new_layout.size()); let res = match self.current_layout() { Some(layout) => { let old_ptr = self.ptr.as_ptr() as *mut u8; @@ -532,15 +543,22 @@ impl RawVec { } None => self.a.alloc(new_layout), }; - let uniq = match res { - Ok(ptr) => Unique::new_unchecked(ptr as *mut T), - Err(e) => self.a.oom(e), - }; - self.ptr = uniq; + + self.ptr = Unique::new_unchecked(res? as *mut T); self.cap = new_cap; + + Ok(()) } } + /// The same as try_reserve, but errors are lowered to a call to oom(). + pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { + match self.try_reserve(used_cap, needed_extra_cap) { + Err(CapacityOverflow) => panic!("capacity overflow"), + Err(AllocErr(e)) => self.a.oom(e), + Ok(()) => { /* yay */ } + } + } /// Attempts to ensure that the buffer contains at least enough space to hold /// `used_cap + needed_extra_cap` elements. If it doesn't already have /// enough capacity, will reallocate in place enough space plus comfortable slack @@ -576,7 +594,8 @@ impl RawVec { return false; } - let new_cap = self.amortized_new_size(used_cap, needed_extra_cap); + let new_cap = self.amortized_new_size(used_cap, needed_extra_cap) + .expect("capacity overflow"); // Here, `cap < used_cap + needed_extra_cap <= new_cap` // (regardless of whether `self.cap - used_cap` wrapped). @@ -585,7 +604,7 @@ impl RawVec { let ptr = self.ptr() as *mut _; let new_layout = Layout::new::().repeat(new_cap).unwrap().0; // FIXME: may crash and burn on over-reserve - alloc_guard(new_layout.size()); + alloc_guard(new_layout.size()).expect("capacity overflow"); match self.a.grow_in_place(ptr, old_layout, new_layout) { Ok(_) => { self.cap = new_cap; @@ -709,14 +728,14 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec { // all 4GB in user-space. e.g. PAE or x32 #[inline] -fn alloc_guard(alloc_size: usize) { - if mem::size_of::() < 8 { - assert!(alloc_size <= ::core::isize::MAX as usize, - "capacity overflow"); +fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { + if mem::size_of::() < 8 && alloc_size > ::core::isize::MAX as usize { + Err(CapacityOverflow) + } else { + Ok(()) } } - #[cfg(test)] mod tests { use super::*; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1fa5d34cb578..8bdc57f96a6d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -250,6 +250,7 @@ use core::cell::Cell; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; +use core::heap::{Alloc, Layout}; use core::intrinsics::abort; use core::marker; use core::marker::{Unsize, PhantomData}; @@ -259,7 +260,7 @@ use core::ops::CoerceUnsized; use core::ptr::{self, NonNull}; use core::convert::From; -use heap::{Heap, Alloc, Layout, box_free}; +use heap::{Heap, box_free}; use string::String; use vec::Vec; diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index dc40062ef13d..68f2313843c3 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -102,6 +102,7 @@ use core::mem::size_of; use core::mem; use core::ptr; use core::slice as core_slice; +use core::{u8, u16, u32}; use borrow::{Borrow, BorrowMut, ToOwned}; use boxed::Box; @@ -1302,7 +1303,8 @@ impl [T] { /// Sorts the slice with a key extraction function. /// - /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case. + /// This sort is stable (i.e. does not reorder equal elements) and `O(m n log(m n))` + /// worst-case, where the key function is `O(m)`. /// /// When applicable, unstable sorting is preferred because it is generally faster than stable /// sorting and it doesn't allocate auxiliary memory. @@ -1328,12 +1330,82 @@ impl [T] { /// ``` #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] - pub fn sort_by_key(&mut self, mut f: F) - where F: FnMut(&T) -> B, B: Ord + pub fn sort_by_key(&mut self, mut f: F) + where F: FnMut(&T) -> K, K: Ord { merge_sort(self, |a, b| f(a).lt(&f(b))); } + /// Sorts the slice with a key extraction function. + /// + /// During sorting, the key function is called only once per element. + /// + /// This sort is stable (i.e. does not reorder equal elements) and `O(m n + n log n)` + /// worst-case, where the key function is `O(m)`. + /// + /// For simple key functions (e.g. functions that are property accesses or + /// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be + /// faster. + /// + /// # Current implementation + /// + /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, + /// which combines the fast average case of randomized quicksort with the fast worst case of + /// heapsort, while achieving linear time on slices with certain patterns. It uses some + /// randomization to avoid degenerate cases, but with a fixed seed to always provide + /// deterministic behavior. + /// + /// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the + /// length of the slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_sort_by_cached_key)] + /// let mut v = [-5i32, 4, 32, -3, 2]; + /// + /// v.sort_by_cached_key(|k| k.to_string()); + /// assert!(v == [-3, -5, 2, 32, 4]); + /// ``` + /// + /// [pdqsort]: https://github.com/orlp/pdqsort + #[unstable(feature = "slice_sort_by_cached_key", issue = "34447")] + #[inline] + pub fn sort_by_cached_key(&mut self, f: F) + where F: FnMut(&T) -> K, K: Ord + { + // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. + macro_rules! sort_by_key { + ($t:ty, $slice:ident, $f:ident) => ({ + let mut indices: Vec<_> = + $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); + // The elements of `indices` are unique, as they are indexed, so any sort will be + // stable with respect to the original slice. We use `sort_unstable` here because + // it requires less memory allocation. + indices.sort_unstable(); + for i in 0..$slice.len() { + let mut index = indices[i].1; + while (index as usize) < i { + index = indices[index as usize].1; + } + indices[i].1 = index; + $slice.swap(i, index as usize); + } + }) + } + + let sz_u8 = mem::size_of::<(K, u8)>(); + let sz_u16 = mem::size_of::<(K, u16)>(); + let sz_u32 = mem::size_of::<(K, u32)>(); + let sz_usize = mem::size_of::<(K, usize)>(); + + let len = self.len(); + if sz_u8 < sz_u16 && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } + if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } + if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } + sort_by_key!(usize, self, f) + } + /// Sorts the slice, but may not preserve the order of equal elements. /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), @@ -1410,7 +1482,7 @@ impl [T] { /// elements. /// /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate), - /// and `O(n log n)` worst-case. + /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`. /// /// # Current implementation /// @@ -1420,9 +1492,6 @@ impl [T] { /// randomization to avoid degenerate cases, but with a fixed seed to always provide /// deterministic behavior. /// - /// It is typically faster than stable sorting, except in a few special cases, e.g. when the - /// slice consists of several concatenated sorted sequences. - /// /// # Examples /// /// ``` @@ -1435,9 +1504,8 @@ impl [T] { /// [pdqsort]: https://github.com/orlp/pdqsort #[stable(feature = "sort_unstable", since = "1.20.0")] #[inline] - pub fn sort_unstable_by_key(&mut self, f: F) - where F: FnMut(&T) -> B, - B: Ord + pub fn sort_unstable_by_key(&mut self, f: F) + where F: FnMut(&T) -> K, K: Ord { core_slice::SliceExt::sort_unstable_by_key(self, f); } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 14d5e96d2e73..d5ef41df0d85 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -2122,6 +2122,48 @@ impl str { unsafe { String::from_utf8_unchecked(buf) } } + /// Returns true if this `str` is entirely whitespace, and false otherwise. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived Core + /// Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!(" \t ".is_whitespace()); + /// + /// // a non-breaking space + /// assert!("\u{A0}".is_whitespace()); + /// + /// assert!(!" 越".is_whitespace()); + /// ``` + #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] + #[inline] + pub fn is_whitespace(&self) -> bool { + UnicodeStr::is_whitespace(self) + } + + /// Returns true if this `str` is entirely alphanumeric, and false otherwise. + /// + /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories + /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!("٣7৬Kو藏".is_alphanumeric()); + /// assert!(!"¾①".is_alphanumeric()); + /// ``` + #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")] + #[inline] + pub fn is_alphanumeric(&self) -> bool { + UnicodeStr::is_alphanumeric(self) + } + /// Checks if all characters in this string are within the ASCII range. /// /// # Examples diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 370fb6b4e890..b95aae02894e 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -59,18 +59,18 @@ use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; -use core::ops::{self, Add, AddAssign, Index, IndexMut}; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds}; use core::ptr; use core::str::pattern::Pattern; use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; -use range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; +use super::allocator::CollectionAllocErr; /// A UTF-8 encoded, growable string. /// @@ -920,6 +920,79 @@ impl String { self.vec.reserve_exact(additional) } + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `String`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::CollectionAllocErr; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.vec.try_reserve(additional) + } + + /// Tries to reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `String`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::CollectionAllocErr; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.vec.try_reserve_exact(additional) + } + /// Shrinks the capacity of this `String` to match its length. /// /// # Examples @@ -941,6 +1014,34 @@ impl String { self.vec.shrink_to_fit() } + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + /// Appends the given [`char`] to the end of this `String`. /// /// [`char`]: ../../std/primitive.char.html @@ -1103,8 +1204,6 @@ impl String { /// # Examples /// /// ``` - /// #![feature(string_retain)] - /// /// let mut s = String::from("f_o_ob_ar"); /// /// s.retain(|c| c != '_'); @@ -1112,7 +1211,7 @@ impl String { /// assert_eq!(s, "foobar"); /// ``` #[inline] - #[unstable(feature = "string_retain", issue = "43874")] + #[stable(feature = "string_retain", since = "1.26.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(char) -> bool { @@ -1384,7 +1483,7 @@ impl String { /// ``` #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: RangeBounds { // Memory safety // @@ -1418,7 +1517,7 @@ impl String { } } - /// Creates a splicing iterator that removes the specified range in the string, + /// Removes the specified range in the string, /// and replaces it with the given string. /// The given string doesn't need to be the same length as the range. /// @@ -1438,21 +1537,20 @@ impl String { /// Basic usage: /// /// ``` - /// #![feature(splice)] /// let mut s = String::from("α is alpha, β is beta"); /// let beta_offset = s.find('β').unwrap_or(s.len()); /// /// // Replace the range up until the β from the string - /// s.splice(..beta_offset, "Α is capital alpha; "); + /// s.replace_range(..beta_offset, "Α is capital alpha; "); /// assert_eq!(s, "Α is capital alpha; β is beta"); /// ``` - #[unstable(feature = "splice", reason = "recently added", issue = "44643")] - pub fn splice(&mut self, range: R, replace_with: &str) - where R: RangeArgument + #[stable(feature = "splice", since = "1.27.0")] + pub fn replace_range(&mut self, range: R, replace_with: &str) + where R: RangeBounds { // Memory safety // - // The String version of Splice does not have the memory safety issues + // Replace_range does not have the memory safety issues of a vector Splice. // of the vector version. The data is just plain bytes. match range.start() { @@ -1502,7 +1600,6 @@ impl FromUtf8Error { /// Basic usage: /// /// ``` - /// #![feature(from_utf8_error_as_bytes)] /// // some invalid bytes, in a vector /// let bytes = vec![0, 159]; /// @@ -1510,7 +1607,7 @@ impl FromUtf8Error { /// /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); /// ``` - #[unstable(feature = "from_utf8_error_as_bytes", reason = "recently added", issue = "40895")] + #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -1876,7 +1973,7 @@ impl ops::Index for String { unsafe { str::from_utf8_unchecked(&self.vec) } } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::Index> for String { type Output = str; @@ -1885,7 +1982,7 @@ impl ops::Index> for String { Index::index(&**self, index) } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::Index> for String { type Output = str; @@ -1923,14 +2020,14 @@ impl ops::IndexMut for String { unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { IndexMut::index_mut(&mut **self, index) } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index 06d585f8ea82..8494463463cb 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::panic; +use std::cmp; use std::collections::BinaryHeap; use std::collections::binary_heap::{Drain, PeekMut}; +use std::panic::{self, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + +use rand::{thread_rng, Rng}; #[test] fn test_iterator() { @@ -274,29 +278,86 @@ fn test_extend_specialization() { assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); } -#[test] -fn test_placement() { - let mut a = BinaryHeap::new(); - &mut a <- 2; - &mut a <- 4; - &mut a <- 3; - assert_eq!(a.peek(), Some(&4)); - assert_eq!(a.len(), 3); - &mut a <- 1; - assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]); -} - -#[test] -fn test_placement_panic() { - let mut heap = BinaryHeap::from(vec![1, 2, 3]); - fn mkpanic() -> usize { panic!() } - let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); })); - assert_eq!(heap.len(), 3); -} - #[allow(dead_code)] fn assert_covariance() { fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d } } + +// old binaryheap failed this test +// +// Integrity means that all elements are present after a comparison panics, +// even if the order may not be correct. +// +// Destructors must be called exactly once per element. +#[test] +fn panic_safe() { + static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + + #[derive(Eq, PartialEq, Ord, Clone, Debug)] + struct PanicOrd(T, bool); + + impl Drop for PanicOrd { + fn drop(&mut self) { + // update global drop count + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } + } + + impl PartialOrd for PanicOrd { + fn partial_cmp(&self, other: &Self) -> Option { + if self.1 || other.1 { + panic!("Panicking comparison"); + } + self.0.partial_cmp(&other.0) + } + } + let mut rng = thread_rng(); + const DATASZ: usize = 32; + const NTEST: usize = 10; + + // don't use 0 in the data -- we want to catch the zeroed-out case. + let data = (1..DATASZ + 1).collect::>(); + + // since it's a fuzzy test, run several tries. + for _ in 0..NTEST { + for i in 1..DATASZ + 1 { + DROP_COUNTER.store(0, Ordering::SeqCst); + + let mut panic_ords: Vec<_> = data.iter() + .filter(|&&x| x != i) + .map(|&x| PanicOrd(x, false)) + .collect(); + let panic_item = PanicOrd(i, true); + + // heapify the sane items + rng.shuffle(&mut panic_ords); + let mut heap = BinaryHeap::from(panic_ords); + let inner_data; + + { + // push the panicking item to the heap and catch the panic + let thread_result = { + let mut heap_ref = AssertUnwindSafe(&mut heap); + panic::catch_unwind(move || { + heap_ref.push(panic_item); + }) + }; + assert!(thread_result.is_err()); + + // Assert no elements were dropped + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert!(drops == 0, "Must not drop items. drops={}", drops); + inner_data = heap.clone().into_vec(); + drop(heap); + } + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert_eq!(drops, DATASZ); + + let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::>(); + data_sorted.sort(); + assert_eq!(data_sorted, data); + } + } +} diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 2393101040d9..6ebdb86cc4a9 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -9,8 +9,8 @@ // except according to those terms. use std::collections::BTreeMap; -use std::collections::Bound::{self, Excluded, Included, Unbounded}; use std::collections::btree_map::Entry::{Occupied, Vacant}; +use std::ops::Bound::{self, Excluded, Included, Unbounded}; use std::rc::Rc; use std::iter::FromIterator; diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 168dbb2ce9b1..1a49fb9964ad 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -14,21 +14,22 @@ #![feature(alloc_system)] #![feature(attr_literals)] #![feature(box_syntax)] -#![feature(inclusive_range_syntax)] -#![feature(collection_placement)] +#![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(const_fn)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(iterator_step_by)] #![feature(pattern)] -#![feature(placement_in_syntax)] #![feature(rand)] +#![feature(slice_sort_by_cached_key)] #![feature(splice)] #![feature(str_escape)] #![feature(string_retain)] +#![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(exact_chunks)] +#![feature(inclusive_range_fields)] extern crate alloc_system; extern crate std_unicode; diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 1a9d26fd1a29..99d9c51efc75 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -8,9 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cell::Cell; use std::cmp::Ordering::{Equal, Greater, Less}; +use std::cmp::Ordering; use std::mem; +use std::panic; use std::rc::Rc; +use std::sync::atomic::Ordering::Relaxed; +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; +use std::thread; use rand::{Rng, thread_rng}; @@ -419,6 +425,14 @@ fn test_sort() { v.sort_by(|a, b| b.cmp(a)); assert!(v.windows(2).all(|w| w[0] >= w[1])); + // Sort in lexicographic order. + let mut v1 = orig.clone(); + let mut v2 = orig.clone(); + v1.sort_by_key(|x| x.to_string()); + v2.sort_by_cached_key(|x| x.to_string()); + assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); + assert!(v1 == v2); + // Sort with many pre-sorted runs. let mut v = orig.clone(); v.sort(); @@ -471,7 +485,7 @@ fn test_sort_stability() { // the second item represents which occurrence of that // number this element is, i.e. the second elements // will occur in sorted order. - let mut v: Vec<_> = (0..len) + let mut orig: Vec<_> = (0..len) .map(|_| { let n = thread_rng().gen::() % 10; counts[n] += 1; @@ -479,16 +493,21 @@ fn test_sort_stability() { }) .collect(); - // only sort on the first element, so an unstable sort + let mut v = orig.clone(); + // Only sort on the first element, so an unstable sort // may mix up the counts. v.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - // this comparison includes the count (the second item + // This comparison includes the count (the second item // of the tuple), so elements with equal first items // will need to be ordered with increasing // counts... i.e. exactly asserting that this sort is // stable. assert!(v.windows(2).all(|w| w[0] <= w[1])); + + let mut v = orig.clone(); + v.sort_by_cached_key(|&(x, _)| x); + assert!(v.windows(2).all(|w| w[0] <= w[1])); } } } @@ -1341,3 +1360,162 @@ fn test_copy_from_slice_dst_shorter() { let mut dst = [0; 3]; dst.copy_from_slice(&src); } + +const MAX_LEN: usize = 80; + +static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ + // FIXME(RFC 1109): AtomicUsize is not Copy. + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), +]; + +static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT; + +#[derive(Clone, Eq)] +struct DropCounter { + x: u32, + id: usize, + version: Cell, +} + +impl PartialEq for DropCounter { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other) == Some(Ordering::Equal) + } +} + +impl PartialOrd for DropCounter { + fn partial_cmp(&self, other: &Self) -> Option { + self.version.set(self.version.get() + 1); + other.version.set(other.version.get() + 1); + VERSIONS.fetch_add(2, Relaxed); + self.x.partial_cmp(&other.x) + } +} + +impl Ord for DropCounter { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } +} + +impl Drop for DropCounter { + fn drop(&mut self) { + DROP_COUNTS[self.id].fetch_add(1, Relaxed); + VERSIONS.fetch_sub(self.version.get(), Relaxed); + } +} + +macro_rules! test { + ($input:ident, $func:ident) => { + let len = $input.len(); + + // Work out the total number of comparisons required to sort + // this array... + let mut count = 0usize; + $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) }); + + // ... and then panic on each and every single one. + for panic_countdown in 0..count { + // Refresh the counters. + VERSIONS.store(0, Relaxed); + for i in 0..len { + DROP_COUNTS[i].store(0, Relaxed); + } + + let v = $input.to_owned(); + let _ = thread::spawn(move || { + let mut v = v; + let mut panic_countdown = panic_countdown; + v.$func(|a, b| { + if panic_countdown == 0 { + SILENCE_PANIC.with(|s| s.set(true)); + panic!(); + } + panic_countdown -= 1; + a.cmp(b) + }) + }).join(); + + // Check that the number of things dropped is exactly + // what we expect (i.e. the contents of `v`). + for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { + let count = c.load(Relaxed); + assert!(count == 1, + "found drop count == {} for i == {}, len == {}", + count, i, len); + } + + // Check that the most recent versions of values were dropped. + assert_eq!(VERSIONS.load(Relaxed), 0); + } + } +} + +thread_local!(static SILENCE_PANIC: Cell = Cell::new(false)); + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] // no threads +fn panic_safe() { + let prev = panic::take_hook(); + panic::set_hook(Box::new(move |info| { + if !SILENCE_PANIC.with(|s| s.get()) { + prev(info); + } + })); + + let mut rng = thread_rng(); + + for len in (1..20).chain(70..MAX_LEN) { + for &modulus in &[5, 20, 50] { + for &has_runs in &[false, true] { + let mut input = (0..len) + .map(|id| { + DropCounter { + x: rng.next_u32() % modulus, + id: id, + version: Cell::new(0), + } + }) + .collect::>(); + + if has_runs { + for c in &mut input { + c.x = c.id as u32; + } + + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + input[a..b].reverse(); + } else { + input.swap(a, b); + } + } + } + + test!(input, sort_by); + test!(input, sort_unstable_by); + } + } + } +} diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index ef6f5e10a72d..cb4a17a22d8a 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -9,6 +9,9 @@ // except according to those terms. use std::borrow::Cow; +use std::collections::CollectionAllocErr::*; +use std::mem::size_of; +use std::{usize, isize}; pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { fn into_cow(self) -> Cow<'a, B>; @@ -440,53 +443,53 @@ fn test_drain() { } #[test] -fn test_splice() { +fn test_replace_range() { let mut s = "Hello, world!".to_owned(); - s.splice(7..12, "世界"); + s.replace_range(7..12, "世界"); assert_eq!(s, "Hello, 世界!"); } #[test] #[should_panic] -fn test_splice_char_boundary() { +fn test_replace_range_char_boundary() { let mut s = "Hello, 世界!".to_owned(); - s.splice(..8, ""); + s.replace_range(..8, ""); } #[test] -fn test_splice_inclusive_range() { +fn test_replace_range_inclusive_range() { let mut v = String::from("12345"); - v.splice(2..=3, "789"); + v.replace_range(2..=3, "789"); assert_eq!(v, "127895"); - v.splice(1..=2, "A"); + v.replace_range(1..=2, "A"); assert_eq!(v, "1A895"); } #[test] #[should_panic] -fn test_splice_out_of_bounds() { +fn test_replace_range_out_of_bounds() { let mut s = String::from("12345"); - s.splice(5..6, "789"); + s.replace_range(5..6, "789"); } #[test] #[should_panic] -fn test_splice_inclusive_out_of_bounds() { +fn test_replace_range_inclusive_out_of_bounds() { let mut s = String::from("12345"); - s.splice(5..=5, "789"); + s.replace_range(5..=5, "789"); } #[test] -fn test_splice_empty() { +fn test_replace_range_empty() { let mut s = String::from("12345"); - s.splice(1..2, ""); + s.replace_range(1..2, ""); assert_eq!(s, "1345"); } #[test] -fn test_splice_unbounded() { +fn test_replace_range_unbounded() { let mut s = String::from("12345"); - s.splice(.., ""); + s.replace_range(.., ""); assert_eq!(s, ""); } @@ -504,3 +507,163 @@ fn test_into_boxed_str() { let ys = xs.into_boxed_str(); assert_eq!(&*ys, "hello my name is bob"); } + +#[test] +fn test_reserve_exact() { + // This is all the same as test_reserve + + let mut s = String::new(); + assert_eq!(s.capacity(), 0); + + s.reserve_exact(2); + assert!(s.capacity() >= 2); + + for _i in 0..16 { + s.push('0'); + } + + assert!(s.capacity() >= 16); + s.reserve_exact(16); + assert!(s.capacity() >= 32); + + s.push('0'); + + s.reserve_exact(16); + assert!(s.capacity() >= 33) +} + +#[test] +fn test_try_reserve() { + + // These are the interesting cases: + // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) + // * > isize::MAX should always fail + // * On 16/32-bit should CapacityOverflow + // * On 64-bit should OOM + // * overflow may trigger when adding `len` to `cap` (in number of elements) + // * overflow may trigger when multiplying `new_cap` by size_of:: (to get bytes) + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + // On 16/32-bit, we check that allocations don't exceed isize::MAX, + // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. + // Any platform that succeeds for these requests is technically broken with + // ptr::offset because LLVM is the worst. + let guards_against_isize = size_of::() < 8; + + { + // Note: basic stuff is checked by test_reserve + let mut empty_string: String = String::new(); + + // Check isize::MAX doesn't count as an overflow + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + // Play it again, frank! (just to be sure) + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + // Check isize::MAX + 1 does count as overflow + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an overflow!") } + + // Check usize::MAX does count as overflow + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } else { + // Check isize::MAX + 1 is an OOM + if let Err(AllocErr(_)) = empty_string.try_reserve(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + + // Check usize::MAX is an OOM + if let Err(AllocErr(_)) = empty_string.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an OOM!") } + } + } + + + { + // Same basic idea, but with non-zero len + let mut ten_bytes: String = String::from("0123456789"); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + // Should always overflow in the add-to-len + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + +} + +#[test] +fn test_try_reserve_exact() { + + // This is exactly the same as test_try_reserve with the method changed. + // See that test for comments. + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + let guards_against_isize = size_of::() < 8; + + { + let mut empty_string: String = String::new(); + + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an overflow!") } + + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } else { + if let Err(AllocErr(_)) = empty_string.try_reserve_exact(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + + if let Err(AllocErr(_)) = empty_string.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an OOM!") } + } + } + + + { + let mut ten_bytes: String = String::from("0123456789"); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + +} diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 9cfde5dcc73c..2895c53009d9 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -10,8 +10,9 @@ use std::borrow::Cow; use std::mem::size_of; -use std::panic; +use std::{usize, isize}; use std::vec::{Drain, IntoIter}; +use std::collections::CollectionAllocErr::*; struct DropCounter<'a> { count: &'a mut u32, @@ -752,24 +753,6 @@ fn assert_covariance() { } } -#[test] -fn test_placement() { - let mut vec = vec![1]; - assert_eq!(vec.place_back() <- 2, &2); - assert_eq!(vec.len(), 2); - assert_eq!(vec.place_back() <- 3, &3); - assert_eq!(vec.len(), 3); - assert_eq!(&vec, &[1, 2, 3]); -} - -#[test] -fn test_placement_panic() { - let mut vec = vec![1, 2, 3]; - fn mkpanic() -> usize { panic!() } - let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); })); - assert_eq!(vec.len(), 3); -} - #[test] fn from_into_inner() { let vec = vec![1, 2, 3]; @@ -965,3 +948,209 @@ fn drain_filter_complex() { assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); } } + +#[test] +fn test_reserve_exact() { + // This is all the same as test_reserve + + let mut v = Vec::new(); + assert_eq!(v.capacity(), 0); + + v.reserve_exact(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push(i); + } + + assert!(v.capacity() >= 16); + v.reserve_exact(16); + assert!(v.capacity() >= 32); + + v.push(16); + + v.reserve_exact(16); + assert!(v.capacity() >= 33) +} + +#[test] +fn test_try_reserve() { + + // These are the interesting cases: + // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) + // * > isize::MAX should always fail + // * On 16/32-bit should CapacityOverflow + // * On 64-bit should OOM + // * overflow may trigger when adding `len` to `cap` (in number of elements) + // * overflow may trigger when multiplying `new_cap` by size_of:: (to get bytes) + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + // On 16/32-bit, we check that allocations don't exceed isize::MAX, + // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. + // Any platform that succeeds for these requests is technically broken with + // ptr::offset because LLVM is the worst. + let guards_against_isize = size_of::() < 8; + + { + // Note: basic stuff is checked by test_reserve + let mut empty_bytes: Vec = Vec::new(); + + // Check isize::MAX doesn't count as an overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + // Play it again, frank! (just to be sure) + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + // Check isize::MAX + 1 does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an overflow!") } + + // Check usize::MAX does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } else { + // Check isize::MAX + 1 is an OOM + if let Err(AllocErr(_)) = empty_bytes.try_reserve(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + + // Check usize::MAX is an OOM + if let Err(AllocErr(_)) = empty_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an OOM!") } + } + } + + + { + // Same basic idea, but with non-zero len + let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + // Should always overflow in the add-to-len + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + + + { + // Same basic idea, but with interesting type size + let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + // Should fail in the mul-by-size + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { + } else { + panic!("usize::MAX should trigger an overflow!"); + } + } + +} + +#[test] +fn test_try_reserve_exact() { + + // This is exactly the same as test_try_reserve with the method changed. + // See that test for comments. + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + let guards_against_isize = size_of::() < 8; + + { + let mut empty_bytes: Vec = Vec::new(); + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an overflow!") } + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } else { + if let Err(AllocErr(_)) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + + if let Err(AllocErr(_)) = empty_bytes.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an OOM!") } + } + } + + + { + let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + + + { + let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + +} diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index f2935c05d4f7..75d3f01f8b60 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -11,6 +11,9 @@ use std::collections::VecDeque; use std::fmt::Debug; use std::collections::vec_deque::{Drain}; +use std::collections::CollectionAllocErr::*; +use std::mem::size_of; +use std::{usize, isize}; use self::Taggy::*; use self::Taggypar::*; @@ -1002,23 +1005,206 @@ fn test_is_empty() { } #[test] -fn test_placement_in() { - let mut buf: VecDeque = VecDeque::new(); - buf.place_back() <- 1; - buf.place_back() <- 2; - assert_eq!(buf, [1,2]); +fn test_reserve_exact_2() { + // This is all the same as test_reserve - buf.place_front() <- 3; - buf.place_front() <- 4; - assert_eq!(buf, [4,3,1,2]); + let mut v = VecDeque::new(); - { - let ptr_head = buf.place_front() <- 5; - assert_eq!(*ptr_head, 5); + v.reserve_exact(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push_back(i); } - { - let ptr_tail = buf.place_back() <- 6; - assert_eq!(*ptr_tail, 6); - } - assert_eq!(buf, [5,4,3,1,2,6]); + + assert!(v.capacity() >= 16); + v.reserve_exact(16); + assert!(v.capacity() >= 32); + + v.push_back(16); + + v.reserve_exact(16); + assert!(v.capacity() >= 48) +} + +#[test] +fn test_try_reserve() { + + // These are the interesting cases: + // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) + // * > isize::MAX should always fail + // * On 16/32-bit should CapacityOverflow + // * On 64-bit should OOM + // * overflow may trigger when adding `len` to `cap` (in number of elements) + // * overflow may trigger when multiplying `new_cap` by size_of:: (to get bytes) + + const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1; + const MAX_USIZE: usize = usize::MAX; + + // On 16/32-bit, we check that allocations don't exceed isize::MAX, + // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. + // Any platform that succeeds for these requests is technically broken with + // ptr::offset because LLVM is the worst. + let guards_against_isize = size_of::() < 8; + + { + // Note: basic stuff is checked by test_reserve + let mut empty_bytes: VecDeque = VecDeque::new(); + + // Check isize::MAX doesn't count as an overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + // Play it again, frank! (just to be sure) + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + // Check isize::MAX + 1 does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an overflow!") } + + // Check usize::MAX does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } else { + // Check isize::MAX is an OOM + // VecDeque starts with capacity 7, always adds 1 to the capacity + // and also rounds the number to next power of 2 so this is the + // furthest we can go without triggering CapacityOverflow + if let Err(AllocErr(_)) = empty_bytes.try_reserve(MAX_CAP) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + } + + + { + // Same basic idea, but with non-zero len + let mut ten_bytes: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + // Should always overflow in the add-to-len + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + + + { + // Same basic idea, but with interesting type size + let mut ten_u32s: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + // Should fail in the mul-by-size + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { + } else { + panic!("usize::MAX should trigger an overflow!"); + } + } + +} + +#[test] +fn test_try_reserve_exact() { + + // This is exactly the same as test_try_reserve with the method changed. + // See that test for comments. + + const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1; + const MAX_USIZE: usize = usize::MAX; + + let guards_against_isize = size_of::() < 8; + + { + let mut empty_bytes: VecDeque = VecDeque::new(); + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + } else { panic!("isize::MAX + 1 should trigger an overflow!") } + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } else { + // Check isize::MAX is an OOM + // VecDeque starts with capacity 7, always adds 1 to the capacity + // and also rounds the number to next power of 2 so this is the + // furthest we can go without triggering CapacityOverflow + if let Err(AllocErr(_)) = empty_bytes.try_reserve_exact(MAX_CAP) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + } + + + { + let mut ten_bytes: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + + + { + let mut ten_u32s: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + if let Err(AllocErr(_)) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { + } else { panic!("usize::MAX should trigger an overflow!") } + } + } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 2f57c53a6d83..4b883b5bce79 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -66,7 +66,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::cmp::Ordering; +use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; @@ -75,7 +75,8 @@ use core::marker::PhantomData; use core::mem; #[cfg(not(test))] use core::num::Float; -use core::ops::{InPlace, Index, IndexMut, Place, Placer}; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{Index, IndexMut, RangeBounds}; use core::ops; use core::ptr; use core::ptr::NonNull; @@ -85,8 +86,7 @@ use borrow::ToOwned; use borrow::Cow; use boxed::Box; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; +use super::allocator::CollectionAllocErr; /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// @@ -333,9 +333,10 @@ impl Vec { /// The vector will be able to hold exactly `capacity` elements without /// reallocating. If `capacity` is 0, the vector will not allocate. /// - /// It is important to note that this function does not specify the *length* - /// of the returned vector, but only the *capacity*. For an explanation of - /// the difference between length and capacity, see *[Capacity and reallocation]*. + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. /// /// [Capacity and reallocation]: #capacity-and-reallocation /// @@ -489,6 +490,83 @@ impl Vec { self.buf.reserve_exact(self.len, additional); } + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::CollectionAllocErr; + /// + /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.buf.try_reserve(self.len, additional) + } + + /// Tries to reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::CollectionAllocErr; + /// + /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.buf.try_reserve_exact(self.len, additional) + } + /// Shrinks the capacity of the vector as much as possible. /// /// It will drop down as close as possible to the length but the allocator @@ -508,6 +586,31 @@ impl Vec { self.buf.shrink_to_fit(self.len); } + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Note that this will drop any excess capacity. @@ -962,29 +1065,6 @@ impl Vec { } } - /// Returns a place for insertion at the back of the `Vec`. - /// - /// Using this method with placement syntax is equivalent to [`push`](#method.push), - /// but may be more efficient. - /// - /// # Examples - /// - /// ``` - /// #![feature(collection_placement)] - /// #![feature(placement_in_syntax)] - /// - /// let mut vec = vec![1, 2]; - /// vec.place_back() <- 3; - /// vec.place_back() <- 4; - /// assert_eq!(&vec, &[1, 2, 3, 4]); - /// ``` - #[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] - pub fn place_back(&mut self) -> PlaceBack { - PlaceBack { vec: self } - } - /// Removes the last element from a vector and returns it, or [`None`] if it /// is empty. /// @@ -1072,7 +1152,7 @@ impl Vec { /// ``` #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: RangeBounds { // Memory safety // @@ -1203,6 +1283,49 @@ impl Vec { } other } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with the result of + /// calling the closure `f`. The return values from `f` will end up + /// in the `Vec` in the order they have been generated. + /// + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses a closure to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`resize`]. If you want + /// to use the [`Default`] trait to generate values, you can pass + /// [`Default::default()`] as the second argument.. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_resize_with)] + /// + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_with(5, Default::default); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![]; + /// let mut p = 1; + /// vec.resize_with(4, || { p *= 2; p }); + /// assert_eq!(vec, [2, 4, 8, 16]); + /// ``` + /// + /// [`resize`]: #method.resize + /// [`Clone`]: ../../std/clone/trait.Clone.html + #[unstable(feature = "vec_resize_with", issue = "41758")] + pub fn resize_with(&mut self, new_len: usize, f: F) + where F: FnMut() -> T + { + let len = self.len(); + if new_len > len { + self.extend_with(new_len - len, ExtendFunc(f)); + } else { + self.truncate(new_len); + } + } } impl Vec { @@ -1212,8 +1335,9 @@ impl Vec { /// difference, with each additional slot filled with `value`. /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// - /// This method requires `Clone` to clone the passed value. If you'd - /// rather create a value with `Default` instead, see [`resize_default`]. + /// This method requires [`Clone`] to be able clone the passed value. If + /// you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`resize_with`]. /// /// # Examples /// @@ -1227,7 +1351,9 @@ impl Vec { /// assert_eq!(vec, [1, 2]); /// ``` /// - /// [`resize_default`]: #method.resize_default + /// [`Clone`]: ../../std/clone/trait.Clone.html + /// [`Default`]: ../../std/default/trait.Default.html + /// [`resize_with`]: #method.resize_with #[stable(feature = "vec_resize", since = "1.5.0")] pub fn resize(&mut self, new_len: usize, value: T) { let len = self.len(); @@ -1244,7 +1370,7 @@ impl Vec { /// Iterates over the slice `other`, clones each element, and then appends /// it to this `Vec`. The `other` vector is traversed in-order. /// - /// Note that this function is same as `extend` except that it is + /// Note that this function is same as [`extend`] except that it is /// specialized to work with slices instead. If and when Rust gets /// specialization this function will likely be deprecated (but still /// available). @@ -1256,6 +1382,8 @@ impl Vec { /// vec.extend_from_slice(&[2, 3, 4]); /// assert_eq!(vec, [1, 2, 3, 4]); /// ``` + /// + /// [`extend`]: #method.extend #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] pub fn extend_from_slice(&mut self, other: &[T]) { self.spec_extend(other.iter()) @@ -1266,12 +1394,11 @@ impl Vec { /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the - /// difference, with each additional slot filled with `Default::default()`. + /// difference, with each additional slot filled with [`Default::default()`]. /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// - /// This method uses `Default` to create new values on every push. If - /// you'd rather `Clone` a given value, use [`resize`]. - /// + /// This method uses [`Default`] to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`resize`]. /// /// # Examples /// @@ -1288,6 +1415,9 @@ impl Vec { /// ``` /// /// [`resize`]: #method.resize + /// [`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default + /// [`Default`]: ../../std/default/trait.Default.html + /// [`Clone`]: ../../std/clone/trait.Clone.html #[unstable(feature = "vec_resize_default", issue = "41758")] pub fn resize_default(&mut self, new_len: usize) { let len = self.len(); @@ -1302,24 +1432,31 @@ impl Vec { // This code generalises `extend_with_{element,default}`. trait ExtendWith { - fn next(&self) -> T; + fn next(&mut self) -> T; fn last(self) -> T; } struct ExtendElement(T); impl ExtendWith for ExtendElement { - fn next(&self) -> T { self.0.clone() } + fn next(&mut self) -> T { self.0.clone() } fn last(self) -> T { self.0 } } struct ExtendDefault; impl ExtendWith for ExtendDefault { - fn next(&self) -> T { Default::default() } + fn next(&mut self) -> T { Default::default() } fn last(self) -> T { Default::default() } } + +struct ExtendFunc(F); +impl T> ExtendWith for ExtendFunc { + fn next(&mut self) -> T { (self.0)() } + fn last(mut self) -> T { (self.0)() } +} + impl Vec { /// Extend the vector by `n` values, using the given generator. - fn extend_with>(&mut self, n: usize, value: E) { + fn extend_with>(&mut self, n: usize, mut value: E) { self.reserve(n); unsafe { @@ -1457,40 +1594,69 @@ impl SpecFromElem for u8 { } } -macro_rules! impl_spec_from_elem { - ($t: ty, $is_zero: expr) => { - impl SpecFromElem for $t { - #[inline] - fn from_elem(elem: $t, n: usize) -> Vec<$t> { - if $is_zero(elem) { - return Vec { - buf: RawVec::with_capacity_zeroed(n), - len: n, - } - } - let mut v = Vec::with_capacity(n); - v.extend_with(n, ExtendElement(elem)); - v +impl SpecFromElem for T { + #[inline] + fn from_elem(elem: T, n: usize) -> Vec { + if elem.is_zero() { + return Vec { + buf: RawVec::with_capacity_zeroed(n), + len: n, } } - }; + let mut v = Vec::with_capacity(n); + v.extend_with(n, ExtendElement(elem)); + v + } } -impl_spec_from_elem!(i8, |x| x == 0); -impl_spec_from_elem!(i16, |x| x == 0); -impl_spec_from_elem!(i32, |x| x == 0); -impl_spec_from_elem!(i64, |x| x == 0); -impl_spec_from_elem!(i128, |x| x == 0); -impl_spec_from_elem!(isize, |x| x == 0); +unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} -impl_spec_from_elem!(u16, |x| x == 0); -impl_spec_from_elem!(u32, |x| x == 0); -impl_spec_from_elem!(u64, |x| x == 0); -impl_spec_from_elem!(u128, |x| x == 0); -impl_spec_from_elem!(usize, |x| x == 0); +macro_rules! impl_is_zero { + ($t: ty, $is_zero: expr) => { + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + $is_zero(*self) + } + } + } +} + +impl_is_zero!(i8, |x| x == 0); +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} -impl_spec_from_elem!(f32, |x: f32| x == 0. && x.is_sign_positive()); -impl_spec_from_elem!(f64, |x: f64| x == 0. && x.is_sign_positive()); //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec @@ -1839,7 +2005,7 @@ impl Vec { #[inline] #[stable(feature = "vec_splice", since = "1.21.0")] pub fn splice(&mut self, range: R, replace_with: I) -> Splice - where R: RangeArgument, I: IntoIterator + where R: RangeBounds, I: IntoIterator { Splice { drain: self.drain(range), @@ -2382,57 +2548,6 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> { #[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Drain<'a, T> {} -/// A place for insertion at the back of a `Vec`. -/// -/// See [`Vec::place_back`](struct.Vec.html#method.place_back) for details. -#[must_use = "places do nothing unless written to with `<-` syntax"] -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -#[derive(Debug)] -pub struct PlaceBack<'a, T: 'a> { - vec: &'a mut Vec, -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> Placer for PlaceBack<'a, T> { - type Place = PlaceBack<'a, T>; - - fn make_place(self) -> Self { - // This will panic or abort if we would allocate > isize::MAX bytes - // or if the length increment would overflow for zero-sized types. - if self.vec.len == self.vec.buf.cap() { - self.vec.buf.double(); - } - self - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, T> Place for PlaceBack<'a, T> { - fn pointer(&mut self) -> *mut T { - unsafe { self.vec.as_mut_ptr().offset(self.vec.len as isize) } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> InPlace for PlaceBack<'a, T> { - type Owner = &'a mut T; - - unsafe fn finalize(mut self) -> &'a mut T { - let ptr = self.pointer(); - self.vec.len += 1; - &mut *ptr - } -} - - /// A splicing iterator for `Vec`. /// /// This struct is created by the [`splice()`] method on [`Vec`]. See its diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 68add3cbd51f..f28c8e389967 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -21,7 +21,8 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; -use core::ops::{Index, IndexMut, Place, Placer, InPlace}; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{Index, IndexMut, RangeBounds}; use core::ptr; use core::ptr::NonNull; use core::slice; @@ -31,8 +32,7 @@ use core::cmp; use raw_vec::RawVec; -use super::range::RangeArgument; -use Bound::{Excluded, Included, Unbounded}; +use super::allocator::CollectionAllocErr; use super::vec::Vec; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 @@ -566,6 +566,97 @@ impl VecDeque { } } + /// Tries to reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `VecDeque`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::CollectionAllocErr; + /// use std::collections::VecDeque; + /// + /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// let mut output = VecDeque::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + self.try_reserve(additional) + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `VecDeque`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::CollectionAllocErr; + /// use std::collections::VecDeque; + /// + /// fn process_data(data: &[u32]) -> Result, CollectionAllocErr> { + /// let mut output = VecDeque::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + let old_cap = self.cap(); + let used_cap = self.len() + 1; + let new_cap = used_cap.checked_add(additional) + .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) + .ok_or(CollectionAllocErr::CapacityOverflow)?; + + if new_cap > old_cap { + self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; + unsafe { + self.handle_cap_increase(old_cap); + } + } + Ok(()) + } + /// Shrinks the capacity of the `VecDeque` as much as possible. /// /// It will drop down as close as possible to the length but the allocator may still inform the @@ -584,9 +675,42 @@ impl VecDeque { /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn shrink_to_fit(&mut self) { + self.shrink_to(0); + } + + /// Shrinks the capacity of the `VecDeque` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to(6); + /// assert!(buf.capacity() >= 6); + /// buf.shrink_to(0); + /// assert!(buf.capacity() >= 4); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + // +1 since the ringbuffer always leaves one space empty // len + 1 can't overflow for an existing, well-formed ringbuffer. - let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + let target_cap = cmp::max( + cmp::max(min_capacity, self.len()) + 1, + MINIMUM_CAPACITY + 1 + ).next_power_of_two(); + if target_cap < self.cap() { // There are three cases of interest: // All elements are out of desired bounds @@ -844,7 +968,7 @@ impl VecDeque { #[inline] #[stable(feature = "drain", since = "1.6.0")] pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: RangeBounds { // Memory safety // @@ -1761,56 +1885,6 @@ impl VecDeque { debug_assert!(!self.is_full()); } } - - /// Returns a place for insertion at the back of the `VecDeque`. - /// - /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back), - /// but may be more efficient. - /// - /// # Examples - /// - /// ``` - /// #![feature(collection_placement)] - /// #![feature(placement_in_syntax)] - /// - /// use std::collections::VecDeque; - /// - /// let mut buf = VecDeque::new(); - /// buf.place_back() <- 3; - /// buf.place_back() <- 4; - /// assert_eq!(&buf, &[3, 4]); - /// ``` - #[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] - pub fn place_back(&mut self) -> PlaceBack { - PlaceBack { vec_deque: self } - } - - /// Returns a place for insertion at the front of the `VecDeque`. - /// - /// Using this method with placement syntax is equivalent to [`push_front`](#method.push_front), - /// but may be more efficient. - /// - /// # Examples - /// - /// ``` - /// #![feature(collection_placement)] - /// #![feature(placement_in_syntax)] - /// - /// use std::collections::VecDeque; - /// - /// let mut buf = VecDeque::new(); - /// buf.place_front() <- 3; - /// buf.place_front() <- 4; - /// assert_eq!(&buf, &[4, 3]); - /// ``` - #[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] - pub fn place_front(&mut self) -> PlaceFront { - PlaceFront { vec_deque: self } - } } impl VecDeque { @@ -2538,98 +2612,6 @@ impl From> for Vec { } } -/// A place for insertion at the back of a `VecDeque`. -/// -/// See [`VecDeque::place_back`](struct.VecDeque.html#method.place_back) for details. -#[must_use = "places do nothing unless written to with `<-` syntax"] -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -#[derive(Debug)] -pub struct PlaceBack<'a, T: 'a> { - vec_deque: &'a mut VecDeque, -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> Placer for PlaceBack<'a, T> { - type Place = PlaceBack<'a, T>; - - fn make_place(self) -> Self { - self.vec_deque.grow_if_necessary(); - self - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, T> Place for PlaceBack<'a, T> { - fn pointer(&mut self) -> *mut T { - unsafe { self.vec_deque.ptr().offset(self.vec_deque.head as isize) } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> InPlace for PlaceBack<'a, T> { - type Owner = &'a mut T; - - unsafe fn finalize(self) -> &'a mut T { - let head = self.vec_deque.head; - self.vec_deque.head = self.vec_deque.wrap_add(head, 1); - &mut *(self.vec_deque.ptr().offset(head as isize)) - } -} - -/// A place for insertion at the front of a `VecDeque`. -/// -/// See [`VecDeque::place_front`](struct.VecDeque.html#method.place_front) for details. -#[must_use = "places do nothing unless written to with `<-` syntax"] -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol are subject to change", - issue = "30172")] -#[derive(Debug)] -pub struct PlaceFront<'a, T: 'a> { - vec_deque: &'a mut VecDeque, -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> Placer for PlaceFront<'a, T> { - type Place = PlaceFront<'a, T>; - - fn make_place(self) -> Self { - self.vec_deque.grow_if_necessary(); - self - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, T> Place for PlaceFront<'a, T> { - fn pointer(&mut self) -> *mut T { - let tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1); - unsafe { self.vec_deque.ptr().offset(tail as isize) } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, T> InPlace for PlaceFront<'a, T> { - type Owner = &'a mut T; - - unsafe fn finalize(self) -> &'a mut T { - self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1); - &mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize)) - } -} - #[cfg(test)] mod tests { use test; diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index d7370ae400da..7a8d01e4ef8b 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -15,7 +15,6 @@ form or name", issue = "27783")] #![deny(warnings)] -#![feature(alloc)] #![feature(alloc_system)] #![feature(libc)] #![feature(linkage)] @@ -25,7 +24,6 @@ #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))] #![rustc_alloc_kind = "exe"] -extern crate alloc; extern crate alloc_system; extern crate libc; @@ -35,7 +33,7 @@ pub use contents::*; mod contents { use core::ptr; - use alloc::heap::{Alloc, AllocErr, Layout}; + use core::heap::{Alloc, AllocErr, Layout}; use alloc_system::System; use libc::{c_int, c_void, size_t}; diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 1d5e7b73be55..d4404e564e06 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -17,7 +17,6 @@ issue = "32838")] #![feature(global_allocator)] #![feature(allocator_api)] -#![feature(alloc)] #![feature(core_intrinsics)] #![feature(staged_api)] #![feature(rustc_attrs)] @@ -43,9 +42,7 @@ const MIN_ALIGN: usize = 8; #[allow(dead_code)] const MIN_ALIGN: usize = 16; -extern crate alloc; - -use self::alloc::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace}; +use core::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace}; #[unstable(feature = "allocator_api", issue = "32838")] pub struct System; @@ -125,7 +122,7 @@ mod platform { use MIN_ALIGN; use System; - use alloc::heap::{Alloc, AllocErr, Layout}; + use core::heap::{Alloc, AllocErr, Layout}; #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl<'a> Alloc for &'a System { @@ -134,6 +131,14 @@ mod platform { let ptr = if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else { + #[cfg(target_os = "macos")] + { + if layout.align() > (1 << 31) { + return Err(AllocErr::Unsupported { + details: "requested alignment too large" + }) + } + } aligned_malloc(&layout) }; if !ptr.is_null() { @@ -279,7 +284,7 @@ mod platform { use MIN_ALIGN; use System; - use alloc::heap::{Alloc, AllocErr, Layout, CannotReallocInPlace}; + use core::heap::{Alloc, AllocErr, Layout, CannotReallocInPlace}; type LPVOID = *mut u8; type HANDLE = LPVOID; @@ -491,7 +496,7 @@ mod platform { mod platform { extern crate dlmalloc; - use alloc::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace}; + use core::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace}; use System; use self::dlmalloc::GlobalDlmalloc; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 72fa3148fe54..7eaf67e6ea66 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -27,7 +27,7 @@ #![feature(alloc)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] -#![feature(generic_param_attrs)] +#![cfg_attr(stage0, feature(generic_param_attrs))] #![cfg_attr(test, feature(test))] #![allow(deprecated)] diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 266ea0740a5b..2a2f6d96c8dc 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 266ea0740a5bdd262a38bbd88fb55fc3d2a7a96e +Subproject commit 2a2f6d96c8dc578d2474742f14c9bab0b36b0408 diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index 5af63aa970f2..24529f7a9d8d 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -16,3 +16,6 @@ path = "../libcore/tests/lib.rs" [[bench]] name = "corebenches" path = "../libcore/benches/lib.rs" + +[dev-dependencies] +rand = "0.4" diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd8..87144c27c9e1 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -59,7 +59,7 @@ unsafe impl> FixedSizeArray for A { } /// The error type returned when a conversion from a slice to an array fails. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] #[derive(Debug, Copy, Clone)] pub struct TryFromSliceError(()); @@ -148,7 +148,7 @@ macro_rules! array_impls { } } - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; @@ -162,7 +162,7 @@ macro_rules! array_impls { } } - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { type Error = TryFromSliceError; diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs new file mode 100644 index 000000000000..2c4bccebceb9 --- /dev/null +++ b/src/libcore/ascii.rs @@ -0,0 +1,147 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations on ASCII strings and characters. +//! +//! Most string operations in Rust act on UTF-8 strings. However, at times it +//! makes more sense to only consider the ASCII character set for a specific +//! operation. +//! +//! The [`escape_default`] function provides an iterator over the bytes of an +//! escaped version of the character given. +//! +//! [`escape_default`]: fn.escape_default.html + +#![stable(feature = "core_ascii", since = "1.26.0")] + +use fmt; +use ops::Range; +use iter::FusedIterator; + +/// An iterator over the escaped version of a byte. +/// +/// This `struct` is created by the [`escape_default`] function. See its +/// documentation for more. +/// +/// [`escape_default`]: fn.escape_default.html +#[stable(feature = "core_ascii", since = "1.26.0")] +pub struct EscapeDefault { + range: Range, + data: [u8; 4], +} + +/// Returns an iterator that produces an escaped version of a `u8`. +/// +/// The default is chosen with a bias toward producing literals that are +/// legal in a variety of languages, including C++11 and similar C-family +/// languages. The exact rules are: +/// +/// * Tab is escaped as `\t`. +/// * Carriage return is escaped as `\r`. +/// * Line feed is escaped as `\n`. +/// * Single quote is escaped as `\'`. +/// * Double quote is escaped as `\"`. +/// * Backslash is escaped as `\\`. +/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e` +/// inclusive is not escaped. +/// * Any other chars are given hex escapes of the form '\xNN'. +/// * Unicode escapes are never generated by this function. +/// +/// # Examples +/// +/// ``` +/// use std::ascii; +/// +/// let escaped = ascii::escape_default(b'0').next().unwrap(); +/// assert_eq!(b'0', escaped); +/// +/// let mut escaped = ascii::escape_default(b'\t'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b't', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\r'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'r', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\n'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'n', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\''); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'\'', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'"'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'"', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\\'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// +/// let mut escaped = ascii::escape_default(b'\x9d'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b'x', escaped.next().unwrap()); +/// assert_eq!(b'9', escaped.next().unwrap()); +/// assert_eq!(b'd', escaped.next().unwrap()); +/// ``` +#[stable(feature = "core_ascii", since = "1.26.0")] +pub fn escape_default(c: u8) -> EscapeDefault { + let (data, len) = match c { + b'\t' => ([b'\\', b't', 0, 0], 2), + b'\r' => ([b'\\', b'r', 0, 0], 2), + b'\n' => ([b'\\', b'n', 0, 0], 2), + b'\\' => ([b'\\', b'\\', 0, 0], 2), + b'\'' => ([b'\\', b'\'', 0, 0], 2), + b'"' => ([b'\\', b'"', 0, 0], 2), + b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1), + _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), + }; + + return EscapeDefault { range: 0..len, data }; + + fn hexify(b: u8) -> u8 { + match b { + 0 ... 9 => b'0' + b, + _ => b'a' + b - 10, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for EscapeDefault { + type Item = u8; + fn next(&mut self) -> Option { self.range.next().map(|i| self.data[i]) } + fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for EscapeDefault { + fn next_back(&mut self) -> Option { + self.range.next_back().map(|i| self.data[i]) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for EscapeDefault {} +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for EscapeDefault {} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("EscapeDefault { .. }") + } +} diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index 201064e823b1..c947b003ccbf 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -11,7 +11,6 @@ #![deny(warnings)] #![feature(flt2dec)] -#![feature(slice_patterns)] #![feature(test)] extern crate core; diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 61558034e63e..f45a32d4b94a 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -14,24 +14,154 @@ /// A trait for borrowing data. /// -/// In general, there may be several ways to "borrow" a piece of data. The -/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` -/// (a mutable borrow). But types like `Vec` provide additional kinds of -/// borrows: the borrowed slices `&[T]` and `&mut [T]`. +/// In Rust, it is common to provide different representations of a type for +/// different use cases. For instance, storage location and management for a +/// value can be specifically chosen as appropriate for a particular use via +/// pointer types such as [`Box`] or [`Rc`]. Beyond these generic +/// wrappers that can be used with any type, some types provide optional +/// facets providing potentially costly functionality. An example for such a +/// type is [`String`] which adds the ability to extend a string to the basic +/// [`str`]. This requires keeping additional information unnecessary for a +/// simple, immutable string. /// -/// When writing generic code, it is often desirable to abstract over all ways -/// of borrowing data from a given type. That is the role of the `Borrow` -/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given -/// type can be borrowed as multiple different types. In particular, `Vec: -/// Borrow>` and `Vec: Borrow<[T]>`. +/// These types provide access to the underlying data through references +/// to the type of that data. They are said to be ‘borrowed as’ that type. +/// For instance, a [`Box`] can be borrowed as `T` while a [`String`] +/// can be borrowed as `str`. /// -/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement -/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result. +/// Types express that they can be borrowed as some type `T` by implementing +/// `Borrow`, providing a reference to a `T` in the trait’s +/// [`borrow`] method. A type is free to borrow as several different types. +/// If it wishes to mutably borrow as the type – allowing the underlying data +/// to be modified, it can additionally implement [`BorrowMut`]. /// -/// `Borrow` is very similar to, but different than, `AsRef`. See -/// [the book][book] for more. +/// Further, when providing implementations for additional traits, it needs +/// to be considered whether they should behave identical to those of the +/// underlying type as a consequence of acting as a representation of that +/// underlying type. Generic code typically uses `Borrow` when it relies +/// on the identical behavior of these additional trait implementations. +/// These traits will likely appear as additional trait bounds. /// -/// [book]: ../../book/first-edition/borrow-and-asref.html +/// If generic code merely needs to work for all types that can +/// provide a reference to related type `T`, it is often better to use +/// [`AsRef`] as more types can safely implement it. +/// +/// [`AsRef`]: ../../std/convert/trait.AsRef.html +/// [`BorrowMut`]: trait.BorrowMut.html +/// [`Box`]: ../../std/boxed/struct.Box.html +/// [`Mutex`]: ../../std/sync/struct.Mutex.html +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [`str`]: ../../std/primitive.str.html +/// [`String`]: ../../std/string/struct.String.html +/// [`borrow`]: #tymethod.borrow +/// +/// # Examples +/// +/// As a data collection, [`HashMap`] owns both keys and values. If +/// the key’s actual data is wrapped in a managing type of some kind, it +/// should, however, still be possible to search for a value using a +/// reference to the key’s data. For instance, if the key is a string, then +/// it is likely stored with the hash map as a [`String`], while it should +/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to +/// operate on a `String` while `get` needs to be able to use a `&str`. +/// +/// Slightly simplified, the relevant parts of `HashMap` look like +/// this: +/// +/// ``` +/// use std::borrow::Borrow; +/// use std::hash::Hash; +/// +/// pub struct HashMap { +/// # marker: ::std::marker::PhantomData<(K, V)>, +/// // fields omitted +/// } +/// +/// impl HashMap { +/// pub fn insert(&self, key: K, value: V) -> Option +/// where K: Hash + Eq +/// { +/// # unimplemented!() +/// // ... +/// } +/// +/// pub fn get(&self, k: &Q) -> Option<&V> +/// where +/// K: Borrow, +/// Q: Hash + Eq + ?Sized +/// { +/// # unimplemented!() +/// // ... +/// } +/// } +/// ``` +/// +/// The entire hash map is generic over a key type `K`. Because these keys +/// are stored with the hash map, this type has to own the key’s data. +/// When inserting a key-value pair, the map is given such a `K` and needs +/// to find the correct hash bucket and check if the key is already present +/// based on that `K`. It therefore requires `K: Hash + Eq`. +/// +/// When searching for a value in the map, however, having to provide a +/// reference to a `K` as the key to search for would require to always +/// create such an owned value. For string keys, this would mean a `String` +/// value needs to be created just for the search for cases where only a +/// `str` is available. +/// +/// Instead, the `get` method is generic over the type of the underlying key +/// data, called `Q` in the method signature above. It states that `K` +/// borrows as a `Q` by requiring that `K: Borrow`. By additionally +/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q` +/// have implementations of the `Hash` and `Eq` traits that produce identical +/// results. +/// +/// The implementation of `get` relies in particular on identical +/// implementations of `Hash` by determining the key’s hash bucket by calling +/// `Hash::hash` on the `Q` value even though it inserted the key based on +/// the hash value calculated from the `K` value. +/// +/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value +/// produces a different hash than `Q`. For instance, imagine you have a +/// type that wraps a string but compares ASCII letters ignoring their case: +/// +/// ``` +/// pub struct CaseInsensitiveString(String); +/// +/// impl PartialEq for CaseInsensitiveString { +/// fn eq(&self, other: &Self) -> bool { +/// self.0.eq_ignore_ascii_case(&other.0) +/// } +/// } +/// +/// impl Eq for CaseInsensitiveString { } +/// ``` +/// +/// Because two equal values need to produce the same hash value, the +/// implementation of `Hash` needs to ignore ASCII case, too: +/// +/// ``` +/// # use std::hash::{Hash, Hasher}; +/// # pub struct CaseInsensitiveString(String); +/// impl Hash for CaseInsensitiveString { +/// fn hash(&self, state: &mut H) { +/// for c in self.0.as_bytes() { +/// c.to_ascii_lowercase().hash(state) +/// } +/// } +/// } +/// ``` +/// +/// Can `CaseInsensitiveString` implement `Borrow`? It certainly can +/// provide a reference to a string slice via its contained owned string. +/// But because its `Hash` implementation differs, it behaves differently +/// from `str` and therefore must not, in fact, implement `Borrow`. +/// If it wants to allow others access to the underlying `str`, it can do +/// that via `AsRef` which doesn’t carry any extra requirements. +/// +/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`String`]: ../../std/string/struct.String.html +/// [`str`]: ../../std/primitive.str.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. @@ -59,7 +189,11 @@ pub trait Borrow { /// A trait for mutably borrowing data. /// -/// Similar to `Borrow`, but for mutable borrows. +/// As a companion to [`Borrow`] this trait allows a type to borrow as +/// an underlying type by providing a mutable reference. See [`Borrow`] +/// for more information on borrowing as another type. +/// +/// [`Borrow`]: trait.Borrow.html #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut : Borrow { /// Mutably borrows from an owned value. diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 1372151b7536..c8ee166fee3e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -146,13 +146,12 @@ //! //! ``` //! #![feature(core_intrinsics)] -//! #![feature(shared)] //! use std::cell::Cell; -//! use std::ptr::Shared; +//! use std::ptr::NonNull; //! use std::intrinsics::abort; //! //! struct Rc { -//! ptr: Shared> +//! ptr: NonNull> //! } //! //! struct RcBox { @@ -1203,22 +1202,43 @@ impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> { /// The `UnsafeCell` type is the only legal way to obtain aliasable data that is considered /// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior. /// -/// The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or -/// mutated, and that `&mut T` is unique. When building abstractions like `Cell`, `RefCell`, -/// `Mutex`, etc, you need to turn these optimizations off. `UnsafeCell` is the only legal way -/// to do this. When `UnsafeCell` is immutably aliased, it is still safe to obtain a mutable -/// reference to its interior and/or to mutate it. However, it is up to the abstraction designer -/// to ensure that no two mutable references obtained this way are active at the same time, and -/// that there are no active mutable references or mutations when an immutable reference is obtained -/// from the cell. This is often done via runtime checks. +/// If you have a reference `&SomeStruct`, then normally in Rust all fields of `SomeStruct` are +/// immutable. The compiler makes optimizations based on the knowledge that `&T` is not mutably +/// aliased or mutated, and that `&mut T` is unique. `UnsafeCel` is the only core language +/// feature to work around this restriction. All other types that allow internal mutability, such as +/// `Cell` and `RefCell` use `UnsafeCell` to wrap their internal data. +/// +/// The `UnsafeCell` API itself is technically very simple: it gives you a raw pointer `*mut T` to +/// its contents. It is up to _you_ as the abstraction designer to use that raw pointer correctly. +/// +/// The precise Rust aliasing rules are somewhat in flux, but the main points are not contentious: +/// +/// - If you create a safe reference with lifetime `'a` (either a `&T` or `&mut T` reference) that +/// is accessible by safe code (for example, because you returned it), then you must not access +/// the data in any way that contradicts that reference for the remainder of `'a`. For example, that +/// means that if you take the `*mut T` from an `UnsafeCell` and case it to an `&T`, then until +/// that reference's lifetime expires, the data in `T` must remain immutable (modulo any +/// `UnsafeCell` data found within `T`, of course). Similarly, if you create an `&mut T` reference +/// that is released to safe code, then you must not access the data within the `UnsafeCell` until +/// that reference expires. +/// +/// - At all times, you must avoid data races, meaning that if multiple threads have access to +/// the same `UnsafeCell`, then any writes must have a proper happens-before relation to all other +/// accesses (or use atomics). +/// +/// To assist with proper design, the following scenarios are explicitly declared legal +/// for single-threaded code: +/// +/// 1. A `&T` reference can be released to safe code and there it can co-exit with other `&T` +/// references, but not with a `&mut T` +/// +/// 2. A `&mut T` reference may be released to safe code, provided neither other `&mut T` nor `&T` +/// co-exist with it. A `&mut T` must always be unique. /// /// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell` is -/// okay (provided you enforce the invariants some other way); it is still undefined behavior +/// okay (provided you enforce the invariants some other way), it is still undefined behavior /// to have multiple `&mut UnsafeCell` aliases. /// -/// -/// Types like `Cell` and `RefCell` use this type to wrap their internal data. -/// /// # Examples /// /// ``` @@ -1282,9 +1302,9 @@ impl UnsafeCell { /// Gets a mutable pointer to the wrapped value. /// /// This can be cast to a pointer of any kind. - /// Ensure that the access is unique when casting to - /// `&mut T`, and ensure that there are no mutations or mutable - /// aliases going on when casting to `&T` + /// Ensure that the access is unique (no active references, mutable or not) + /// when casting to `&mut T`, and ensure that there are no mutations + /// or mutable aliases going on when casting to `&T` /// /// # Examples /// diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 1638f9710f59..718c6b893edf 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -265,7 +265,7 @@ impl FromStr for char { } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl TryFrom for char { type Error = CharTryFromError; @@ -280,11 +280,11 @@ impl TryFrom for char { } /// The error type returned when a conversion from u32 to char fails. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct CharTryFromError(()); -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl fmt::Display for CharTryFromError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "converted integer out of range for `char`".fmt(f) @@ -902,6 +902,16 @@ impl> Iterator for DecodeUtf8 { } }) } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.0.size_hint(); + + // A code point is at most 4 bytes long. + let min_code_points = lower / 4; + + (min_code_points, upper) + } } #[unstable(feature = "decode_utf8", issue = "33906")] diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 826420a0c001..58a8439162c1 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -87,6 +87,23 @@ /// fn clone(&self) -> Stats { *self } /// } /// ``` +/// +/// ## Additional implementors +/// +/// In addition to the [implementors listed below][impls], +/// the following types also implement `Clone`: +/// +/// * Function item types (i.e. the distinct types defined for each function) +/// * Function pointer types (e.g. `fn() -> i32`) +/// * Array types, for all sizes, if the item type also implements `Clone` (e.g. `[i32; 123456]`) +/// * Tuple types, if each component also implements `Clone` (e.g. `()`, `(i32, bool)`) +/// * Closure types, if they capture no value from the environment +/// or if all such captured values implement `Clone` themselves. +/// Note that variables captured by shared reference always implement `Clone` +/// (even if the referent doesn't), +/// while variables captured by mutable reference never implement `Clone`. +/// +/// [impls]: #implementors #[stable(feature = "rust1", since = "1.0.0")] #[lang = "clone"] pub trait Clone : Sized { @@ -100,6 +117,7 @@ pub trait Clone : Sized { /// assert_eq!("Hello", hello.clone()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] fn clone(&self) -> Self; /// Performs copy-assignment from `source`. @@ -130,3 +148,68 @@ pub struct AssertParamIsClone { _field: ::marker::PhantomData reason = "deriving hack, should not be public", issue = "0")] pub struct AssertParamIsCopy { _field: ::marker::PhantomData } + +/// Implementations of `Clone` for primitive types. +/// +/// Implementations that cannot be described in Rust +/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc. +#[cfg(not(stage0))] +mod impls { + + use super::Clone; + + macro_rules! impl_clone { + ($($t:ty)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for $t { + #[inline] + fn clone(&self) -> Self { + *self + } + } + )* + } + } + + impl_clone! { + usize u8 u16 u32 u64 u128 + isize i8 i16 i32 i64 i128 + f32 f64 + bool char + } + + #[stable(feature = "never_type", since = "1.26.0")] + impl Clone for ! { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for *const T { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Clone for *mut T { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + // Shared references can be cloned, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T: ?Sized> Clone for &'a T { + #[inline] + fn clone(&self) -> Self { + *self + } + } + +} diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 6602643dc510..67445daa4360 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -882,24 +882,24 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - #[unstable(feature = "never_type", issue = "35121")] + #[stable(feature = "never_type", since = "1.26.0")] impl PartialEq for ! { fn eq(&self, _: &!) -> bool { *self } } - #[unstable(feature = "never_type", issue = "35121")] + #[stable(feature = "never_type", since = "1.26.0")] impl Eq for ! {} - #[unstable(feature = "never_type", issue = "35121")] + #[stable(feature = "never_type", since = "1.26.0")] impl PartialOrd for ! { fn partial_cmp(&self, _: &!) -> Option { *self } } - #[unstable(feature = "never_type", issue = "35121")] + #[stable(feature = "never_type", since = "1.26.0")] impl Ord for ! { fn cmp(&self, _: &!) -> Ordering { *self diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index d3a83dc795c8..637213957848 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -48,25 +48,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use fmt; - -/// A type used as the error type for implementations of fallible conversion -/// traits in cases where conversions cannot actually fail. -/// -/// Because `Infallible` has no variants, a value of this type can never exist. -/// It is used only to satisfy trait signatures that expect an error type, and -/// signals to both the compiler and the user that the error case is impossible. -#[unstable(feature = "try_from", issue = "33417")] -#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub enum Infallible {} - -#[unstable(feature = "try_from", issue = "33417")] -impl fmt::Display for Infallible { - fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { - match *self { - } - } -} /// A cheap reference-to-reference conversion. Used to convert a value to a /// reference value within generic code. /// @@ -341,22 +322,26 @@ pub trait From: Sized { /// /// [`TryFrom`]: trait.TryFrom.html /// [`Into`]: trait.Into.html -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. + #[stable(feature = "try_from", since = "1.26.0")] type Error; /// Performs the conversion. + #[stable(feature = "try_from", since = "1.26.0")] fn try_into(self) -> Result; } /// Attempt to construct `Self` via a conversion. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. + #[stable(feature = "try_from", since = "1.26.0")] type Error; /// Performs the conversion. + #[stable(feature = "try_from", since = "1.26.0")] fn try_from(value: T) -> Result; } @@ -382,7 +367,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef } } -// FIXME (#23442): replace the above impls for &/&mut with the following more general one: +// FIXME (#45742): replace the above impls for &/&mut with the following more general one: // // As lifts over Deref // impl AsRef for D where D::Target: AsRef { // fn as_ref(&self) -> &U { @@ -399,7 +384,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut } } -// FIXME (#23442): replace the above impl for &mut with the following more general one: +// FIXME (#45742): replace the above impl for &mut with the following more general one: // // AsMut lifts over DerefMut // impl AsMut for D where D::Target: AsMut { // fn as_mut(&mut self) -> &mut U { @@ -424,7 +409,7 @@ impl From for T { // TryFrom implies TryInto -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl TryInto for T where U: TryFrom { type Error = U::Error; @@ -436,9 +421,9 @@ impl TryInto for T where U: TryFrom // Infallible conversions are semantically equivalent to fallible conversions // with an uninhabited error type. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl TryFrom for T where T: From { - type Error = Infallible; + type Error = !; fn try_from(value: U) -> Result { Ok(T::from(value)) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8ad5a9861a02..d55219d7226e 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -333,7 +333,7 @@ impl<'a> ArgumentV1<'a> { // flags available in the v1 format of format_args #[derive(Copy, Clone)] -enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, } +enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex } impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the @@ -401,10 +401,21 @@ impl<'a> Arguments<'a> { /// safely be done, so no constructors are given and the fields are private /// to prevent modification. /// -/// The [`format_args!`] macro will safely create an instance of this structure -/// and pass it to a function or closure, passed as the first argument. The -/// macro validates the format string at compile-time so usage of the [`write`] -/// and [`format`] functions can be safely performed. +/// The [`format_args!`] macro will safely create an instance of this structure. +/// The macro validates the format string at compile-time so usage of the +/// [`write`] and [`format`] functions can be safely performed. +/// +/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` +/// and `Display` contexts as seen below. The example also shows that `Debug` +/// and `Display` format to the same thing: the interpolated format string +/// in `format_args!`. +/// +/// ```rust +/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); +/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); +/// assert_eq!("1 foo 2", display); +/// assert_eq!(display, debug); +/// ``` /// /// [`format_args!`]: ../../std/macro.format_args.html /// [`format`]: ../../std/fmt/fn.format.html @@ -684,18 +695,16 @@ pub trait Octal { /// /// The `Binary` trait should format its output as a number in binary. /// -/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// For primitive signed integers ([`i8`] to [`i128`], and [`isize`]), /// negative values are formatted as the two’s complement representation. /// /// The alternate flag, `#`, adds a `0b` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. /// -/// [module]: ../../std/fmt/index.html -/// /// # Examples /// -/// Basic usage with `i32`: +/// Basic usage with [`i32`]: /// /// ``` /// let x = 42; // 42 is '101010' in binary @@ -725,6 +734,12 @@ pub trait Octal { /// /// println!("l as binary is: {:b}", l); /// ``` +/// +/// [module]: ../../std/fmt/index.html +/// [`i8`]: ../../std/primitive.i8.html +/// [`i128`]: ../../std/primitive.i128.html +/// [`isize`]: ../../std/primitive.isize.html +/// [`i32`]: ../../std/primitive.i32.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Binary { /// Formats the value using the given formatter. @@ -1375,32 +1390,170 @@ impl<'a> Formatter<'a> { } } - /// Optionally specified integer width that the output should be + /// Optionally specified integer width that the output should be. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// if let Some(width) = formatter.width() { + /// // If we received a width, we use it + /// write!(formatter, "{:width$}", &format!("Foo({})", self.0), width = width) + /// } else { + /// // Otherwise we do nothing special + /// write!(formatter, "Foo({})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) "); + /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn width(&self) -> Option { self.width } - /// Optionally specified precision for numeric types + /// Optionally specified precision for numeric types. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(f32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// if let Some(precision) = formatter.precision() { + /// // If we received a precision, we use it. + /// write!(formatter, "Foo({1:.*})", precision, self.0) + /// } else { + /// // Otherwise we default to 2. + /// write!(formatter, "Foo({:.2})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); + /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn precision(&self) -> Option { self.precision } /// Determines if the `+` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// if formatter.sign_plus() { + /// write!(formatter, + /// "Foo({}{})", + /// if self.0 < 0 { '-' } else { '+' }, + /// self.0) + /// } else { + /// write!(formatter, "Foo({})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)"); + /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 } /// Determines if the `-` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// if formatter.sign_minus() { + /// // You want a minus sign? Have one! + /// write!(formatter, "-Foo({})", self.0) + /// } else { + /// write!(formatter, "Foo({})", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)"); + /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 } /// Determines if the `#` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// if formatter.alternate() { + /// write!(formatter, "Foo({})", self.0) + /// } else { + /// write!(formatter, "{}", self.0) + /// } + /// } + /// } + /// + /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)"); + /// assert_eq!(&format!("{}", Foo(23)), "23"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 } /// Determines if the `0` flag was specified. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo(i32); + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// assert!(formatter.sign_aware_zero_pad()); + /// assert_eq!(formatter.width(), Some(4)); + /// // We ignore the formatter's options. + /// write!(formatter, "{}", self.0) + /// } + /// } + /// + /// assert_eq!(&format!("{:04}", Foo(23)), "23"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_aware_zero_pad(&self) -> bool { self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0 } + // FIXME: Decide what public API we want for these two flags. + // https://github.com/rust-lang/rust/issues/48584 + fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 } + + fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 } + /// Creates a [`DebugStruct`] builder designed to assist with creation of /// [`fmt::Debug`] implementations for structs. /// @@ -1411,10 +1564,12 @@ impl<'a> Formatter<'a> { /// /// ```rust /// use std::fmt; + /// use std::net::Ipv4Addr; /// /// struct Foo { /// bar: i32, /// baz: String, + /// addr: Ipv4Addr, /// } /// /// impl fmt::Debug for Foo { @@ -1422,12 +1577,19 @@ impl<'a> Formatter<'a> { /// fmt.debug_struct("Foo") /// .field("bar", &self.bar) /// .field("baz", &self.baz) + /// .field("addr", &format_args!("{}", self.addr)) /// .finish() /// } /// } /// - /// // prints "Foo { bar: 10, baz: "Hello World" }" - /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); + /// assert_eq!( + /// "Foo { bar: 10, baz: \"Hello World\", addr: 127.0.0.1 }", + /// format!("{:?}", Foo { + /// bar: 10, + /// baz: "Hello World".to_string(), + /// addr: Ipv4Addr::new(127, 0, 0, 1), + /// }) + /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { @@ -1441,20 +1603,24 @@ impl<'a> Formatter<'a> { /// /// ```rust /// use std::fmt; + /// use std::marker::PhantomData; /// - /// struct Foo(i32, String); + /// struct Foo(i32, String, PhantomData); /// - /// impl fmt::Debug for Foo { + /// impl fmt::Debug for Foo { /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { /// fmt.debug_tuple("Foo") /// .field(&self.0) /// .field(&self.1) + /// .field(&format_args!("_")) /// .finish() /// } /// } /// - /// // prints "Foo(10, "Hello World")" - /// println!("{:?}", Foo(10, "Hello World".to_string())); + /// assert_eq!( + /// "Foo(10, \"Hello\", _)", + /// format!("{:?}", Foo(10, "Hello".to_string(), PhantomData::)) + /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { @@ -1504,6 +1670,41 @@ impl<'a> Formatter<'a> { /// // prints "{10, 11}" /// println!("{:?}", Foo(vec![10, 11])); /// ``` + /// + /// [`format_args!`]: ../../std/macro.format_args.html + /// + /// In this more complex example, we use [`format_args!`] and `.debug_set()` + /// to build a list of match arms: + /// + /// ```rust + /// use std::fmt; + /// + /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R)); + /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V); + /// + /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R> + /// where + /// L: 'a + fmt::Debug, R: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// L::fmt(&(self.0).0, fmt)?; + /// fmt.write_str(" => ")?; + /// R::fmt(&(self.0).1, fmt) + /// } + /// } + /// + /// impl<'a, K, V> fmt::Debug for Table<'a, K, V> + /// where + /// K: 'a + fmt::Debug, V: 'a + fmt::Debug + /// { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fmt.debug_set() + /// .entries(self.0.iter().map(Arm)) + /// .entry(&Arm(&(format_args!("_"), &self.1))) + /// .finish() + /// } + /// } + /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { builders::debug_set_new(self) @@ -1575,14 +1776,14 @@ macro_rules! fmt_refs { fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } -#[unstable(feature = "never_type", issue = "35121")] +#[stable(feature = "never_type", since = "1.26.0")] impl Debug for ! { fn fmt(&self, _: &mut Formatter) -> Result { *self } } -#[unstable(feature = "never_type", issue = "35121")] +#[stable(feature = "never_type", since = "1.26.0")] impl Display for ! { fn fmt(&self, _: &mut Formatter) -> Result { *self diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 2992e7cf8db3..4451ab445cc5 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -49,15 +49,13 @@ doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } #[doc(hidden)] trait GenericRadix { /// The number of digits. - fn base(&self) -> u8; + const BASE: u8; /// A radix-specific prefix string. - fn prefix(&self) -> &'static str { - "" - } + const PREFIX: &'static str; /// Converts an integer to corresponding radix digit. - fn digit(&self, x: u8) -> u8; + fn digit(x: u8) -> u8; /// Format an integer using the radix using a formatter. fn fmt_int(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result { @@ -65,16 +63,16 @@ trait GenericRadix { // characters for a base 2 number. let zero = T::zero(); let is_nonnegative = x >= zero; - let mut buf = [0; 128]; + let mut buf: [u8; 128] = unsafe { mem::uninitialized() }; let mut curr = buf.len(); - let base = T::from_u8(self.base()); + let base = T::from_u8(Self::BASE); if is_nonnegative { // Accumulate each digit of the number from the least significant // to the most significant figure. for byte in buf.iter_mut().rev() { - let n = x % base; // Get the current place value. - x = x / base; // Deaccumulate the number. - *byte = self.digit(n.to_u8()); // Store the digit in the buffer. + let n = x % base; // Get the current place value. + x = x / base; // Deaccumulate the number. + *byte = Self::digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; if x == zero { // No more digits left to accumulate. @@ -84,9 +82,9 @@ trait GenericRadix { } else { // Do the same as above, but accounting for two's complement. for byte in buf.iter_mut().rev() { - let n = zero - (x % base); // Get the current place value. - x = x / base; // Deaccumulate the number. - *byte = self.digit(n.to_u8()); // Store the digit in the buffer. + let n = zero - (x % base); // Get the current place value. + x = x / base; // Deaccumulate the number. + *byte = Self::digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; if x == zero { // No more digits left to accumulate. @@ -95,7 +93,7 @@ trait GenericRadix { } } let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) }; - f.pad_integral(is_nonnegative, self.prefix(), buf) + f.pad_integral(is_nonnegative, Self::PREFIX, buf) } } @@ -107,10 +105,6 @@ struct Binary; #[derive(Clone, PartialEq)] struct Octal; -/// A decimal (base 10) radix -#[derive(Clone, PartialEq)] -struct Decimal; - /// A hexadecimal (base 16) radix, formatted with lower-case characters #[derive(Clone, PartialEq)] struct LowerHex; @@ -122,12 +116,12 @@ struct UpperHex; macro_rules! radix { ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => { impl GenericRadix for $T { - fn base(&self) -> u8 { $base } - fn prefix(&self) -> &'static str { $prefix } - fn digit(&self, x: u8) -> u8 { + const BASE: u8 = $base; + const PREFIX: &'static str = $prefix; + fn digit(x: u8) -> u8 { match x { $($x => $conv,)+ - x => panic!("number not in the range 0..{}: {}", self.base() - 1, x), + x => panic!("number not in the range 0..{}: {}", Self::BASE - 1, x), } } } @@ -136,7 +130,6 @@ macro_rules! radix { radix! { Binary, 2, "0b", x @ 0 ... 1 => b'0' + x } radix! { Octal, 8, "0o", x @ 0 ... 7 => b'0' + x } -radix! { Decimal, 10, "", x @ 0 ... 9 => b'0' + x } radix! { LowerHex, 16, "0x", x @ 0 ... 9 => b'0' + x, x @ 10 ... 15 => b'a' + (x - 10) } radix! { UpperHex, 16, "0x", x @ 0 ... 9 => b'0' + x, @@ -159,7 +152,13 @@ macro_rules! debug { impl fmt::Debug for $T { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) + if f.debug_lower_hex() { + fmt::LowerHex::fmt(self, f) + } else if f.debug_upper_hex() { + fmt::UpperHex::fmt(self, f) + } else { + fmt::Display::fmt(self, f) + } } } } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 15545a04b64d..3e1f21cafe41 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -99,9 +99,10 @@ use mem; #[allow(deprecated)] pub use self::sip::SipHasher; -#[unstable(feature = "sip_hash_13", issue = "34767")] +#[unstable(feature = "hashmap_internals", issue = "0")] #[allow(deprecated)] -pub use self::sip::{SipHasher13, SipHasher24}; +#[doc(hidden)] +pub use self::sip::SipHasher13; mod sip; @@ -307,7 +308,7 @@ pub trait Hasher { } /// Writes a single `u128` into this hasher. #[inline] - #[unstable(feature = "i128", issue = "35118")] + #[stable(feature = "i128", since = "1.26.0")] fn write_u128(&mut self, i: u128) { self.write(&unsafe { mem::transmute::<_, [u8; 16]>(i) }) } @@ -347,7 +348,7 @@ pub trait Hasher { } /// Writes a single `i128` into this hasher. #[inline] - #[unstable(feature = "i128", issue = "35118")] + #[stable(feature = "i128", since = "1.26.0")] fn write_i128(&mut self, i: i128) { self.write_u128(i as u128) } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 4e4d9b3f1e2f..e3bdecdc4b1f 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -23,10 +23,11 @@ use mem; /// (eg. `collections::HashMap` uses it by default). /// /// See: -#[unstable(feature = "sip_hash_13", issue = "34767")] +#[unstable(feature = "hashmap_internals", issue = "0")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] +#[doc(hidden)] pub struct SipHasher13 { hasher: Hasher, } @@ -34,11 +35,11 @@ pub struct SipHasher13 { /// An implementation of SipHash 2-4. /// /// See: -#[unstable(feature = "sip_hash_13", issue = "34767")] +#[unstable(feature = "hashmap_internals", issue = "0")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] -pub struct SipHasher24 { +struct SipHasher24 { hasher: Hasher, } @@ -156,14 +157,16 @@ impl SipHasher { #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { - SipHasher(SipHasher24::new_with_keys(key0, key1)) + SipHasher(SipHasher24 { + hasher: Hasher::new_with_keys(key0, key1) + }) } } impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] - #[unstable(feature = "sip_hash_13", issue = "34767")] + #[unstable(feature = "hashmap_internals", issue = "0")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher13 { @@ -172,7 +175,7 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] - #[unstable(feature = "sip_hash_13", issue = "34767")] + #[unstable(feature = "hashmap_internals", issue = "0")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { @@ -182,28 +185,6 @@ impl SipHasher13 { } } -impl SipHasher24 { - /// Creates a new `SipHasher24` with the two initial keys set to 0. - #[inline] - #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] - pub fn new() -> SipHasher24 { - SipHasher24::new_with_keys(0, 0) - } - - /// Creates a `SipHasher24` that is keyed off the provided keys. - #[inline] - #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] - pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 { - SipHasher24 { - hasher: Hasher::new_with_keys(key0, key1) - } - } -} - impl Hasher { #[inline] fn new_with_keys(key0: u64, key1: u64) -> Hasher { @@ -271,16 +252,16 @@ impl Hasher { impl super::Hasher for SipHasher { #[inline] fn write(&mut self, msg: &[u8]) { - self.0.write(msg) + self.0.hasher.write(msg) } #[inline] fn finish(&self) -> u64 { - self.0.finish() + self.0.hasher.finish() } } -#[unstable(feature = "sip_hash_13", issue = "34767")] +#[unstable(feature = "hashmap_internals", issue = "0")] impl super::Hasher for SipHasher13 { #[inline] fn write(&mut self, msg: &[u8]) { @@ -293,19 +274,6 @@ impl super::Hasher for SipHasher13 { } } -#[unstable(feature = "sip_hash_13", issue = "34767")] -impl super::Hasher for SipHasher24 { - #[inline] - fn write(&mut self, msg: &[u8]) { - self.hasher.write(msg) - } - - #[inline] - fn finish(&self) -> u64 { - self.hasher.finish() - } -} - impl super::Hasher for Hasher { // see short_write comment for explanation #[inline] diff --git a/src/liballoc/allocator.rs b/src/libcore/heap.rs similarity index 97% rename from src/liballoc/allocator.rs rename to src/libcore/heap.rs index 55e8c0b430f5..fe19c923a58d 100644 --- a/src/liballoc/allocator.rs +++ b/src/libcore/heap.rs @@ -15,11 +15,11 @@ tracing garbage collector", issue = "32838")] -use core::cmp; -use core::fmt; -use core::mem; -use core::usize; -use core::ptr::{self, NonNull}; +use cmp; +use fmt; +use mem; +use usize; +use ptr::{self, NonNull}; /// Represents the combination of a starting address and /// a total capacity of the returned block. @@ -65,13 +65,11 @@ pub struct Layout { impl Layout { /// Constructs a `Layout` from a given `size` and `align`, - /// or returns `None` if any of the following conditions + /// or returns `None` if either of the following conditions /// are not met: /// /// * `align` must be a power of two, /// - /// * `align` must not exceed 231 (i.e. `1 << 31`), - /// /// * `size`, when rounded up to the nearest multiple of `align`, /// must not overflow (i.e. the rounded value must be less than /// `usize::MAX`). @@ -81,10 +79,6 @@ impl Layout { return None; } - if align > (1 << 31) { - return None; - } - // (power-of-two implies align != 0.) // Rounded up size is: @@ -113,9 +107,8 @@ impl Layout { /// # Safety /// /// This function is unsafe as it does not verify that `align` is - /// a power-of-two that is also less than or equal to 231, nor - /// that `size` aligned to `align` fits within the address space - /// (i.e. the `Layout::from_size_align` preconditions). + /// a power-of-two nor `size` aligned to `align` fits within the + /// address space (i.e. the `Layout::from_size_align` preconditions). #[inline] pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Layout { Layout { size: size, align: align } @@ -220,10 +213,10 @@ impl Layout { let padded_size = self.size.checked_add(self.padding_needed_for(self.align))?; let alloc_size = padded_size.checked_mul(n)?; - // We can assume that `self.align` is a power-of-two that does - // not exceed 231. Furthermore, `alloc_size` has already been - // rounded up to a multiple of `self.align`; therefore, the - // call to `Layout::from_size_align` below should never panic. + // We can assume that `self.align` is a power-of-two. + // Furthermore, `alloc_size` has already been rounded up + // to a multiple of `self.align`; therefore, the call to + // `Layout::from_size_align` below should never panic. Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size)) } @@ -373,6 +366,24 @@ impl fmt::Display for CannotReallocInPlace { } } +/// Augments `AllocErr` with a CapacityOverflow variant. +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] +pub enum CollectionAllocErr { + /// Error due to the computed capacity exceeding the collection's maximum + /// (usually `isize::MAX` bytes). + CapacityOverflow, + /// Error due to the allocator (see the `AllocErr` type's docs). + AllocErr(AllocErr), +} + +#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] +impl From for CollectionAllocErr { + fn from(err: AllocErr) -> Self { + CollectionAllocErr::AllocErr(err) + } +} + /// An implementation of `Alloc` can allocate, reallocate, and /// deallocate arbitrary blocks of data described via `Layout`. /// @@ -550,7 +561,7 @@ pub unsafe trait Alloc { /// invoked method, and let the client decide whether to invoke /// this `oom` method in response. fn oom(&mut self, _: AllocErr) -> ! { - unsafe { ::core::intrinsics::abort() } + unsafe { ::intrinsics::abort() } } // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 830ebad06542..3b740adc4683 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1314,6 +1314,11 @@ extern "rust-intrinsic" { /// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul) pub fn mul_with_overflow(x: T, y: T) -> (T, bool); + /// Performs an exact division, resulting in undefined behavior where + /// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1` + #[cfg(not(stage0))] + pub fn exact_div(x: T, y: T) -> T; + /// Performs an unchecked division, resulting in undefined behavior /// where y = 0 or x = `T::min_value()` and y = -1 pub fn unchecked_div(x: T, y: T) -> T; @@ -1396,3 +1401,8 @@ extern "rust-intrinsic" { /// Probably will never become stable. pub fn nontemporal_store(ptr: *mut T, val: T); } + +#[cfg(stage0)] +pub unsafe fn exact_div(a: T, b: T) -> T { + unchecked_div(a, b) +} diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 2cfbc0922934..4ccf446aa634 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -974,13 +974,13 @@ pub trait Iterator { /// // each iteration, we'll multiply the state by the element /// *state = *state * x; /// - /// // the value passed on to the next iteration - /// Some(*state) + /// // then, we'll yield the negation of the state + /// Some(-*state) /// }); /// - /// assert_eq!(iter.next(), Some(1)); - /// assert_eq!(iter.next(), Some(2)); - /// assert_eq!(iter.next(), Some(6)); + /// assert_eq!(iter.next(), Some(-1)); + /// assert_eq!(iter.next(), Some(-2)); + /// assert_eq!(iter.next(), Some(-6)); /// assert_eq!(iter.next(), None); /// ``` #[inline] @@ -1368,6 +1368,7 @@ pub trait Iterator { /// [`Result`]: ../../std/result/enum.Result.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect>(self) -> B where Self: Sized { FromIterator::from_iter(self) } @@ -1446,7 +1447,6 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = [1, 2, 3]; /// /// // the checked sum of all of the elements of the array @@ -1458,7 +1458,6 @@ pub trait Iterator { /// Short-circuiting: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = [10, 20, 30, 100, 40, 50]; /// let mut it = a.iter(); /// @@ -1472,7 +1471,7 @@ pub trait Iterator { /// assert_eq!(it.next(), Some(&40)); /// ``` #[inline] - #[unstable(feature = "iterator_try_fold", issue = "45594")] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_fold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -1495,7 +1494,6 @@ pub trait Iterator { /// # Examples /// /// ``` - /// #![feature(iterator_try_fold)] /// use std::fs::rename; /// use std::io::{stdout, Write}; /// use std::path::Path; @@ -1512,7 +1510,7 @@ pub trait Iterator { /// assert_eq!(it.next(), Some("stale_bread.json")); /// ``` #[inline] - #[unstable(feature = "iterator_try_fold", issue = "45594")] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_for_each(&mut self, mut f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try { @@ -1745,6 +1743,38 @@ pub trait Iterator { }).break_value() } + /// Applies function to the elements of iterator and returns + /// the first non-none result. + /// + /// `iter.find_map(f)` is equivalent to `iter.filter_map(f).next()`. + /// + /// + /// # Examples + /// + /// ``` + /// #![feature(iterator_find_map)] + /// let a = ["lol", "NaN", "2", "5"]; + /// + /// let mut first_number = a.iter().find_map(|s| s.parse().ok()); + /// + /// assert_eq!(first_number, Some(2)); + /// ``` + #[inline] + #[unstable(feature = "iterator_find_map", + reason = "unstable new API", + issue = "49602")] + fn find_map(&mut self, mut f: F) -> Option where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + self.try_for_each(move |x| { + match f(x) { + Some(x) => LoopState::Break(x), + None => LoopState::Continue(()), + } + }).break_value() + } + /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index a6802d606ca8..1e8476d3880c 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1872,7 +1872,7 @@ impl Iterator for Peekable { #[inline] fn nth(&mut self, n: usize) -> Option { - // FIXME(#6393): merge these when borrow-checking gets better. + // FIXME(#43234): merge these when borrow-checking gets better. if n == 0 { match self.peeked.take() { Some(v) => v, @@ -2605,7 +2605,7 @@ impl DoubleEndedIterator for Flatten } } -#[stable(feature = "fused", since = "1.26.0")] +#[unstable(feature = "iterator_flatten", issue = "48213")] impl FusedIterator for Flatten where I: FusedIterator, U: Iterator, I::Item: IntoIterator {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9a3fd215dcfe..5d57207763e4 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -91,7 +91,7 @@ macro_rules! step_impl_unsigned { #[inline] #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { - match <$t>::try_from(n) { + match <$t>::private_try_from(n) { Ok(n_as_t) => self.checked_add(n_as_t), Err(_) => None, } @@ -123,7 +123,7 @@ macro_rules! step_impl_signed { #[inline] #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { - match <$unsigned>::try_from(n) { + match <$unsigned>::private_try_from(n) { Ok(n_as_unsigned) => { // Wrapping in unsigned space handles cases like // `-120_i8.add_usize(200) == Some(80_i8)`, @@ -186,9 +186,7 @@ macro_rules! range_exact_iter_impl { macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl ExactSizeIterator for ops::RangeInclusive<$t> { } )*) } @@ -202,9 +200,7 @@ macro_rules! range_trusted_len_impl { macro_rules! range_incl_trusted_len_impl { ($($t:ty)*) => ($( - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] unsafe impl TrustedLen for ops::RangeInclusive<$t> { } )*) } @@ -328,7 +324,7 @@ impl FusedIterator for ops::RangeFrom {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ops::RangeFrom {} -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl Iterator for ops::RangeInclusive { type Item = A; @@ -422,7 +418,7 @@ impl Iterator for ops::RangeInclusive { } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl DoubleEndedIterator for ops::RangeInclusive { #[inline] fn next_back(&mut self) -> Option { @@ -465,3 +461,74 @@ impl DoubleEndedIterator for ops::RangeInclusive { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::RangeInclusive {} + +/// Compensate removal of some impls per +/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243 +trait PrivateTryFromUsize: Sized { + fn private_try_from(n: usize) -> Result; +} + +impl PrivateTryFromUsize for T where T: TryFrom { + #[inline] + fn private_try_from(n: usize) -> Result { + T::try_from(n).map_err(|_| ()) + } +} + +// no possible bounds violation +macro_rules! try_from_unbounded { + ($($target:ty),*) => {$( + impl PrivateTryFromUsize for $target { + #[inline] + fn private_try_from(value: usize) -> Result { + Ok(value as $target) + } + } + )*} +} + +// unsigned to signed (only positive bound) +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +macro_rules! try_from_upper_bounded { + ($($target:ty),*) => {$( + impl PrivateTryFromUsize for $target { + #[inline] + fn private_try_from(u: usize) -> Result<$target, ()> { + if u > (<$target>::max_value() as usize) { + Err(()) + } else { + Ok(u as $target) + } + } + } + )*} +} + + +#[cfg(target_pointer_width = "16")] +mod ptr_try_from_impls { + use super::PrivateTryFromUsize; + + try_from_unbounded!(u16, u32, u64, u128); + try_from_unbounded!(i32, i64, i128); +} + +#[cfg(target_pointer_width = "32")] +mod ptr_try_from_impls { + use super::PrivateTryFromUsize; + + try_from_upper_bounded!(u16); + try_from_unbounded!(u32, u64, u128); + try_from_upper_bounded!(i32); + try_from_unbounded!(i64, i128); +} + +#[cfg(target_pointer_width = "64")] +mod ptr_try_from_impls { + use super::PrivateTryFromUsize; + + try_from_upper_bounded!(u16, u32); + try_from_unbounded!(u64, u128); + try_from_upper_bounded!(i32, i64); + try_from_unbounded!(i128); +} diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 0267fcd37545..ddbb59989424 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -427,7 +427,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = ["1", "2", "3"]; /// let sum = a.iter() /// .map(|&s| s.parse::()) @@ -438,7 +437,6 @@ pub trait DoubleEndedIterator: Iterator { /// Short-circuiting: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = ["1", "rust", "3"]; /// let mut it = a.iter(); /// let sum = it @@ -452,7 +450,7 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(it.next_back(), Some(&"1")); /// ``` #[inline] - #[unstable(feature = "iterator_try_fold", issue = "45594")] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -491,7 +489,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_rfold)] /// let a = [1, 2, 3]; /// /// // the sum of all of the elements of a @@ -505,7 +502,6 @@ pub trait DoubleEndedIterator: Iterator { /// and continuing with each element from the back until the front: /// /// ``` - /// #![feature(iter_rfold)] /// let numbers = [1, 2, 3, 4, 5]; /// /// let zero = "0".to_string(); @@ -517,14 +513,14 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))"); /// ``` #[inline] - #[unstable(feature = "iter_rfold", issue = "44705")] + #[stable(feature = "iter_rfold", since = "1.27.0")] fn rfold(mut self, accum: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { self.try_rfold(accum, move |acc, x| AlwaysOk(f(acc, x))).0 } - /// Searches for an element of an iterator from the right that satisfies a predicate. + /// Searches for an element of an iterator from the back that satisfies a predicate. /// /// `rfind()` takes a closure that returns `true` or `false`. It applies /// this closure to each element of the iterator, starting at the end, and if any @@ -547,8 +543,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_rfind)] - /// /// let a = [1, 2, 3]; /// /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); @@ -559,8 +553,6 @@ pub trait DoubleEndedIterator: Iterator { /// Stopping at the first `true`: /// /// ``` - /// #![feature(iter_rfind)] - /// /// let a = [1, 2, 3]; /// /// let mut iter = a.iter(); @@ -571,7 +563,7 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(iter.next_back(), Some(&1)); /// ``` #[inline] - #[unstable(feature = "iter_rfind", issue = "39480")] + #[stable(feature = "iter_rfind", since = "1.27.0")] fn rfind

(&mut self, mut predicate: P) -> Option where Self: Sized, P: FnMut(&Self::Item) -> bool @@ -901,6 +893,15 @@ impl Iterator for ResultShunt None => None, } } + + fn size_hint(&self) -> (usize, Option) { + if self.error.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } } #[stable(feature = "iter_arith_traits_result", since="1.16.0")] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1efd605112dc..5a62b8438f93 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -74,16 +74,19 @@ #![feature(concat_idents)] #![feature(const_fn)] #![feature(custom_attribute)] +#![feature(doc_cfg)] #![feature(doc_spotlight)] +#![feature(fn_must_use)] #![feature(fundamental)] -#![feature(i128_type)] -#![feature(inclusive_range_syntax)] +#![cfg_attr(stage0, feature(i128_type))] +#![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(intrinsics)] #![feature(iterator_flatten)] #![feature(iterator_repeat_with)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] -#![feature(never_type)] +#![feature(exhaustive_patterns)] +#![feature(macro_at_most_once_rep)] #![feature(no_core)] #![feature(on_unimplemented)] #![feature(optin_builtin_traits)] @@ -101,6 +104,7 @@ #![feature(unwind_attributes)] #![cfg_attr(stage0, allow(unused_attributes))] +#![cfg_attr(stage0, feature(never_type))] #[prelude_import] #[allow(unused)] @@ -165,6 +169,7 @@ pub mod borrow; pub mod any; pub mod array; +pub mod ascii; pub mod sync; pub mod cell; pub mod char; @@ -181,6 +186,10 @@ pub mod hash; pub mod fmt; pub mod time; +/* Heap memory allocator trait */ +#[allow(missing_docs)] +pub mod heap; + // note: does not need to be public mod char_private; mod iter_private; diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 52eb9f29d57a..8a87bea71e25 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -76,6 +76,7 @@ macro_rules! panic { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] macro_rules! assert { ($cond:expr) => ( if !$cond { @@ -784,4 +785,18 @@ mod builtin { ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }); } + + /// Ensure that a boolean expression is `true` at runtime. + /// + /// For more information, see the documentation for [`std::assert!`]. + /// + /// [`std::assert!`]: ../std/macro.assert.html + #[macro_export] + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(dox)] + macro_rules! assert { + ($cond:expr) => ({ /* compiler built-in */ }); + ($cond:expr,) => ({ /* compiler built-in */ }); + ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }); + } } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 98e0f71eb935..885aabe08069 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -260,6 +260,21 @@ pub trait Unsize { /// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to /// avoid a breaking API change. /// +/// ## Additional implementors +/// +/// In addition to the [implementors listed below][impls], +/// the following types also implement `Copy`: +/// +/// * Function item types (i.e. the distinct types defined for each function) +/// * Function pointer types (e.g. `fn() -> i32`) +/// * Array types, for all sizes, if the item type also implements `Copy` (e.g. `[i32; 123456]`) +/// * Tuple types, if each component also implements `Copy` (e.g. `()`, `(i32, bool)`) +/// * Closure types, if they capture no value from the environment +/// or if all such captured values implement `Copy` themselves. +/// Note that variables captured by shared reference always implement `Copy` +/// (even if the referent doesn't), +/// while variables captured by mutable reference never implement `Copy`. +/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`String`]: ../../std/string/struct.String.html /// [`Drop`]: ../../std/ops/trait.Drop.html @@ -267,6 +282,7 @@ pub trait Unsize { /// [`Clone`]: ../clone/trait.Clone.html /// [`String`]: ../../std/string/struct.String.html /// [`i32`]: ../../std/primitive.i32.html +/// [impls]: #implementors #[stable(feature = "rust1", since = "1.0.0")] #[lang = "copy"] pub trait Copy : Clone { @@ -343,8 +359,21 @@ pub trait Copy : Clone { /// [transmute]: ../../std/mem/fn.transmute.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sync"] -#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] +#[rustc_on_unimplemented( + message="`{Self}` cannot be shared between threads safely", + label="`{Self}` cannot be shared between threads safely" +)] pub unsafe auto trait Sync { + // FIXME(estebank): once support to add notes in `rustc_on_unimplemented` + // lands in beta, and it has been extended to check whether a closure is + // anywhere in the requirement chain, extend it as such (#48534): + // ``` + // on( + // closure, + // note="`{Self}` cannot be shared safely, consider marking the closure `move`" + // ), + // ``` + // Empty } @@ -565,3 +594,53 @@ unsafe impl Freeze for *const T {} unsafe impl Freeze for *mut T {} unsafe impl<'a, T: ?Sized> Freeze for &'a T {} unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} + +/// Types which can be moved out of a `Pin`. +/// +/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a +/// type implements `Unpin`, it is safe to move a value of that type out of the +/// `Pin` pointer. +/// +/// This trait is automatically implemented for almost every type. +#[unstable(feature = "pin", issue = "49150")] +pub unsafe auto trait Unpin {} + +/// Implementations of `Copy` for primitive types. +/// +/// Implementations that cannot be described in Rust +/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc. +#[cfg(not(stage0))] +mod copy_impls { + + use super::Copy; + + macro_rules! impl_copy { + ($($t:ty)*) => { + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl Copy for $t {} + )* + } + } + + impl_copy! { + usize u8 u16 u32 u64 u128 + isize i8 i16 i32 i64 i128 + f32 f64 + bool char + } + + #[stable(feature = "never_type", since = "1.26.0")] + impl Copy for ! {} + + #[stable(feature = "rust1", since = "1.0.0")] + impl Copy for *const T {} + + #[stable(feature = "rust1", since = "1.0.0")] + impl Copy for *mut T {} + + // Shared references can be copied, but mutable references *cannot*! + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, T: ?Sized> Copy for &'a T {} + +} diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 21a0beccbf64..b2467c948b4b 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -20,9 +20,9 @@ use cmp; use fmt; use hash; use intrinsics; -use marker::{Copy, PhantomData, Sized}; +use marker::{Copy, PhantomData, Sized, Unpin, Unsize}; use ptr; -use ops::{Deref, DerefMut}; +use ops::{Deref, DerefMut, CoerceUnsized}; #[stable(feature = "rust1", since = "1.0.0")] pub use intrinsics::transmute; @@ -1105,3 +1105,111 @@ impl ::hash::Hash for ManuallyDrop { pub unsafe fn unreachable() -> ! { intrinsics::unreachable() } + +/// A pinned reference. +/// +/// A pinned reference is a lot like a mutable reference, except that it is not +/// safe to move a value out of a pinned reference unless the type of that +/// value implements the `Unpin` trait. +#[unstable(feature = "pin", issue = "49150")] +#[fundamental] +pub struct Pin<'a, T: ?Sized + 'a> { + inner: &'a mut T, +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unpin> Pin<'a, T> { + /// Construct a new `Pin` around a reference to some data of a type that + /// implements `Unpin`. + #[unstable(feature = "pin", issue = "49150")] + pub fn new(reference: &'a mut T) -> Pin<'a, T> { + Pin { inner: reference } + } +} + + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> Pin<'a, T> { + /// Construct a new `Pin` around a reference to some data of a type that + /// may or may not implement `Unpin`. + /// + /// This constructor is unsafe because we do not know what will happen with + /// that data after the reference ends. If you cannot guarantee that the + /// data will never move again, calling this constructor is invalid. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> { + Pin { inner: reference } + } + + /// Borrow a Pin for a shorter lifetime than it already has. + #[unstable(feature = "pin", issue = "49150")] + pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> { + Pin { inner: this.inner } + } + + /// Get a mutable reference to the data inside of this `Pin`. + /// + /// This function is unsafe. You must guarantee that you will never move + /// the data out of the mutable reference you receive when you call this + /// function. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T { + this.inner + } + + /// Construct a new pin by mapping the interior value. + /// + /// For example, if you wanted to get a `Pin` of a field of something, you + /// could use this to get access to that field in one line of code. + /// + /// This function is unsafe. You must guarantee that the data you return + /// will not move so long as the argument value does not move (for example, + /// because it is one of the fields of that value), and also that you do + /// not move out of the argument you receive to the interior function. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where + F: FnOnce(&mut T) -> &mut U + { + Pin { inner: f(this.inner) } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> Deref for Pin<'a, T> { + type Target = T; + + fn deref(&self) -> &T { + &*self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> { + fn deref_mut(&mut self) -> &mut T { + self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&(&*self.inner as *const T), f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Pin<'a, T> {} diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 2c966eb3b579..19836d98844e 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -9,9 +9,10 @@ // except according to those terms. //! Exposes the NonZero lang item which provides optimization hints. -#![unstable(feature = "nonzero", - reason = "needs an RFC to flesh out the design", - issue = "27730")] +#![unstable(feature = "nonzero", reason = "deprecated", issue = "49137")] +#![rustc_deprecated(reason = "use `std::ptr::NonNull` or `std::num::NonZero*` instead", + since = "1.26.0")] +#![allow(deprecated)] use ops::CoerceUnsized; @@ -62,14 +63,11 @@ impl_zeroable_for_integer_types! { /// NULL or 0 that might allow certain optimizations. #[lang = "non_zero"] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)] -pub struct NonZero(T); +pub struct NonZero(pub(crate) T); impl NonZero { /// Creates an instance of NonZero with the provided value. /// You must indeed ensure that the value is actually "non-zero". - #[unstable(feature = "nonzero", - reason = "needs an RFC to flesh out the design", - issue = "27730")] #[inline] pub const unsafe fn new_unchecked(inner: T) -> Self { NonZero(inner) diff --git a/src/libcore/num/i128.rs b/src/libcore/num/i128.rs index 04354e2e33f9..989376d1ac2d 100644 --- a/src/libcore/num/i128.rs +++ b/src/libcore/num/i128.rs @@ -12,6 +12,6 @@ //! //! *[See also the `i128` primitive type](../../std/primitive.i128.html).* -#![unstable(feature = "i128", issue="35118")] +#![stable(feature = "i128", since = "1.26.0")] -int_module! { i128, #[unstable(feature = "i128", issue="35118")] } +int_module! { i128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 09ab7060d37d..dcda404721c1 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -12,12 +12,111 @@ #![stable(feature = "rust1", since = "1.0.0")] -use convert::{Infallible, TryFrom}; +use convert::TryFrom; use fmt; use intrinsics; +#[allow(deprecated)] use nonzero::NonZero; use ops; use str::FromStr; +macro_rules! impl_nonzero_fmt { + ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { + $( + #[$stability] + #[allow(deprecated)] + impl fmt::$Trait for $Ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.get().fmt(f) + } + } + )+ + } +} + +macro_rules! nonzero_integers { + ( #[$stability: meta] #[$deprecation: meta] $( $Ty: ident($Int: ty); )+ ) => { + $( + /// An integer that is known not to equal zero. + /// + /// This may enable some memory layout optimization such as: + /// + /// ```rust + /// # #![feature(nonzero)] + /// use std::mem::size_of; + /// assert_eq!(size_of::>(), size_of::()); + /// ``` + #[$stability] + #[$deprecation] + #[allow(deprecated)] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + pub struct $Ty(NonZero<$Int>); + + #[allow(deprecated)] + impl $Ty { + /// Create a non-zero without checking the value. + /// + /// # Safety + /// + /// The value must not be zero. + #[$stability] + #[inline] + pub const unsafe fn new_unchecked(n: $Int) -> Self { + $Ty(NonZero(n)) + } + + /// Create a non-zero if the given value is not zero. + #[$stability] + #[inline] + pub fn new(n: $Int) -> Option { + if n != 0 { + Some($Ty(NonZero(n))) + } else { + None + } + } + + /// Returns the value as a primitive type. + #[$stability] + #[inline] + pub fn get(self) -> $Int { + self.0 .0 + } + + } + + impl_nonzero_fmt! { + #[$stability] + (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + } + )+ + } +} + +nonzero_integers! { + #[unstable(feature = "nonzero", issue = "49137")] + #[allow(deprecated)] // Redundant, works around "error: inconsistent lockstep iteration" + NonZeroU8(u8); + NonZeroU16(u16); + NonZeroU32(u32); + NonZeroU64(u64); + NonZeroU128(u128); + NonZeroUsize(usize); +} + +nonzero_integers! { + #[unstable(feature = "nonzero", issue = "49137")] + #[rustc_deprecated(since = "1.26.0", reason = "\ + signed non-zero integers are considered for removal due to lack of known use cases. \ + If you’re using them, please comment on https://github.com/rust-lang/rust/issues/49137")] + NonZeroI8(i8); + NonZeroI16(i16); + NonZeroI32(i32); + NonZeroI64(i64); + NonZeroI128(i128); + NonZeroIsize(isize); +} + /// Provides intentionally-wrapped arithmetic on `T`. /// /// Operations like `+` on `u32` values is intended to never overflow, @@ -1546,11 +1645,7 @@ impl i64 { #[lang = "i128"] impl i128 { int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728, - 170141183460469231731687303715884105727, "#![feature(i128_type)] -#![feature(i128)] -# fn main() { -", " -# }" } + 170141183460469231731687303715884105727, "", "" } } #[cfg(target_pointer_width = "16")] @@ -3404,12 +3499,7 @@ impl u64 { #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "#![feature(i128_type)] -#![feature(i128)] - -# fn main() { -", " -# }" } + uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "" } } #[cfg(target_pointer_width = "16")] @@ -3573,7 +3663,7 @@ macro_rules! from_str_radix_int_impl { from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } /// The error type returned when a checked integral type conversion fails. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] #[derive(Debug, Copy, Clone)] pub struct TryFromIntError(()); @@ -3588,40 +3678,24 @@ impl TryFromIntError { } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl fmt::Display for TryFromIntError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.__description().fmt(fmt) } } -#[unstable(feature = "try_from", issue = "33417")] -impl From for TryFromIntError { - fn from(infallible: Infallible) -> TryFromIntError { - match infallible { - } +#[stable(feature = "try_from", since = "1.26.0")] +impl From for TryFromIntError { + fn from(never: !) -> TryFromIntError { + never } } -// no possible bounds violation -macro_rules! try_from_unbounded { - ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] - impl TryFrom<$source> for $target { - type Error = Infallible; - - #[inline] - fn try_from(value: $source) -> Result { - Ok(value as $target) - } - } - )*} -} - // only negative bounds macro_rules! try_from_lower_bounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -3640,7 +3714,7 @@ macro_rules! try_from_lower_bounded { // unsigned to signed (only positive bound) macro_rules! try_from_upper_bounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -3659,7 +3733,7 @@ macro_rules! try_from_upper_bounded { // all other cases macro_rules! try_from_both_bounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -3716,82 +3790,44 @@ try_from_both_bounded!(i128, u64, u32, u16, u8); try_from_upper_bounded!(usize, isize); try_from_lower_bounded!(isize, usize); +try_from_upper_bounded!(usize, u8); +try_from_upper_bounded!(usize, i8, i16); +try_from_both_bounded!(isize, u8); +try_from_both_bounded!(isize, i8); + #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::{Infallible, TryFrom}; + use convert::TryFrom; - try_from_upper_bounded!(usize, u8); - try_from_unbounded!(usize, u16, u32, u64, u128); - try_from_upper_bounded!(usize, i8, i16); - try_from_unbounded!(usize, i32, i64, i128); - - try_from_both_bounded!(isize, u8); + // Fallible across platfoms, only implementation differs try_from_lower_bounded!(isize, u16, u32, u64, u128); - try_from_both_bounded!(isize, i8); - try_from_unbounded!(isize, i16, i32, i64, i128); - - rev!(try_from_unbounded, usize, u16); - rev!(try_from_upper_bounded, usize, u32, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16); rev!(try_from_both_bounded, usize, i32, i64, i128); - - rev!(try_from_unbounded, isize, u8); - rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); - rev!(try_from_unbounded, isize, i16); - rev!(try_from_both_bounded, isize, i32, i64, i128); } #[cfg(target_pointer_width = "32")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::{Infallible, TryFrom}; + use convert::TryFrom; - try_from_upper_bounded!(usize, u8, u16); - try_from_unbounded!(usize, u32, u64, u128); - try_from_upper_bounded!(usize, i8, i16, i32); - try_from_unbounded!(usize, i64, i128); - - try_from_both_bounded!(isize, u8, u16); + // Fallible across platfoms, only implementation differs + try_from_both_bounded!(isize, u16); try_from_lower_bounded!(isize, u32, u64, u128); - try_from_both_bounded!(isize, i8, i16); - try_from_unbounded!(isize, i32, i64, i128); - - rev!(try_from_unbounded, usize, u16, u32); - rev!(try_from_upper_bounded, usize, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32); rev!(try_from_both_bounded, usize, i64, i128); - - rev!(try_from_unbounded, isize, u8, u16); - rev!(try_from_upper_bounded, isize, u32, u64, u128); - rev!(try_from_unbounded, isize, i16, i32); - rev!(try_from_both_bounded, isize, i64, i128); } #[cfg(target_pointer_width = "64")] mod ptr_try_from_impls { use super::TryFromIntError; - use convert::{Infallible, TryFrom}; + use convert::TryFrom; - try_from_upper_bounded!(usize, u8, u16, u32); - try_from_unbounded!(usize, u64, u128); - try_from_upper_bounded!(usize, i8, i16, i32, i64); - try_from_unbounded!(usize, i128); - - try_from_both_bounded!(isize, u8, u16, u32); + // Fallible across platfoms, only implementation differs + try_from_both_bounded!(isize, u16, u32); try_from_lower_bounded!(isize, u64, u128); - try_from_both_bounded!(isize, i8, i16, i32); - try_from_unbounded!(isize, i64, i128); - - rev!(try_from_unbounded, usize, u16, u32, u64); - rev!(try_from_upper_bounded, usize, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); rev!(try_from_both_bounded, usize, i128); - - rev!(try_from_unbounded, isize, u8, u16, u32); - rev!(try_from_upper_bounded, isize, u64, u128); - rev!(try_from_unbounded, isize, i16, i32, i64); - rev!(try_from_both_bounded, isize, i128); } #[doc(hidden)] @@ -3967,39 +4003,53 @@ macro_rules! impl_from { impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, u128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, u128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u32, u128, #[unstable(feature = "i128", issue = "35118")] } -impl_from! { u64, u128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] } // Signed -> Signed impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i8, i128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i16, i128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i32, i128, #[unstable(feature = "i128", issue = "35118")] } -impl_from! { i64, i128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] } // Unsigned -> Signed impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, i128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, i128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u32, i128, #[unstable(feature = "i128", issue = "35118")] } -impl_from! { u64, i128, #[unstable(feature = "i128", issue = "35118")] } +impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] } + +// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX +// which imply that pointer-sized integers must be at least 16 bits: +// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4 +impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } +impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } +impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } + +// RISC-V defines the possibility of a 128-bit address space (RV128). + +// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. +// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf +// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf + // Note: integers can only be represented with full precision in a float if // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. diff --git a/src/libcore/num/u128.rs b/src/libcore/num/u128.rs index 987ac3e00073..e8c783a1bb54 100644 --- a/src/libcore/num/u128.rs +++ b/src/libcore/num/u128.rs @@ -12,5 +12,5 @@ //! //! *[See also the `u128` primitive type](../../std/primitive.u128.html).* -#![unstable(feature = "i128", issue="35118")] -uint_module! { u128, #[unstable(feature = "i128", issue="35118")] } +#![stable(feature = "i128", since = "1.26.0")] +uint_module! { u128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index ae1b0b3ce11b..826883fdc3f0 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -317,11 +317,320 @@ macro_rules! wrapping_impl { } forward_ref_unop! { impl Neg, neg for Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } + )*) } wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +macro_rules! wrapping_int_impl { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + /// Returns the number of ones in the binary representation of + /// `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-0b1000_0000); + /// + /// assert_eq!(n.count_ones(), 1); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representation of + /// `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-0b1000_0000); + /// + /// assert_eq!(n.count_zeros(), 7); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-1); + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-4); + /// + /// assert_eq!(n.trailing_zeros(), 2); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting + /// integer. + /// + /// Please note this isn't the same operation as `>>`! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let m: Wrapping = Wrapping(-0x76543210FEDCBA99); + /// + /// assert_eq!(n.rotate_left(32), m); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn rotate_left(self, n: u32) -> Self { + Wrapping(self.0.rotate_left(n)) + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as `<<`! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let m: Wrapping = Wrapping(-0xFEDCBA987654322); + /// + /// assert_eq!(n.rotate_right(4), m); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn rotate_right(self, n: u32) -> Self { + Wrapping(self.0.rotate_right(n)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0b0000000_01010101); + /// assert_eq!(n, Wrapping(85)); + /// + /// let m = n.swap_bytes(); + /// + /// assert_eq!(m, Wrapping(0b01010101_00000000)); + /// assert_eq!(m, Wrapping(21760)); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn swap_bytes(self) -> Self { + Wrapping(self.0.swap_bytes()) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Wrapping::::from_be(n), n); + /// } else { + /// assert_eq!(Wrapping::::from_be(n), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn from_be(x: Self) -> Self { + Wrapping(<$t>::from_be(x.0)) + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Wrapping::::from_le(n), n); + /// } else { + /// assert_eq!(Wrapping::::from_le(n), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn from_le(x: Self) -> Self { + Wrapping(<$t>::from_le(x.0)) + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n); + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn to_be(self) -> Self { + Wrapping(self.0.to_be()) + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n); + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn to_le(self) -> Self { + Wrapping(self.0.to_le()) + } + + /// Raises self to the power of `exp`, using exponentiation by + /// squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let x: Wrapping = Wrapping(2); // or any other integer type + /// + /// assert_eq!(x.pow(4), Wrapping(16)); + /// ``` + /// + /// Results that are too large are wrapped: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// // 5 ^ 4 = 625, which is too big for a u8 + /// let x: Wrapping = Wrapping(5); + /// + /// assert_eq!(x.pow(4).0, 113); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn pow(self, exp: u32) -> Self { + Wrapping(self.0.wrapping_pow(exp)) + } + } + )*) +} + +wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + + mod shift_max { #![allow(non_upper_case_globals)] diff --git a/src/libcore/ops/drop.rs b/src/libcore/ops/drop.rs index 70ab7b2f3b7e..474f7e34c347 100644 --- a/src/libcore/ops/drop.rs +++ b/src/libcore/ops/drop.rs @@ -95,7 +95,7 @@ pub trait Drop { /// Executes the destructor for this type. /// - /// This method is called implilcitly when the value goes out of scope, + /// This method is called implicitly when the value goes out of scope, /// and cannot be called explicitly (this is compiler error [E0040]). /// However, the [`std::mem::drop`] function in the prelude can be /// used to call the argument's `Drop` implementation. diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs index dc7669d195c1..4b70c5398be4 100644 --- a/src/libcore/ops/generator.rs +++ b/src/libcore/ops/generator.rs @@ -56,11 +56,11 @@ pub enum GeneratorState { /// return "foo" /// }; /// -/// match generator.resume() { +/// match unsafe { generator.resume() } { /// GeneratorState::Yielded(1) => {} /// _ => panic!("unexpected return from resume"), /// } -/// match generator.resume() { +/// match unsafe { generator.resume() } { /// GeneratorState::Complete("foo") => {} /// _ => panic!("unexpected return from resume"), /// } @@ -98,6 +98,10 @@ pub trait Generator { /// generator will continue executing until it either yields or returns, at /// which point this function will return. /// + /// The function is unsafe because it can be used on an immovable generator. + /// After such a call, the immovable generator must not move again, but + /// this is not enforced by the compiler. + /// /// # Return value /// /// The `GeneratorState` enum returned from this function indicates what @@ -116,7 +120,7 @@ pub trait Generator { /// been returned previously. While generator literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Generator` trait. - fn resume(&mut self) -> GeneratorState; + unsafe fn resume(&mut self) -> GeneratorState; } #[unstable(feature = "generator_trait", issue = "43122")] @@ -125,7 +129,7 @@ impl<'a, T> Generator for &'a mut T { type Yield = T::Yield; type Return = T::Return; - fn resume(&mut self) -> GeneratorState { + unsafe fn resume(&mut self) -> GeneratorState { (**self).resume() } } diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 70ef4487334c..ce4f45762de4 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -161,7 +161,6 @@ mod drop; mod function; mod generator; mod index; -mod place; mod range; mod try; mod unsize; @@ -191,8 +190,8 @@ pub use self::index::{Index, IndexMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -pub use self::range::{RangeInclusive, RangeToInclusive}; +#[stable(feature = "inclusive_range", since = "1.26.0")] +pub use self::range::{RangeInclusive, RangeToInclusive, RangeBounds, Bound}; #[unstable(feature = "try_trait", issue = "42327")] pub use self::try::Try; @@ -200,8 +199,5 @@ pub use self::try::Try; #[unstable(feature = "generator_trait", issue = "43122")] pub use self::generator::{Generator, GeneratorState}; -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace}; - #[unstable(feature = "coerce_unsized", issue = "27732")] pub use self::unsize::CoerceUnsized; diff --git a/src/libcore/ops/place.rs b/src/libcore/ops/place.rs deleted file mode 100644 index b3dcf4e7ee95..000000000000 --- a/src/libcore/ops/place.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// Both `PLACE <- EXPR` and `box EXPR` desugar into expressions -/// that allocate an intermediate "place" that holds uninitialized -/// state. The desugaring evaluates EXPR, and writes the result at -/// the address returned by the `pointer` method of this trait. -/// -/// A `Place` can be thought of as a special representation for a -/// hypothetical `&uninit` reference (which Rust cannot currently -/// express directly). That is, it represents a pointer to -/// uninitialized storage. -/// -/// The client is responsible for two steps: First, initializing the -/// payload (it can access its address via `pointer`). Second, -/// converting the agent to an instance of the owning pointer, via the -/// appropriate `finalize` method (see the `InPlace`. -/// -/// If evaluating EXPR fails, then it is up to the destructor for the -/// implementation of Place to clean up any intermediate state -/// (e.g. deallocate box storage, pop a stack, etc). -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub unsafe trait Place { - /// Returns the address where the input value will be written. - /// Note that the data at this address is generally uninitialized, - /// and thus one should use `ptr::write` for initializing it. - /// - /// This function must return a pointer through which a value - /// of type `Data` can be written. - fn pointer(&mut self) -> *mut Data; -} - -/// Interface to implementations of `PLACE <- EXPR`. -/// -/// `PLACE <- EXPR` effectively desugars into: -/// -/// ``` -/// # #![feature(placement_new_protocol, box_heap)] -/// # use std::ops::{Placer, Place, InPlace}; -/// # #[allow(non_snake_case)] -/// # fn main() { -/// # let PLACE = std::boxed::HEAP; -/// # let EXPR = 1; -/// let p = PLACE; -/// let mut place = Placer::make_place(p); -/// let raw_place = Place::pointer(&mut place); -/// let value = EXPR; -/// unsafe { -/// std::ptr::write(raw_place, value); -/// InPlace::finalize(place) -/// } -/// # ; } -/// ``` -/// -/// The type of `PLACE <- EXPR` is derived from the type of `PLACE`; -/// if the type of `PLACE` is `P`, then the final type of the whole -/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` -/// traits). -/// -/// Values for types implementing this trait usually are transient -/// intermediate values (e.g. the return value of `Vec::emplace_back`) -/// or `Copy`, since the `make_place` method takes `self` by value. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Placer { - /// `Place` is the intermediate agent guarding the - /// uninitialized state for `Data`. - type Place: InPlace; - - /// Creates a fresh place from `self`. - fn make_place(self) -> Self::Place; -} - -/// Specialization of `Place` trait supporting `PLACE <- EXPR`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait InPlace: Place { - /// `Owner` is the type of the end value of `PLACE <- EXPR` - /// - /// Note that when `PLACE <- EXPR` is solely used for - /// side-effecting an existing data-structure, - /// e.g. `Vec::emplace_back`, then `Owner` need not carry any - /// information at all (e.g. it can be the unit type `()` in that - /// case). - type Owner; - - /// Converts self into the final value, shifting - /// deallocation/cleanup responsibilities (if any remain), over to - /// the returned instance of `Owner` and forgetting self. - unsafe fn finalize(self) -> Self::Owner; -} - -/// Core trait for the `box EXPR` form. -/// -/// `box EXPR` effectively desugars into: -/// -/// ``` -/// # #![feature(placement_new_protocol)] -/// # use std::ops::{BoxPlace, Place, Boxed}; -/// # #[allow(non_snake_case)] -/// # fn main() { -/// # let EXPR = 1; -/// let mut place = BoxPlace::make_place(); -/// let raw_place = Place::pointer(&mut place); -/// let value = EXPR; -/// # let _: Box<_> = -/// unsafe { -/// ::std::ptr::write(raw_place, value); -/// Boxed::finalize(place) -/// } -/// # ; } -/// ``` -/// -/// The type of `box EXPR` is supplied from its surrounding -/// context; in the above expansion, the result type `T` is used -/// to determine which implementation of `Boxed` to use, and that -/// `` in turn dictates determines which -/// implementation of `BoxPlace` to use, namely: -/// `<::Place as BoxPlace>`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Boxed { - /// The kind of data that is stored in this kind of box. - type Data; /* (`Data` unused b/c cannot yet express below bound.) */ - /// The place that will negotiate the storage of the data. - type Place: BoxPlace; - - /// Converts filled place into final owning value, shifting - /// deallocation/cleanup responsibilities (if any remain), over to - /// returned instance of `Self` and forgetting `filled`. - unsafe fn finalize(filled: Self::Place) -> Self; -} - -/// Specialization of `Place` trait supporting `box EXPR`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait BoxPlace : Place { - /// Creates a globally fresh place. - fn make_place() -> Self; -} diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 1d9c0f873b34..3f6674071256 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -128,7 +128,7 @@ impl> Range { /// The range is empty if either side is incomparable: /// /// ``` - /// #![feature(range_is_empty,inclusive_range_syntax)] + /// #![feature(range_is_empty)] /// /// use std::f32::NAN; /// assert!(!(3.0..5.0).is_empty()); @@ -283,7 +283,7 @@ impl> RangeTo { /// # Examples /// /// ``` -/// #![feature(inclusive_range,inclusive_range_syntax)] +/// #![feature(inclusive_range_fields)] /// /// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 }); /// assert_eq!(3 + 4 + 5, (3..=5).sum()); @@ -293,21 +293,17 @@ impl> RangeTo { /// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive /// ``` #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[unstable(feature = "inclusive_range_fields", issue = "49022")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[unstable(feature = "inclusive_range_fields", issue = "49022")] pub end: Idx, } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}..={:?}", self.start, self.end) @@ -320,7 +316,7 @@ impl> RangeInclusive { /// # Examples /// /// ``` - /// #![feature(range_contains,inclusive_range_syntax)] + /// #![feature(range_contains)] /// /// assert!(!(3..=5).contains(2)); /// assert!( (3..=5).contains(3)); @@ -341,7 +337,7 @@ impl> RangeInclusive { /// # Examples /// /// ``` - /// #![feature(range_is_empty,inclusive_range_syntax)] + /// #![feature(range_is_empty)] /// /// assert!(!(3..=5).is_empty()); /// assert!(!(3..=3).is_empty()); @@ -351,7 +347,7 @@ impl> RangeInclusive { /// The range is empty if either side is incomparable: /// /// ``` - /// #![feature(range_is_empty,inclusive_range_syntax)] + /// #![feature(range_is_empty)] /// /// use std::f32::NAN; /// assert!(!(3.0..=5.0).is_empty()); @@ -362,7 +358,7 @@ impl> RangeInclusive { /// This method returns `true` after iteration has finished: /// /// ``` - /// #![feature(range_is_empty,inclusive_range_syntax)] + /// #![feature(range_is_empty)] /// /// let mut r = 3..=5; /// for _ in r.by_ref() {} @@ -385,7 +381,6 @@ impl> RangeInclusive { /// The `..=end` syntax is a `RangeToInclusive`: /// /// ``` -/// #![feature(inclusive_range,inclusive_range_syntax)] /// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 }); /// ``` /// @@ -393,8 +388,6 @@ impl> RangeInclusive { /// `for` loop directly. This won't compile: /// /// ```compile_fail,E0277 -/// #![feature(inclusive_range_syntax)] -/// /// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>: /// // std::iter::Iterator` is not satisfied /// for i in ..=5 { @@ -406,8 +399,6 @@ impl> RangeInclusive { /// array elements up to and including the index indicated by `end`. /// /// ``` -/// #![feature(inclusive_range_syntax)] -/// /// let arr = [0, 1, 2, 3]; /// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive /// assert_eq!(arr[1..=2], [ 1,2 ]); @@ -417,16 +408,14 @@ impl> RangeInclusive { /// [`Iterator`]: ../iter/trait.IntoIterator.html /// [slicing index]: ../slice/trait.SliceIndex.html #[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] pub end: Idx, } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl fmt::Debug for RangeToInclusive { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "..={:?}", self.end) @@ -440,7 +429,7 @@ impl> RangeToInclusive { /// # Examples /// /// ``` - /// #![feature(range_contains,inclusive_range_syntax)] + /// #![feature(range_contains)] /// /// assert!( (..=5).contains(-1_000_000_000)); /// assert!( (..=5).contains(5)); @@ -453,3 +442,267 @@ impl> RangeToInclusive { // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// #![feature(collections_range)] +/// +/// use std::ops::Bound::*; +/// use std::ops::RangeBounds; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::ops::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +/// `RangeBounds` is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +pub trait RangeBounds { + /// Start index bound. + /// + /// Returns the start value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(collections_range)] + /// + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((..10).start(), Unbounded); + /// assert_eq!((3..10).start(), Included(&3)); + /// # } + /// ``` + fn start(&self) -> Bound<&T>; + + /// End index bound. + /// + /// Returns the end value as a `Bound`. + /// + /// # Examples + /// + /// ``` + /// #![feature(collections_range)] + /// + /// # fn main() { + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((3..).end(), Unbounded); + /// assert_eq!((3..10).end(), Excluded(&10)); + /// # } + /// ``` + fn end(&self) -> Bound<&T>; +} + +use self::Bound::{Excluded, Included, Unbounded}; + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for RangeFull { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for RangeFrom { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for RangeTo { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for Range { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Excluded(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for RangeInclusive { + fn start(&self) -> Bound<&T> { + Included(&self.start) + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for RangeToInclusive { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl RangeBounds for (Bound, Bound) { + fn start(&self) -> Bound<&T> { + match *self { + (Included(ref start), _) => Included(start), + (Excluded(ref start), _) => Excluded(start), + (Unbounded, _) => Unbounded, + } + } + + fn end(&self) -> Bound<&T> { + match *self { + (_, Included(ref end)) => Included(end), + (_, Excluded(ref end)) => Excluded(end), + (_, Unbounded) => Unbounded, + } + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { + fn start(&self) -> Bound<&T> { + self.0 + } + + fn end(&self) -> Bound<&T> { + self.1 + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl<'a, T> RangeBounds for RangeFrom<&'a T> { + fn start(&self) -> Bound<&T> { + Included(self.start) + } + fn end(&self) -> Bound<&T> { + Unbounded + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl<'a, T> RangeBounds for RangeTo<&'a T> { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl<'a, T> RangeBounds for Range<&'a T> { + fn start(&self) -> Bound<&T> { + Included(self.start) + } + fn end(&self) -> Bound<&T> { + Excluded(self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl<'a, T> RangeBounds for RangeInclusive<&'a T> { + fn start(&self) -> Bound<&T> { + Included(self.start) + } + fn end(&self) -> Bound<&T> { + Included(self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "might be replaced with `Into<_>` and a type containing two `Bound` values", + issue = "30877")] +impl<'a, T> RangeBounds for RangeToInclusive<&'a T> { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(self.end) + } +} diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index 81e5cb5c3504..ef6a8fb6a61c 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -20,7 +20,7 @@ any(from_method="from_error", from_method="from_ok"), from_desugaring="?"), message="the `?` operator can only be used in a \ - function that returns `Result` \ + function that returns `Result` or `Option` \ (or another type that implements `{Try}`)", label="cannot use the `?` operator in a function that returns `{Self}`"), on(all(from_method="into_result", from_desugaring="?"), diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 570f745f8330..61ef6798b2ef 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1188,6 +1188,16 @@ impl> FromIterator> for Option { None => None, } } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.found_none { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } } let mut adapter = Adapter { iter: iter.into_iter(), found_none: false }; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 6270e5892b3a..5a54de06b5ef 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -23,7 +23,7 @@ use fmt; use hash; use marker::{PhantomData, Unsize}; use mem; -use nonzero::NonZero; +#[allow(deprecated)] use nonzero::NonZero; use cmp::Ordering::{self, Less, Equal, Greater}; @@ -669,7 +669,7 @@ impl *const T { /// `mem::size_of::()` then the result of the division is rounded towards /// zero. /// - /// This function returns `None` if `T` is a zero-sized typed. + /// This function returns `None` if `T` is a zero-sized type. /// /// # Examples /// @@ -700,6 +700,124 @@ impl *const T { } } + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// This function is the inverse of [`offset`]. + /// + /// [`offset`]: #method.offset + /// [`wrapping_offset_from`]: #method.wrapping_offset_from + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined + /// Behavior: + /// + /// * Both the starting and other pointer must be either in bounds or one + /// byte past the end of the same allocated object. + /// + /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`. + /// + /// * The distance between the pointers, in bytes, must be an exact multiple + /// of the size of `T`. + /// + /// * The distance being in bounds cannot rely on "wrapping around" the address space. + /// + /// The compiler and standard library generally try to ensure allocations + /// never reach a size where an offset is a concern. For instance, `Vec` + /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so + /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe. + /// + /// Most platforms fundamentally can't even construct such an allocation. + /// For instance, no known 64-bit platform can ever serve a request + /// for 263 bytes due to page-table limitations or splitting the address space. + /// However, some 32-bit and 16-bit platforms may successfully serve a request for + /// more than `isize::MAX` bytes with things like Physical Address + /// Extension. As such, memory acquired directly from allocators or memory + /// mapped files *may* be too large to handle with this function. + /// + /// Consider using [`wrapping_offset_from`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_offset_from)] + /// + /// let a = [0; 5]; + /// let ptr1: *const i32 = &a[1]; + /// let ptr2: *const i32 = &a[3]; + /// unsafe { + /// assert_eq!(ptr2.offset_from(ptr1), 2); + /// assert_eq!(ptr1.offset_from(ptr2), -2); + /// assert_eq!(ptr1.offset(2), ptr2); + /// assert_eq!(ptr2.offset(-2), ptr1); + /// } + /// ``` + #[unstable(feature = "ptr_offset_from", issue = "41079")] + #[inline] + pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { + let pointee_size = mem::size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); + + // This is the same sequence that Clang emits for pointer subtraction. + // It can be neither `nsw` nor `nuw` because the input is treated as + // unsigned but then the output is treated as signed, so neither works. + let d = isize::wrapping_sub(self as _, origin as _); + intrinsics::exact_div(d, pointee_size as _) + } + + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// If the address different between the two pointers is not a multiple of + /// `mem::size_of::()` then the result of the division is rounded towards + /// zero. + /// + /// Though this method is safe for any two pointers, note that its result + /// will be mostly useless if the two pointers aren't into the same allocated + /// object, for example if they point to two different local variables. + /// + /// # Panics + /// + /// This function panics if `T` is a zero-sized type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_wrapping_offset_from)] + /// + /// let a = [0; 5]; + /// let ptr1: *const i32 = &a[1]; + /// let ptr2: *const i32 = &a[3]; + /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); + /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2); + /// assert_eq!(ptr1.wrapping_offset(2), ptr2); + /// assert_eq!(ptr2.wrapping_offset(-2), ptr1); + /// + /// let ptr1: *const i32 = 3 as _; + /// let ptr2: *const i32 = 13 as _; + /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); + /// ``` + #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[inline] + pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized { + let pointee_size = mem::size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); + + let d = isize::wrapping_sub(self as _, origin as _); + d.wrapping_div(pointee_size as _) + } + /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). /// /// `count` is in units of T; e.g. a `count` of 3 represents a pointer @@ -1316,7 +1434,7 @@ impl *mut T { /// `mem::size_of::()` then the result of the division is rounded towards /// zero. /// - /// This function returns `None` if `T` is a zero-sized typed. + /// This function returns `None` if `T` is a zero-sized type. /// /// # Examples /// @@ -1347,6 +1465,113 @@ impl *mut T { } } + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// This function is the inverse of [`offset`]. + /// + /// [`offset`]: #method.offset-1 + /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1 + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined + /// Behavior: + /// + /// * Both the starting and other pointer must be either in bounds or one + /// byte past the end of the same allocated object. + /// + /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`. + /// + /// * The distance between the pointers, in bytes, must be an exact multiple + /// of the size of `T`. + /// + /// * The distance being in bounds cannot rely on "wrapping around" the address space. + /// + /// The compiler and standard library generally try to ensure allocations + /// never reach a size where an offset is a concern. For instance, `Vec` + /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so + /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe. + /// + /// Most platforms fundamentally can't even construct such an allocation. + /// For instance, no known 64-bit platform can ever serve a request + /// for 263 bytes due to page-table limitations or splitting the address space. + /// However, some 32-bit and 16-bit platforms may successfully serve a request for + /// more than `isize::MAX` bytes with things like Physical Address + /// Extension. As such, memory acquired directly from allocators or memory + /// mapped files *may* be too large to handle with this function. + /// + /// Consider using [`wrapping_offset_from`] instead if these constraints are + /// difficult to satisfy. The only advantage of this method is that it + /// enables more aggressive compiler optimizations. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_offset_from)] + /// + /// let mut a = [0; 5]; + /// let ptr1: *mut i32 = &mut a[1]; + /// let ptr2: *mut i32 = &mut a[3]; + /// unsafe { + /// assert_eq!(ptr2.offset_from(ptr1), 2); + /// assert_eq!(ptr1.offset_from(ptr2), -2); + /// assert_eq!(ptr1.offset(2), ptr2); + /// assert_eq!(ptr2.offset(-2), ptr1); + /// } + /// ``` + #[unstable(feature = "ptr_offset_from", issue = "41079")] + #[inline] + pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { + (self as *const T).offset_from(origin) + } + + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// If the address different between the two pointers is not a multiple of + /// `mem::size_of::()` then the result of the division is rounded towards + /// zero. + /// + /// Though this method is safe for any two pointers, note that its result + /// will be mostly useless if the two pointers aren't into the same allocated + /// object, for example if they point to two different local variables. + /// + /// # Panics + /// + /// This function panics if `T` is a zero-sized type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_wrapping_offset_from)] + /// + /// let mut a = [0; 5]; + /// let ptr1: *mut i32 = &mut a[1]; + /// let ptr2: *mut i32 = &mut a[3]; + /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); + /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2); + /// assert_eq!(ptr1.wrapping_offset(2), ptr2); + /// assert_eq!(ptr2.wrapping_offset(-2), ptr1); + /// + /// let ptr1: *mut i32 = 3 as _; + /// let ptr2: *mut i32 = 13 as _; + /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2); + /// ``` + #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] + #[inline] + pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized { + (self as *const T).wrapping_offset_from(origin) + } + /// Computes the byte offset that needs to be applied in order to /// make the pointer aligned to `align`. /// If it is not possible to align the pointer, the implementation returns @@ -2285,6 +2510,7 @@ impl PartialOrd for *mut T { #[unstable(feature = "ptr_internals", issue = "0", reason = "use NonNull instead and consider PhantomData \ (if you also use #[may_dangle]), Send, and/or Sync")] +#[allow(deprecated)] pub struct Unique { pointer: NonZero<*const T>, // NOTE: this marker has no consequences for variance, but is necessary @@ -2332,6 +2558,7 @@ impl Unique { } #[unstable(feature = "ptr_internals", issue = "0")] +#[allow(deprecated)] impl Unique { /// Creates a new `Unique`. /// @@ -2339,17 +2566,21 @@ impl Unique { /// /// `ptr` must be non-null. pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData } + Unique { pointer: NonZero(ptr as _), _marker: PhantomData } } /// Creates a new `Unique` if `ptr` is non-null. pub fn new(ptr: *mut T) -> Option { - NonZero::new(ptr as *const T).map(|nz| Unique { pointer: nz, _marker: PhantomData }) + if !ptr.is_null() { + Some(Unique { pointer: NonZero(ptr as _), _marker: PhantomData }) + } else { + None + } } /// Acquires the underlying `*mut` pointer. pub fn as_ptr(self) -> *mut T { - self.pointer.get() as *mut T + self.pointer.0 as *mut T } /// Dereferences the content. @@ -2392,16 +2623,18 @@ impl fmt::Pointer for Unique { } #[unstable(feature = "ptr_internals", issue = "0")] +#[allow(deprecated)] impl<'a, T: ?Sized> From<&'a mut T> for Unique { fn from(reference: &'a mut T) -> Self { - Unique { pointer: NonZero::from(reference), _marker: PhantomData } + Unique { pointer: NonZero(reference as _), _marker: PhantomData } } } #[unstable(feature = "ptr_internals", issue = "0")] +#[allow(deprecated)] impl<'a, T: ?Sized> From<&'a T> for Unique { fn from(reference: &'a T) -> Self { - Unique { pointer: NonZero::from(reference), _marker: PhantomData } + Unique { pointer: NonZero(reference as _), _marker: PhantomData } } } @@ -2412,11 +2645,6 @@ impl<'a, T: ?Sized> From> for Unique { } } -/// Previous name of `NonNull`. -#[rustc_deprecated(since = "1.25.0", reason = "renamed to `NonNull`")] -#[unstable(feature = "shared", issue = "27730")] -pub type Shared = NonNull; - /// `*mut T` but non-zero and covariant. /// /// This is often the correct thing to use when building data structures using @@ -2425,7 +2653,7 @@ pub type Shared = NonNull; /// /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer /// is never dereferenced. This is so that enums may use this forbidden value -/// as a discriminant -- `Option>` has the same size as `NonNull`. +/// as a discriminant -- `Option>` has the same size as `*mut T`. /// However the pointer may still dangle if it isn't dereferenced. /// /// Unlike `*mut T`, `NonNull` is covariant over `T`. If this is incorrect @@ -2436,7 +2664,7 @@ pub type Shared = NonNull; /// provide a public API that follows the normal shared XOR mutable rules of Rust. #[stable(feature = "nonnull", since = "1.25.0")] pub struct NonNull { - pointer: NonZero<*const T>, + #[allow(deprecated)] pointer: NonZero<*const T>, } /// `NonNull` pointers are not `Send` because the data they reference may be aliased. @@ -2463,6 +2691,7 @@ impl NonNull { } } +#[allow(deprecated)] impl NonNull { /// Creates a new `NonNull`. /// @@ -2471,19 +2700,23 @@ impl NonNull { /// `ptr` must be non-null. #[stable(feature = "nonnull", since = "1.25.0")] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - NonNull { pointer: NonZero::new_unchecked(ptr) } + NonNull { pointer: NonZero(ptr as _) } } /// Creates a new `NonNull` if `ptr` is non-null. #[stable(feature = "nonnull", since = "1.25.0")] pub fn new(ptr: *mut T) -> Option { - NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz }) + if !ptr.is_null() { + Some(NonNull { pointer: NonZero(ptr as _) }) + } else { + None + } } /// Acquires the underlying `*mut` pointer. #[stable(feature = "nonnull", since = "1.25.0")] pub fn as_ptr(self) -> *mut T { - self.pointer.get() as *mut T + self.pointer.0 as *mut T } /// Dereferences the content. @@ -2581,15 +2814,17 @@ impl From> for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] +#[allow(deprecated)] impl<'a, T: ?Sized> From<&'a mut T> for NonNull { fn from(reference: &'a mut T) -> Self { - NonNull { pointer: NonZero::from(reference) } + NonNull { pointer: NonZero(reference as _) } } } #[stable(feature = "nonnull", since = "1.25.0")] +#[allow(deprecated)] impl<'a, T: ?Sized> From<&'a T> for NonNull { fn from(reference: &'a T) -> Self { - NonNull { pointer: NonZero::from(reference) } + NonNull { pointer: NonZero(reference as _) } } } diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 19fe4dd36b68..0f1b7cb8fcc0 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1039,7 +1039,7 @@ impl SliceIndex<[T]> for ops::RangeFull { } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -1080,7 +1080,7 @@ impl SliceIndex<[T]> for ops::RangeInclusive { } } -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[stable(feature = "inclusive_range", since = "1.26.0")] impl SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index e225c9522bc0..1185b7acaae1 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -165,6 +165,37 @@ Section: Creating a string /// /// [`String`]: ../../std/string/struct.String.html#method.from_utf8 /// [`&str`]: ../../std/str/fn.from_utf8.html +/// +/// # Examples +/// +/// This error type’s methods can be used to create functionality +/// similar to `String::from_utf8_lossy` without allocating heap memory: +/// +/// ``` +/// fn from_utf8_lossy(mut input: &[u8], mut push: F) where F: FnMut(&str) { +/// loop { +/// match ::std::str::from_utf8(input) { +/// Ok(valid) => { +/// push(valid); +/// break +/// } +/// Err(error) => { +/// let (valid, after_valid) = input.split_at(error.valid_up_to()); +/// unsafe { +/// push(::std::str::from_utf8_unchecked(valid)) +/// } +/// push("\u{FFFD}"); +/// +/// if let Some(invalid_sequence_length) = error.error_len() { +/// input = &after_valid[invalid_sequence_length..] +/// } else { +/// break +/// } +/// } +/// } +/// } +/// } +/// ``` #[derive(Copy, Eq, PartialEq, Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Utf8Error { @@ -1779,9 +1810,7 @@ mod traits { } } - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::Index> for str { type Output = str; @@ -1791,9 +1820,7 @@ mod traits { } } - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::Index> for str { type Output = str; @@ -1803,18 +1830,14 @@ mod traits { } } - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { index.index_mut(self) } } - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { @@ -1997,9 +2020,7 @@ mod traits { } } - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] @@ -2042,9 +2063,7 @@ mod traits { - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] + #[stable(feature = "inclusive_range", since = "1.26.0")] impl SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 25827edee7d9..d336934ec721 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -205,8 +205,11 @@ pub enum Ordering { /// [`Release`]: http://llvm.org/docs/Atomics.html#release #[stable(feature = "rust1", since = "1.0.0")] Acquire, - /// When coupled with a load, uses [`Acquire`] ordering, and with a store - /// [`Release`] ordering. + /// Has the effects of both [`Acquire`] and [`Release`] together. + /// + /// This ordering is only applicable for operations that combine both loads and stores. + /// + /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering. /// /// [`Acquire`]: http://llvm.org/docs/Atomics.html#acquire /// [`Release`]: http://llvm.org/docs/Atomics.html#release @@ -948,6 +951,8 @@ macro_rules! atomic_int { $stable_from:meta, $stable_nand:meta, $s_int_type:expr, $int_ref:expr, + $extra_feature:expr, + $min_fn:ident, $max_fn:ident, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. /// @@ -959,12 +964,7 @@ macro_rules! atomic_int { /// ). For more about the differences between atomic types and /// non-atomic types, please see the [module-level documentation]. /// - /// Please note that examples are shared between atomic variants of - /// primitive integer types, so it's normal that they are all - /// demonstrating [`AtomicIsize`]. - /// /// [module-level documentation]: index.html - /// [`AtomicIsize`]: struct.AtomicIsize.html #[$stable] pub struct $atomic_type { v: UnsafeCell<$int_type>, @@ -1001,396 +1001,549 @@ macro_rules! atomic_int { unsafe impl Sync for $atomic_type {} impl $atomic_type { - /// Creates a new atomic integer. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicIsize; - /// - /// let atomic_forty_two = AtomicIsize::new(42); - /// ``` - #[inline] - #[$stable] - pub const fn new(v: $int_type) -> Self { - $atomic_type {v: UnsafeCell::new(v)} - } + doc_comment! { + concat!("Creates a new atomic integer. - /// Returns a mutable reference to the underlying integer. - /// - /// This is safe because the mutable reference guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let mut some_isize = AtomicIsize::new(10); - /// assert_eq!(*some_isize.get_mut(), 10); - /// *some_isize.get_mut() = 5; - /// assert_eq!(some_isize.load(Ordering::SeqCst), 5); - /// ``` - #[inline] - #[$stable_access] - pub fn get_mut(&mut self) -> &mut $int_type { - unsafe { &mut *self.v.get() } - } +# Examples - /// Consumes the atomic and returns the contained value. - /// - /// This is safe because passing `self` by value guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicIsize; - /// - /// let some_isize = AtomicIsize::new(5); - /// assert_eq!(some_isize.into_inner(), 5); - /// ``` - #[inline] - #[$stable_access] - pub fn into_inner(self) -> $int_type { - self.v.into_inner() - } +``` +", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; - /// Loads a value from the atomic integer. - /// - /// `load` takes an [`Ordering`] argument which describes the memory ordering of this - /// operation. - /// - /// # Panics - /// - /// Panics if `order` is [`Release`] or [`AcqRel`]. - /// - /// [`Ordering`]: enum.Ordering.html - /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.load(Ordering::Relaxed), 5); - /// ``` - #[inline] - #[$stable] - pub fn load(&self, order: Ordering) -> $int_type { - unsafe { atomic_load(self.v.get(), order) } - } - - /// Stores a value into the atomic integer. - /// - /// `store` takes an [`Ordering`] argument which describes the memory ordering of this - /// operation. - /// - /// [`Ordering`]: enum.Ordering.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// some_isize.store(10, Ordering::Relaxed); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// ``` - /// - /// # Panics - /// - /// Panics if `order` is [`Acquire`] or [`AcqRel`]. - /// - /// [`Acquire`]: enum.Ordering.html#variant.Acquire - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - #[inline] - #[$stable] - pub fn store(&self, val: $int_type, order: Ordering) { - unsafe { atomic_store(self.v.get(), val, order); } - } - - /// Stores a value into the atomic integer, returning the previous value. - /// - /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this - /// operation. - /// - /// [`Ordering`]: enum.Ordering.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5); - /// ``` - #[inline] - #[$stable] - pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_swap(self.v.get(), val, order) } - } - - /// Stores a value into the atomic integer if the current value is the same as the - /// `current` value. - /// - /// The return value is always the previous value. If it is equal to `current`, then the - /// value was updated. - /// - /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory - /// ordering of this operation. - /// - /// [`Ordering`]: enum.Ordering.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// - /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// ``` - #[inline] - #[$stable] - pub fn compare_and_swap(&self, - current: $int_type, - new: $int_type, - order: Ordering) -> $int_type { - match self.compare_exchange(current, - new, - order, - strongest_failure_ordering(order)) { - Ok(x) => x, - Err(x) => x, +let atomic_forty_two = ", stringify!($atomic_type), "::new(42); +```"), + #[inline] + #[$stable] + pub const fn new(v: $int_type) -> Self { + $atomic_type {v: UnsafeCell::new(v)} } } - /// Stores a value into the atomic integer if the current value is the same as the - /// `current` value. - /// - /// The return value is a result indicating whether the new value was written and - /// containing the previous value. On success this value is guaranteed to be equal to - /// `current`. - /// - /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if - /// the operation succeeds while the second describes the required ordering when - /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and - /// must be equivalent or weaker than the success ordering. - /// - /// [`Ordering`]: enum.Ordering.html - /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let some_isize = AtomicIsize::new(5); - /// - /// assert_eq!(some_isize.compare_exchange(5, 10, - /// Ordering::Acquire, - /// Ordering::Relaxed), - /// Ok(5)); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// - /// assert_eq!(some_isize.compare_exchange(6, 12, - /// Ordering::SeqCst, - /// Ordering::Acquire), - /// Err(10)); - /// assert_eq!(some_isize.load(Ordering::Relaxed), 10); - /// ``` - #[inline] - #[$stable_cxchg] - pub fn compare_exchange(&self, - current: $int_type, - new: $int_type, - success: Ordering, - failure: Ordering) -> Result<$int_type, $int_type> { - unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } - } + doc_comment! { + concat!("Returns a mutable reference to the underlying integer. - /// Stores a value into the atomic integer if the current value is the same as the - /// `current` value. - /// - /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even - /// when the comparison succeeds, which can result in more efficient code on some - /// platforms. The return value is a result indicating whether the new value was - /// written and containing the previous value. - /// - /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering if the - /// operation succeeds while the second describes the required ordering when the - /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and - /// must be equivalent or weaker than the success ordering. - /// - /// [`compare_exchange`]: #method.compare_exchange - /// [`Ordering`]: enum.Ordering.html - /// [`Release`]: enum.Ordering.html#variant.Release - /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let val = AtomicIsize::new(4); - /// - /// let mut old = val.load(Ordering::Relaxed); - /// loop { - /// let new = old * 2; - /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { - /// Ok(_) => break, - /// Err(x) => old = x, - /// } - /// } - /// ``` - #[inline] - #[$stable_cxchg] - pub fn compare_exchange_weak(&self, - current: $int_type, - new: $int_type, - success: Ordering, - failure: Ordering) -> Result<$int_type, $int_type> { - unsafe { - atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) +This is safe because the mutable reference guarantees that no other threads are +concurrently accessing the atomic data. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let mut some_var = ", stringify!($atomic_type), "::new(10); +assert_eq!(*some_var.get_mut(), 10); +*some_var.get_mut() = 5; +assert_eq!(some_var.load(Ordering::SeqCst), 5); +```"), + #[inline] + #[$stable_access] + pub fn get_mut(&mut self) -> &mut $int_type { + unsafe { &mut *self.v.get() } } } - /// Adds to the current value, returning the previous value. - /// - /// This operation wraps around on overflow. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0); - /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); - /// assert_eq!(foo.load(Ordering::SeqCst), 10); - /// ``` - #[inline] - #[$stable] - pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_add(self.v.get(), val, order) } + doc_comment! { + concat!("Consumes the atomic and returns the contained value. + +This is safe because passing `self` by value guarantees that no other threads are +concurrently accessing the atomic data. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; + +let some_var = ", stringify!($atomic_type), "::new(5); +assert_eq!(some_var.into_inner(), 5); +```"), + #[inline] + #[$stable_access] + pub fn into_inner(self) -> $int_type { + self.v.into_inner() + } } - /// Subtracts from the current value, returning the previous value. - /// - /// This operation wraps around on overflow. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0); - /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0); - /// assert_eq!(foo.load(Ordering::SeqCst), -10); - /// ``` - #[inline] - #[$stable] - pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_sub(self.v.get(), val, order) } + doc_comment! { + concat!("Loads a value from the atomic integer. + +`load` takes an [`Ordering`] argument which describes the memory ordering of this operation. + +# Panics + +Panics if `order` is [`Release`] or [`AcqRel`]. + +[`Ordering`]: enum.Ordering.html +[`Release`]: enum.Ordering.html#variant.Release +[`AcqRel`]: enum.Ordering.html#variant.AcqRel + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.load(Ordering::Relaxed), 5); +```"), + #[inline] + #[$stable] + pub fn load(&self, order: Ordering) -> $int_type { + unsafe { atomic_load(self.v.get(), order) } + } } - /// Bitwise "and" with the current value. - /// - /// Performs a bitwise "and" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0b101101); - /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); - /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001); - #[inline] - #[$stable] - pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_and(self.v.get(), val, order) } + doc_comment! { + concat!("Stores a value into the atomic integer. + +`store` takes an [`Ordering`] argument which describes the memory ordering of this operation. + +[`Ordering`]: enum.Ordering.html + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +some_var.store(10, Ordering::Relaxed); +assert_eq!(some_var.load(Ordering::Relaxed), 10); +``` + +# Panics + +Panics if `order` is [`Acquire`] or [`AcqRel`]. + +[`Acquire`]: enum.Ordering.html#variant.Acquire +[`AcqRel`]: enum.Ordering.html#variant.AcqRel"), + #[inline] + #[$stable] + pub fn store(&self, val: $int_type, order: Ordering) { + unsafe { atomic_store(self.v.get(), val, order); } + } } - /// Bitwise "nand" with the current value. - /// - /// Performs a bitwise "nand" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// #![feature(atomic_nand)] - /// - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0xf731); - /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731); - /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f)); - #[inline] - #[$stable_nand] - pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_nand(self.v.get(), val, order) } + doc_comment! { + concat!("Stores a value into the atomic integer, returning the previous value. + +`swap` takes an [`Ordering`] argument which describes the memory ordering of this operation. + +[`Ordering`]: enum.Ordering.html + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); +```"), + #[inline] + #[$stable] + pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_swap(self.v.get(), val, order) } + } } - /// Bitwise "or" with the current value. - /// - /// Performs a bitwise "or" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0b101101); - /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); - /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111); - #[inline] - #[$stable] - pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_or(self.v.get(), val, order) } + doc_comment! { + concat!("Stores a value into the atomic integer if the current value is the same as +the `current` value. + +The return value is always the previous value. If it is equal to `current`, then the +value was updated. + +`compare_and_swap` also takes an [`Ordering`] argument which describes the memory +ordering of this operation. + +[`Ordering`]: enum.Ordering.html + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5); +assert_eq!(some_var.load(Ordering::Relaxed), 10); + +assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10); +assert_eq!(some_var.load(Ordering::Relaxed), 10); +```"), + #[inline] + #[$stable] + pub fn compare_and_swap(&self, + current: $int_type, + new: $int_type, + order: Ordering) -> $int_type { + match self.compare_exchange(current, + new, + order, + strongest_failure_ordering(order)) { + Ok(x) => x, + Err(x) => x, + } + } } - /// Bitwise "xor" with the current value. - /// - /// Performs a bitwise "xor" operation on the current value and the argument `val`, and - /// sets the new value to the result. - /// - /// Returns the previous value. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{AtomicIsize, Ordering}; - /// - /// let foo = AtomicIsize::new(0b101101); - /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); - /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110); - #[inline] - #[$stable] - pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { - unsafe { atomic_xor(self.v.get(), val, order) } + doc_comment! { + concat!("Stores a value into the atomic integer if the current value is the same as +the `current` value. + +The return value is a result indicating whether the new value was written and +containing the previous value. On success this value is guaranteed to be equal to +`current`. + +`compare_exchange` takes two [`Ordering`] arguments to describe the memory +ordering of this operation. The first describes the required ordering if +the operation succeeds while the second describes the required ordering when +the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and +must be equivalent or weaker than the success ordering. + +[`Ordering`]: enum.Ordering.html +[`Release`]: enum.Ordering.html#variant.Release +[`AcqRel`]: enum.Ordering.html#variant.AcqRel + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let some_var = ", stringify!($atomic_type), "::new(5); + +assert_eq!(some_var.compare_exchange(5, 10, + Ordering::Acquire, + Ordering::Relaxed), + Ok(5)); +assert_eq!(some_var.load(Ordering::Relaxed), 10); + +assert_eq!(some_var.compare_exchange(6, 12, + Ordering::SeqCst, + Ordering::Acquire), + Err(10)); +assert_eq!(some_var.load(Ordering::Relaxed), 10); +```"), + #[inline] + #[$stable_cxchg] + pub fn compare_exchange(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } + } } + + doc_comment! { + concat!("Stores a value into the atomic integer if the current value is the same as +the `current` value. + +Unlike [`compare_exchange`], this function is allowed to spuriously fail even +when the comparison succeeds, which can result in more efficient code on some +platforms. The return value is a result indicating whether the new value was +written and containing the previous value. + +`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory +ordering of this operation. The first describes the required ordering if the +operation succeeds while the second describes the required ordering when the +operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and +must be equivalent or weaker than the success ordering. + +[`compare_exchange`]: #method.compare_exchange +[`Ordering`]: enum.Ordering.html +[`Release`]: enum.Ordering.html#variant.Release +[`AcqRel`]: enum.Ordering.html#variant.AcqRel + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let val = ", stringify!($atomic_type), "::new(4); + +let mut old = val.load(Ordering::Relaxed); +loop { + let new = old * 2; + match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { + Ok(_) => break, + Err(x) => old = x, + } +} +```"), + #[inline] + #[$stable_cxchg] + pub fn compare_exchange_weak(&self, + current: $int_type, + new: $int_type, + success: Ordering, + failure: Ordering) -> Result<$int_type, $int_type> { + unsafe { + atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) + } + } + } + + doc_comment! { + concat!("Adds to the current value, returning the previous value. + +This operation wraps around on overflow. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0); +assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); +assert_eq!(foo.load(Ordering::SeqCst), 10); +```"), + #[inline] + #[$stable] + pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_add(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Subtracts from the current value, returning the previous value. + +This operation wraps around on overflow. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(20); +assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); +assert_eq!(foo.load(Ordering::SeqCst), 10); +```"), + #[inline] + #[$stable] + pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_sub(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Bitwise \"and\" with the current value. + +Performs a bitwise \"and\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0b101101); +assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); +assert_eq!(foo.load(Ordering::SeqCst), 0b100001); +```"), + #[inline] + #[$stable] + pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_and(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Bitwise \"nand\" with the current value. + +Performs a bitwise \"nand\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "#![feature(atomic_nand)] + +use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0x13); +assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); +assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); +```"), + #[inline] + #[$stable_nand] + pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_nand(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Bitwise \"or\" with the current value. + +Performs a bitwise \"or\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0b101101); +assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); +assert_eq!(foo.load(Ordering::SeqCst), 0b111111); +```"), + #[inline] + #[$stable] + pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_or(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Bitwise \"xor\" with the current value. + +Performs a bitwise \"xor\" operation on the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(0b101101); +assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); +assert_eq!(foo.load(Ordering::SeqCst), 0b011110); +```"), + #[inline] + #[$stable] + pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { atomic_xor(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Fetches the value, and applies a function to it that returns an optional +new value. Returns a `Result` (`Ok(_)` if the function returned `Some(_)`, else `Err(_)`) of the +previous value. + +Note: This may call the function multiple times if the value has been changed from other threads in +the meantime, as long as the function returns `Some(_)`, but the function will have been applied +but once to the stored value. + +# Examples + +```rust +#![feature(no_more_cas)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let x = ", stringify!($atomic_type), "::new(7); +assert_eq!(x.fetch_update(|_| None, Ordering::SeqCst, Ordering::SeqCst), Err(7)); +assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(7)); +assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(8)); +assert_eq!(x.load(Ordering::SeqCst), 9); +```"), + #[inline] + #[unstable(feature = "no_more_cas", + reason = "no more CAS loops in user code", + issue = "48655")] + pub fn fetch_update(&self, + mut f: F, + fetch_order: Ordering, + set_order: Ordering) -> Result<$int_type, $int_type> + where F: FnMut($int_type) -> Option<$int_type> { + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev + } + } + Err(prev) + } + } + + doc_comment! { + concat!("Maximum with the current value. + +Finds the maximum of the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); +assert_eq!(foo.load(Ordering::SeqCst), 42); +``` + +If you want to obtain the maximum value in one step, you can use the following: + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +let bar = 42; +let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); +assert!(max_foo == 42); +```"), + #[inline] + #[unstable(feature = "atomic_min_max", + reason = "easier and faster min/max than writing manual CAS loop", + issue = "48655")] + pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { $max_fn(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Minimum with the current value. + +Finds the minimum of the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); +assert_eq!(foo.load(Ordering::Relaxed), 23); +assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); +assert_eq!(foo.load(Ordering::Relaxed), 22); +``` + +If you want to obtain the minimum value in one step, you can use the following: + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +let bar = 12; +let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); +assert_eq!(min_foo, 12); +```"), + #[inline] + #[unstable(feature = "atomic_min_max", + reason = "easier and faster min/max than writing manual CAS loop", + issue = "48655")] + pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { $min_fn(self.v.get(), val, order) } + } + } + } } } @@ -1404,6 +1557,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i8", "../../../std/primitive.i8.html", + "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i8 AtomicI8 ATOMIC_I8_INIT } #[cfg(target_has_atomic = "8")] @@ -1415,6 +1570,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u8", "../../../std/primitive.u8.html", + "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u8 AtomicU8 ATOMIC_U8_INIT } #[cfg(target_has_atomic = "16")] @@ -1426,6 +1583,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i16", "../../../std/primitive.i16.html", + "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i16 AtomicI16 ATOMIC_I16_INIT } #[cfg(target_has_atomic = "16")] @@ -1437,6 +1596,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u16", "../../../std/primitive.u16.html", + "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u16 AtomicU16 ATOMIC_U16_INIT } #[cfg(target_has_atomic = "32")] @@ -1448,6 +1609,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i32", "../../../std/primitive.i32.html", + "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i32 AtomicI32 ATOMIC_I32_INIT } #[cfg(target_has_atomic = "32")] @@ -1459,6 +1622,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u32", "../../../std/primitive.u32.html", + "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u32 AtomicU32 ATOMIC_U32_INIT } #[cfg(target_has_atomic = "64")] @@ -1470,6 +1635,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "i64", "../../../std/primitive.i64.html", + "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i64 AtomicI64 ATOMIC_I64_INIT } #[cfg(target_has_atomic = "64")] @@ -1481,6 +1648,8 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "atomic_nand", issue = "13226"), "u64", "../../../std/primitive.u64.html", + "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u64 AtomicU64 ATOMIC_U64_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1492,6 +1661,8 @@ atomic_int!{ stable(feature = "atomic_from", since = "1.23.0"), unstable(feature = "atomic_nand", issue = "13226"), "isize", "../../../std/primitive.isize.html", + "", + atomic_min, atomic_max, isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1503,6 +1674,8 @@ atomic_int!{ stable(feature = "atomic_from", since = "1.23.0"), unstable(feature = "atomic_nand", issue = "13226"), "usize", "../../../std/primitive.usize.html", + "", + atomic_umin, atomic_umax, usize AtomicUsize ATOMIC_USIZE_INIT } @@ -1680,6 +1853,58 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { } } +/// returns the max value (signed comparison) +#[inline] +unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_max_acq(dst, val), + Release => intrinsics::atomic_max_rel(dst, val), + AcqRel => intrinsics::atomic_max_acqrel(dst, val), + Relaxed => intrinsics::atomic_max_relaxed(dst, val), + SeqCst => intrinsics::atomic_max(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + +/// returns the min value (signed comparison) +#[inline] +unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_min_acq(dst, val), + Release => intrinsics::atomic_min_rel(dst, val), + AcqRel => intrinsics::atomic_min_acqrel(dst, val), + Relaxed => intrinsics::atomic_min_relaxed(dst, val), + SeqCst => intrinsics::atomic_min(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + +/// returns the max value (signed comparison) +#[inline] +unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_umax_acq(dst, val), + Release => intrinsics::atomic_umax_rel(dst, val), + AcqRel => intrinsics::atomic_umax_acqrel(dst, val), + Relaxed => intrinsics::atomic_umax_relaxed(dst, val), + SeqCst => intrinsics::atomic_umax(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + +/// returns the min value (signed comparison) +#[inline] +unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_umin_acq(dst, val), + Release => intrinsics::atomic_umin_rel(dst, val), + AcqRel => intrinsics::atomic_umin_acqrel(dst, val), + Relaxed => intrinsics::atomic_umin_relaxed(dst, val), + SeqCst => intrinsics::atomic_umin(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + /// An atomic fence. /// /// Depending on the specified order, a fence prevents the compiler and CPU from diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs new file mode 100644 index 000000000000..950222dbcfa3 --- /dev/null +++ b/src/libcore/tests/ascii.rs @@ -0,0 +1,357 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::char::from_u32; + +#[test] +fn test_is_ascii() { + assert!(b"".is_ascii()); + assert!(b"banana\0\x7F".is_ascii()); + assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii())); + assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii()); + assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii())); + assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii())); + + assert!("".is_ascii()); + assert!("banana\0\u{7F}".is_ascii()); + assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii())); + assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii())); + assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii())); +} + +#[test] +fn test_to_ascii_uppercase() { + assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL"); + assert_eq!("hıKß".to_ascii_uppercase(), "HıKß"); + + for i in 0..501 { + let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } + else { i }; + assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(), + (from_u32(upper).unwrap()).to_string()); + } +} + +#[test] +fn test_to_ascii_lowercase() { + assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl"); + // Dotted capital I, Kelvin sign, Sharp S. + assert_eq!("HİKß".to_ascii_lowercase(), "hİKß"); + + for i in 0..501 { + let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } + else { i }; + assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(), + (from_u32(lower).unwrap()).to_string()); + } +} + +#[test] +fn test_make_ascii_lower_case() { + macro_rules! test { + ($from: expr, $to: expr) => { + { + let mut x = $from; + x.make_ascii_lowercase(); + assert_eq!(x, $to); + } + } + } + test!(b'A', b'a'); + test!(b'a', b'a'); + test!(b'!', b'!'); + test!('A', 'a'); + test!('À', 'À'); + test!('a', 'a'); + test!('!', '!'); + test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89"); + test!("HİKß".to_string(), "hİKß"); +} + + +#[test] +fn test_make_ascii_upper_case() { + macro_rules! test { + ($from: expr, $to: expr) => { + { + let mut x = $from; + x.make_ascii_uppercase(); + assert_eq!(x, $to); + } + } + } + test!(b'a', b'A'); + test!(b'A', b'A'); + test!(b'!', b'!'); + test!('a', 'A'); + test!('à', 'à'); + test!('A', 'A'); + test!('!', '!'); + test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9"); + test!("hıKß".to_string(), "HıKß"); + + let mut x = "Hello".to_string(); + x[..3].make_ascii_uppercase(); // Test IndexMut on String. + assert_eq!(x, "HELlo") +} + +#[test] +fn test_eq_ignore_ascii_case() { + assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl")); + assert!(!"Ürl".eq_ignore_ascii_case("ürl")); + // Dotted capital I, Kelvin sign, Sharp S. + assert!("HİKß".eq_ignore_ascii_case("hİKß")); + assert!(!"İ".eq_ignore_ascii_case("i")); + assert!(!"K".eq_ignore_ascii_case("k")); + assert!(!"ß".eq_ignore_ascii_case("s")); + + for i in 0..501 { + let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } + else { i }; + assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case( + &from_u32(lower).unwrap().to_string())); + } +} + +#[test] +fn inference_works() { + let x = "a".to_string(); + x.eq_ignore_ascii_case("A"); +} + +// Shorthands used by the is_ascii_* tests. +macro_rules! assert_all { + ($what:ident, $($str:tt),+) => {{ + $( + for b in $str.chars() { + if !b.$what() { + panic!("expected {}({}) but it isn't", + stringify!($what), b); + } + } + for b in $str.as_bytes().iter() { + if !b.$what() { + panic!("expected {}(0x{:02x})) but it isn't", + stringify!($what), b); + } + } + )+ + }}; + ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+)) +} +macro_rules! assert_none { + ($what:ident, $($str:tt),+) => {{ + $( + for b in $str.chars() { + if b.$what() { + panic!("expected not-{}({}) but it is", + stringify!($what), b); + } + } + for b in $str.as_bytes().iter() { + if b.$what() { + panic!("expected not-{}(0x{:02x})) but it is", + stringify!($what), b); + } + } + )* + }}; + ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+)) +} + +#[test] +fn test_is_ascii_alphabetic() { + assert_all!(is_ascii_alphabetic, + "", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + ); + assert_none!(is_ascii_alphabetic, + "0123456789", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_uppercase() { + assert_all!(is_ascii_uppercase, + "", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + ); + assert_none!(is_ascii_uppercase, + "abcdefghijklmnopqrstuvwxyz", + "0123456789", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_lowercase() { + assert_all!(is_ascii_lowercase, + "abcdefghijklmnopqrstuvwxyz", + ); + assert_none!(is_ascii_lowercase, + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "0123456789", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_alphanumeric() { + assert_all!(is_ascii_alphanumeric, + "", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "0123456789", + ); + assert_none!(is_ascii_alphanumeric, + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_digit() { + assert_all!(is_ascii_digit, + "", + "0123456789", + ); + assert_none!(is_ascii_digit, + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_hexdigit() { + assert_all!(is_ascii_hexdigit, + "", + "0123456789", + "abcdefABCDEF", + ); + assert_none!(is_ascii_hexdigit, + "ghijklmnopqrstuvwxyz", + "GHIJKLMNOQPRSTUVWXYZ", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_punctuation() { + assert_all!(is_ascii_punctuation, + "", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ); + assert_none!(is_ascii_punctuation, + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "0123456789", + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_graphic() { + assert_all!(is_ascii_graphic, + "", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "0123456789", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ); + assert_none!(is_ascii_graphic, + " \t\n\x0c\r", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_whitespace() { + assert_all!(is_ascii_whitespace, + "", + " \t\n\x0c\r", + ); + assert_none!(is_ascii_whitespace, + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "0123456789", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x0b\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); +} + +#[test] +fn test_is_ascii_control() { + assert_all!(is_ascii_control, + "", + "\x00\x01\x02\x03\x04\x05\x06\x07", + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + "\x10\x11\x12\x13\x14\x15\x16\x17", + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + "\x7f", + ); + assert_none!(is_ascii_control, + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOQPRSTUVWXYZ", + "0123456789", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + " ", + ); +} diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs index 4ddedd910048..bc205ec0582e 100644 --- a/src/libcore/tests/fmt/num.rs +++ b/src/libcore/tests/fmt/num.rs @@ -150,3 +150,9 @@ fn test_format_int_twos_complement() { assert!(format!("{}", i32::MIN) == "-2147483648"); assert!(format!("{}", i64::MIN) == "-9223372036854775808"); } + +#[test] +fn test_format_debug_hex() { + assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]"); + assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]"); +} diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs index c6dd41798f2a..bad858011e96 100644 --- a/src/libcore/tests/hash/sip.rs +++ b/src/libcore/tests/hash/sip.rs @@ -11,7 +11,7 @@ #![allow(deprecated)] use core::hash::{Hash, Hasher}; -use core::hash::{SipHasher, SipHasher13, SipHasher24}; +use core::hash::{SipHasher, SipHasher13}; use core::{slice, mem}; // Hash just the bytes of the slice, without length prefix @@ -224,14 +224,14 @@ fn test_siphash_2_4() { let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; let mut buf = Vec::new(); let mut t = 0; - let mut state_inc = SipHasher24::new_with_keys(k0, k1); + let mut state_inc = SipHasher::new_with_keys(k0, k1); while t < 64 { let vec = u8to64_le!(vecs[t], 0); - let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf)); + let out = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf)); assert_eq!(vec, out); - let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf)); + let full = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf)); let i = state_inc.finish(); assert_eq!(full, i); @@ -322,13 +322,13 @@ fn test_hash_no_concat_alias() { #[test] fn test_write_short_works() { let test_usize = 0xd0c0b0a0usize; - let mut h1 = SipHasher24::new(); + let mut h1 = SipHasher::new(); h1.write_usize(test_usize); h1.write(b"bytes"); h1.write(b"string"); h1.write_u8(0xFFu8); h1.write_u8(0x01u8); - let mut h2 = SipHasher24::new(); + let mut h2 = SipHasher::new(); h2.write(unsafe { slice::from_raw_parts(&test_usize as *const _ as *const u8, mem::size_of::()) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index a962efadd64e..2abac0cf1d5b 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1146,6 +1146,33 @@ fn test_find() { assert!(v.iter().find(|&&x| x % 12 == 0).is_none()); } +#[test] +fn test_find_map() { + let xs: &[isize] = &[]; + assert_eq!(xs.iter().find_map(half_if_even), None); + let xs: &[isize] = &[3, 5]; + assert_eq!(xs.iter().find_map(half_if_even), None); + let xs: &[isize] = &[4, 5]; + assert_eq!(xs.iter().find_map(half_if_even), Some(2)); + let xs: &[isize] = &[3, 6]; + assert_eq!(xs.iter().find_map(half_if_even), Some(3)); + + let xs: &[isize] = &[1, 2, 3, 4, 5, 6, 7]; + let mut iter = xs.iter(); + assert_eq!(iter.find_map(half_if_even), Some(1)); + assert_eq!(iter.find_map(half_if_even), Some(2)); + assert_eq!(iter.find_map(half_if_even), Some(3)); + assert_eq!(iter.next(), Some(&7)); + + fn half_if_even(x: &isize) -> Option { + if x % 2 == 0 { + Some(x / 2) + } else { + None + } + } +} + #[test] fn test_position() { let v = &[1, 3, 9, 27, 103, 14, 11]; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index a9c5683e0ef7..de7211e718c9 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -10,6 +10,7 @@ #![deny(warnings)] +#![feature(ascii_ctype)] #![feature(box_syntax)] #![feature(core_float)] #![feature(core_private_bignum)] @@ -20,39 +21,39 @@ #![feature(fixed_size_array)] #![feature(flt2dec)] #![feature(fmt_internals)] +#![feature(hashmap_internals)] #![feature(iterator_step_by)] -#![feature(i128_type)] -#![feature(inclusive_range)] -#![feature(inclusive_range_syntax)] -#![feature(iterator_try_fold)] +#![cfg_attr(stage0, feature(i128_type))] +#![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(iterator_flatten)] -#![feature(conservative_impl_trait)] -#![feature(iter_rfind)] -#![feature(iter_rfold)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] #![feature(iterator_repeat_with)] #![feature(nonzero)] #![feature(pattern)] #![feature(range_is_empty)] #![feature(raw)] #![feature(refcell_replace_swap)] -#![feature(sip_hash_13)] #![feature(slice_patterns)] +#![feature(slice_rotate)] #![feature(sort_internals)] #![feature(specialization)] #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] -#![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] #![feature(atomic_nand)] #![feature(reverse_bits)] +#![feature(inclusive_range_fields)] +#![feature(iterator_find_map)] extern crate core; extern crate test; +extern crate rand; mod any; mod array; +mod ascii; mod atomic; mod cell; mod char; diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index a795dd575043..8d39298bac3d 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::nonzero::NonZero; +use core::num::NonZeroU32; use core::option::Option; use core::option::Option::{Some, None}; use std::mem::size_of; @@ -16,28 +16,28 @@ use std::mem::size_of; #[test] fn test_create_nonzero_instance() { let _a = unsafe { - NonZero::new_unchecked(21) + NonZeroU32::new_unchecked(21) }; } #[test] fn test_size_nonzero_in_option() { - assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::(), size_of::>()); } #[test] fn test_match_on_nonzero_option() { let a = Some(unsafe { - NonZero::new_unchecked(42) + NonZeroU32::new_unchecked(42) }); match a { Some(val) => assert_eq!(val.get(), 42), - None => panic!("unexpected None while matching on Some(NonZero(_))") + None => panic!("unexpected None while matching on Some(NonZeroU32(_))") } - match unsafe { Some(NonZero::new_unchecked(43)) } { + match unsafe { Some(NonZeroU32::new_unchecked(43)) } { Some(val) => assert_eq!(val.get(), 43), - None => panic!("unexpected None while matching on Some(NonZero(_))") + None => panic!("unexpected None while matching on Some(NonZeroU32(_))") } } @@ -98,3 +98,26 @@ fn test_match_option_string() { None => panic!("unexpected None while matching on Some(String { ... })") } } + +mod atom { + use core::num::NonZeroU32; + + #[derive(PartialEq, Eq)] + pub struct Atom { + index: NonZeroU32, // private + } + pub const FOO_ATOM: Atom = Atom { index: unsafe { NonZeroU32::new_unchecked(7) } }; +} + +macro_rules! atom { + ("foo") => { atom::FOO_ATOM } +} + +#[test] +fn test_match_nonzero_const_pattern() { + match atom!("foo") { + // Using as a pattern is supported by the compiler: + atom!("foo") => {} + _ => panic!("Expected the const item as a pattern to match.") + } +} diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs index ef0178815f98..04567e25e25b 100644 --- a/src/libcore/tests/num/flt2dec/mod.rs +++ b/src/libcore/tests/num/flt2dec/mod.rs @@ -23,6 +23,7 @@ mod strategy { mod dragon; mod grisu; } +mod random; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { diff --git a/src/test/run-pass-fulldeps/flt2dec.rs b/src/libcore/tests/num/flt2dec/random.rs similarity index 98% rename from src/test/run-pass-fulldeps/flt2dec.rs rename to src/libcore/tests/num/flt2dec/random.rs index 3db0644d1ef3..315ac4d7d99f 100644 --- a/src/test/run-pass-fulldeps/flt2dec.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -8,12 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--test - -#![feature(rustc_private, flt2dec)] - -extern crate core; -extern crate rand; +#![cfg(not(target_arch = "wasm32"))] use std::i16; use std::mem; @@ -24,8 +19,9 @@ use core::num::flt2dec::strategy::grisu::format_exact_opt; use core::num::flt2dec::strategy::grisu::format_shortest_opt; use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; -use rand::{Rand, XorShiftRng}; +use rand::{self, Rand, XorShiftRng}; use rand::distributions::{IndependentSample, Range}; + pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { FullDecoded::Finite(decoded) => decoded, @@ -161,3 +157,4 @@ fn exact_f64_random_equivalence_test() { |d, buf| fallback(d, buf, i16::MIN), k, 1_000); } } + diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 587dcbe6d678..c7edb55b378c 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -37,15 +37,6 @@ mod flt2dec; mod dec2flt; mod bignum; - -/// Adds the attribute to all items in the block. -macro_rules! cfg_block { - ($(#[$attr:meta]{$($it:item)*})*) => {$($( - #[$attr] - $it - )*)*} -} - /// Groups items that assume the pointer width is either 16/32/64, and has to be altered if /// support for larger/smaller pointer widths are added in the future. macro_rules! assume_usize_width { @@ -318,42 +309,6 @@ assume_usize_width! { test_impl_try_from_always_ok! { test_try_u16usize, u16, usize } test_impl_try_from_always_ok! { test_try_i16isize, i16, isize } - - test_impl_try_from_always_ok! { test_try_usizeu64, usize, u64 } - test_impl_try_from_always_ok! { test_try_usizeu128, usize, u128 } - test_impl_try_from_always_ok! { test_try_usizei128, usize, i128 } - - test_impl_try_from_always_ok! { test_try_isizei64, isize, i64 } - test_impl_try_from_always_ok! { test_try_isizei128, isize, i128 } - - cfg_block!( - #[cfg(target_pointer_width = "16")] { - test_impl_try_from_always_ok! { test_try_usizeu16, usize, u16 } - test_impl_try_from_always_ok! { test_try_isizei16, isize, i16 } - test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 } - test_impl_try_from_always_ok! { test_try_usizei32, usize, i32 } - test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 } - test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 } - } - - #[cfg(target_pointer_width = "32")] { - test_impl_try_from_always_ok! { test_try_u16isize, u16, isize } - test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 } - test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 } - test_impl_try_from_always_ok! { test_try_u32usize, u32, usize } - test_impl_try_from_always_ok! { test_try_i32isize, i32, isize } - test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 } - } - - #[cfg(target_pointer_width = "64")] { - test_impl_try_from_always_ok! { test_try_u16isize, u16, isize } - test_impl_try_from_always_ok! { test_try_u32usize, u32, usize } - test_impl_try_from_always_ok! { test_try_u32isize, u32, isize } - test_impl_try_from_always_ok! { test_try_i32isize, i32, isize } - test_impl_try_from_always_ok! { test_try_u64usize, u64, usize } - test_impl_try_from_always_ok! { test_try_i64isize, i64, isize } - } - ); } /// Conversions where max of $source can be represented as $target, @@ -402,24 +357,6 @@ assume_usize_width! { test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu64, isize, u64 } test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu128, isize, u128 } test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeusize, isize, usize } - - cfg_block!( - #[cfg(target_pointer_width = "16")] { - test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu16, isize, u16 } - test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 } - } - - #[cfg(target_pointer_width = "32")] { - test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 } - - test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize } - } - - #[cfg(target_pointer_width = "64")] { - test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize } - test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64usize, i64, usize } - } - ); } /// Conversions where max of $source can not be represented as $target, @@ -461,29 +398,9 @@ test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i64, u128, i64 } test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i128, u128, i128 } assume_usize_width! { - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64isize, u64, isize } - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128isize, u128, isize } - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei8, usize, i8 } test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei16, usize, i16 } test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizeisize, usize, isize } - - cfg_block!( - #[cfg(target_pointer_width = "16")] { - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16isize, u16, isize } - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize } - } - - #[cfg(target_pointer_width = "32")] { - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize } - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 } - } - - #[cfg(target_pointer_width = "64")] { - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 } - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei64, usize, i64 } - } - ); } /// Conversions where min/max of $source can not be represented as $target. @@ -543,34 +460,6 @@ test_impl_try_from_same_sign_err! { test_try_i128i64, i128, i64 } assume_usize_width! { test_impl_try_from_same_sign_err! { test_try_usizeu8, usize, u8 } - test_impl_try_from_same_sign_err! { test_try_u128usize, u128, usize } - test_impl_try_from_same_sign_err! { test_try_i128isize, i128, isize } - - cfg_block!( - #[cfg(target_pointer_width = "16")] { - test_impl_try_from_same_sign_err! { test_try_u32usize, u32, usize } - test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize } - - test_impl_try_from_same_sign_err! { test_try_i32isize, i32, isize } - test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize } - } - - #[cfg(target_pointer_width = "32")] { - test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize } - test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 } - - test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize } - test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 } - } - - #[cfg(target_pointer_width = "64")] { - test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 } - test_impl_try_from_same_sign_err! { test_try_usizeu32, usize, u32 } - - test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 } - test_impl_try_from_same_sign_err! { test_try_isizei32, isize, i32 } - } - ); } /// Conversions where neither the min nor the max of $source can be represented by @@ -615,22 +504,6 @@ test_impl_try_from_signed_to_unsigned_err! { test_try_i128u64, i128, u64 } assume_usize_width! { test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu8, isize, u8 } test_impl_try_from_signed_to_unsigned_err! { test_try_i128usize, i128, usize } - - cfg_block! { - #[cfg(target_pointer_width = "16")] { - test_impl_try_from_signed_to_unsigned_err! { test_try_i32usize, i32, usize } - test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize } - } - #[cfg(target_pointer_width = "32")] { - test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize } - - test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 } - } - #[cfg(target_pointer_width = "64")] { - test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 } - test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu32, isize, u32 } - } - } } macro_rules! test_float { diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 13740b958025..53fdfa068274 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -10,7 +10,6 @@ use core::result::Result::{Ok, Err}; - #[test] fn test_position() { let b = [1, 2, 3, 5, 5]; @@ -481,3 +480,73 @@ fn test_rotate_right() { assert_eq!(a[(i + 42) % N], i); } } + +#[test] +#[cfg(not(target_arch = "wasm32"))] +fn sort_unstable() { + use core::cmp::Ordering::{Equal, Greater, Less}; + use core::slice::heapsort; + use rand::{Rng, XorShiftRng}; + + let mut v = [0; 600]; + let mut tmp = [0; 600]; + let mut rng = XorShiftRng::new_unseeded(); + + for len in (2..25).chain(500..510) { + let v = &mut v[0..len]; + let tmp = &mut tmp[0..len]; + + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..100 { + for i in 0..len { + v[i] = rng.gen::() % modulus; + } + + // Sort in default order. + tmp.copy_from_slice(v); + tmp.sort_unstable(); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Sort in ascending order. + tmp.copy_from_slice(v); + tmp.sort_unstable_by(|a, b| a.cmp(b)); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Sort in descending order. + tmp.copy_from_slice(v); + tmp.sort_unstable_by(|a, b| b.cmp(a)); + assert!(tmp.windows(2).all(|w| w[0] >= w[1])); + + // Test heapsort using `<` operator. + tmp.copy_from_slice(v); + heapsort(tmp, |a, b| a < b); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Test heapsort using `>` operator. + tmp.copy_from_slice(v); + heapsort(tmp, |a, b| a > b); + assert!(tmp.windows(2).all(|w| w[0] >= w[1])); + } + } + } + + // Sort using a completely random comparison function. + // This will reorder the elements *somehow*, but won't panic. + for i in 0..v.len() { + v[i] = i as i32; + } + v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); + v.sort_unstable(); + for i in 0..v.len() { + assert_eq!(v[i], i as i32); + } + + // Should not panic. + [0i32; 0].sort_unstable(); + [(); 10].sort_unstable(); + [(); 100].sort_unstable(); + + let mut v = [0xDEADBEEFu64]; + v.sort_unstable(); + assert!(v == [0xDEADBEEF]); +} diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 71519ab21fef..0f45f965104c 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -108,6 +108,10 @@ pub enum Flag { /// For numbers, this means that the number will be padded with zeroes, /// and the sign (`+` or `-`) will precede them. FlagSignAwareZeroPad, + /// For Debug / `?`, format integers in lower-case hexadecimal. + FlagDebugLowerHex, + /// For Debug / `?`, format integers in upper-case hexadecimal. + FlagDebugUpperHex, } /// A count is used for the precision and width parameters of an integer, and @@ -377,8 +381,22 @@ impl<'a> Parser<'a> { spec.precision = self.count(); } } - // Finally the actual format specifier - if self.consume('?') { + // Optional radix followed by the actual format specifier + if self.consume('x') { + if self.consume('?') { + spec.flags |= 1 << (FlagDebugLowerHex as u32); + spec.ty = "?"; + } else { + spec.ty = "x"; + } + } else if self.consume('X') { + if self.consume('?') { + spec.flags |= 1 << (FlagDebugUpperHex as u32); + spec.ty = "?"; + } else { + spec.ty = "X"; + } + } else if self.consume('?') { spec.ty = "?"; } else { spec.ty = self.word(); diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs deleted file mode 100644 index 81fa0374f549..000000000000 --- a/src/libgetopts/lib.rs +++ /dev/null @@ -1,1622 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Simple getopt alternative. -//! -//! Construct a vector of options, either by using `reqopt`, `optopt`, and `optflag` -//! or by building them from components yourself, and pass them to `getopts`, -//! along with a vector of actual arguments (not including `argv[0]`). You'll -//! either get a failure code back, or a match. You'll have to verify whether -//! the amount of 'free' arguments in the match is what you expect. Use `opt_*` -//! accessors to get argument values out of the matches object. -//! -//! Single-character options are expected to appear on the command line with a -//! single preceding dash; multiple-character options are expected to be -//! proceeded by two dashes. Options that expect an argument accept their -//! argument following either a space or an equals sign. Single-character -//! options don't require the space. -//! -//! # Example -//! -//! The following example shows simple command line parsing for an application -//! that requires an input file to be specified, accepts an optional output -//! file name following `-o`, and accepts both `-h` and `--help` as optional flags. -//! -//! ```{.rust} -//! #![feature(rustc_private)] -//! -//! extern crate getopts; -//! use getopts::{optopt,optflag,getopts,OptGroup,usage}; -//! use std::env; -//! -//! fn do_work(inp: &str, out: Option) { -//! println!("{}", inp); -//! match out { -//! Some(x) => println!("{}", x), -//! None => println!("No Output"), -//! } -//! } -//! -//! fn print_usage(program: &str, opts: &[OptGroup]) { -//! let brief = format!("Usage: {} [options]", program); -//! print!("{}", usage(&brief, opts)); -//! } -//! -//! fn main() { -//! let args: Vec = env::args().collect(); -//! -//! let program = args[0].clone(); -//! -//! let opts = &[ -//! optopt("o", "", "set output file name", "NAME"), -//! optflag("h", "help", "print this help menu") -//! ]; -//! let matches = match getopts(&args[1..], opts) { -//! Ok(m) => { m } -//! Err(f) => { panic!(f.to_string()) } -//! }; -//! if matches.opt_present("h") { -//! print_usage(&program, opts); -//! return; -//! } -//! let output = matches.opt_str("o"); -//! let input = if !matches.free.is_empty() { -//! matches.free[0].clone() -//! } else { -//! print_usage(&program, opts); -//! return; -//! }; -//! do_work(&input, output); -//! } -//! ``` - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/", - test(attr(deny(warnings))))] - -#![deny(missing_docs)] -#![deny(warnings)] - -use self::Name::*; -use self::HasArg::*; -use self::Occur::*; -use self::Fail::*; -use self::Optval::*; -use self::SplitWithinState::*; -use self::Whitespace::*; -use self::LengthLimit::*; - -use std::fmt; -use std::iter::repeat; -use std::result; - -/// Name of an option. Either a string or a single char. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum Name { - /// A string representing the long name of an option. - /// For example: "help" - Long(String), - /// A char representing the short name of an option. - /// For example: 'h' - Short(char), -} - -/// Describes whether an option has an argument. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum HasArg { - /// The option requires an argument. - Yes, - /// The option takes no argument. - No, - /// The option argument is optional. - Maybe, -} - -/// Describes how often an option may occur. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum Occur { - /// The option occurs once. - Req, - /// The option occurs at most once. - Optional, - /// The option occurs zero or more times. - Multi, -} - -/// A description of a possible option. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Opt { - /// Name of the option - pub name: Name, - /// Whether it has an argument - pub hasarg: HasArg, - /// How often it can occur - pub occur: Occur, - /// Which options it aliases - pub aliases: Vec, -} - -/// One group of options, e.g., both `-h` and `--help`, along with -/// their shared description and properties. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct OptGroup { - /// Short name of the option, e.g. `h` for a `-h` option - pub short_name: String, - /// Long name of the option, e.g. `help` for a `--help` option - pub long_name: String, - /// Hint for argument, e.g. `FILE` for a `-o FILE` option - pub hint: String, - /// Description for usage help text - pub desc: String, - /// Whether option has an argument - pub hasarg: HasArg, - /// How often it can occur - pub occur: Occur, -} - -/// Describes whether an option is given at all or has a value. -#[derive(Clone, PartialEq, Eq, Debug)] -enum Optval { - Val(String), - Given, -} - -/// The result of checking command line arguments. Contains a vector -/// of matches and a vector of free strings. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Matches { - /// Options that matched - opts: Vec, - /// Values of the Options that matched - vals: Vec>, - /// Free string fragments - pub free: Vec, -} - -/// The type returned when the command line does not conform to the -/// expected format. Use the `Debug` implementation to output detailed -/// information. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum Fail { - /// The option requires an argument but none was passed. - ArgumentMissing(String), - /// The passed option is not declared among the possible options. - UnrecognizedOption(String), - /// A required option is not present. - OptionMissing(String), - /// A single occurrence option is being used multiple times. - OptionDuplicated(String), - /// There's an argument being passed to a non-argument option. - UnexpectedArgument(String), -} - -/// The type of failure that occurred. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -#[allow(missing_docs)] -pub enum FailType { - ArgumentMissing_, - UnrecognizedOption_, - OptionMissing_, - OptionDuplicated_, - UnexpectedArgument_, -} - -/// The result of parsing a command line with a set of options. -pub type Result = result::Result; - -impl Name { - fn from_str(nm: &str) -> Name { - if nm.len() == 1 { - Short(nm.chars().next().unwrap()) - } else { - Long(nm.to_owned()) - } - } - - fn to_string(&self) -> String { - match *self { - Short(ch) => ch.to_string(), - Long(ref s) => s.to_owned(), - } - } -} - -impl OptGroup { - /// Translate OptGroup into Opt. - /// (Both short and long names correspond to different Opts). - pub fn long_to_short(&self) -> Opt { - let OptGroup { - short_name, - long_name, - hasarg, - occur, - .. - } = (*self).clone(); - - match (short_name.len(), long_name.len()) { - (0, 0) => panic!("this long-format option was given no name"), - (0, _) => { - Opt { - name: Long((long_name)), - hasarg, - occur, - aliases: Vec::new(), - } - } - (1, 0) => { - Opt { - name: Short(short_name.chars().next().unwrap()), - hasarg, - occur, - aliases: Vec::new(), - } - } - (1, _) => { - Opt { - name: Long((long_name)), - hasarg, - occur, - aliases: vec![Opt { - name: Short(short_name.chars().next().unwrap()), - hasarg, - occur, - aliases: Vec::new(), - }], - } - } - _ => panic!("something is wrong with the long-form opt"), - } - } -} - -impl Matches { - fn opt_vals(&self, nm: &str) -> Vec { - match find_opt(&self.opts[..], Name::from_str(nm)) { - Some(id) => self.vals[id].clone(), - None => panic!("No option '{}' defined", nm), - } - } - - fn opt_val(&self, nm: &str) -> Option { - let vals = self.opt_vals(nm); - if vals.is_empty() { - None - } else { - Some(vals[0].clone()) - } - } - - /// Returns true if an option was matched. - pub fn opt_present(&self, nm: &str) -> bool { - !self.opt_vals(nm).is_empty() - } - - /// Returns the number of times an option was matched. - pub fn opt_count(&self, nm: &str) -> usize { - self.opt_vals(nm).len() - } - - /// Returns true if any of several options were matched. - pub fn opts_present(&self, names: &[String]) -> bool { - for nm in names { - match find_opt(&self.opts, Name::from_str(&**nm)) { - Some(id) if !self.vals[id].is_empty() => return true, - _ => (), - }; - } - false - } - - /// Returns the string argument supplied to one of several matching options or `None`. - pub fn opts_str(&self, names: &[String]) -> Option { - for nm in names { - if let Some(Val(ref s)) = self.opt_val(&nm[..]) { - return Some(s.clone()) - } - } - None - } - - /// Returns a vector of the arguments provided to all matches of the given - /// option. - /// - /// Used when an option accepts multiple values. - pub fn opt_strs(&self, nm: &str) -> Vec { - let mut acc: Vec = Vec::new(); - let r = self.opt_vals(nm); - for v in &r { - match *v { - Val(ref s) => acc.push((*s).clone()), - _ => (), - } - } - acc - } - - /// Returns the string argument supplied to a matching option or `None`. - pub fn opt_str(&self, nm: &str) -> Option { - let vals = self.opt_vals(nm); - if vals.is_empty() { - return None::; - } - match vals[0] { - Val(ref s) => Some((*s).clone()), - _ => None, - } - } - - - /// Returns the matching string, a default, or none. - /// - /// Returns none if the option was not present, `def` if the option was - /// present but no argument was provided, and the argument if the option was - /// present and an argument was provided. - pub fn opt_default(&self, nm: &str, def: &str) -> Option { - let vals = self.opt_vals(nm); - if vals.is_empty() { - None - } else { - match vals[0] { - Val(ref s) => Some((*s).clone()), - _ => Some(def.to_owned()), - } - } - } -} - -fn is_arg(arg: &str) -> bool { - arg.len() > 1 && arg.as_bytes()[0] == b'-' -} - -fn find_opt(opts: &[Opt], nm: Name) -> Option { - // Search main options. - let pos = opts.iter().position(|opt| opt.name == nm); - if pos.is_some() { - return pos; - } - - // Search in aliases. - for candidate in opts { - if candidate.aliases.iter().position(|opt| opt.name == nm).is_some() { - return opts.iter().position(|opt| opt.name == candidate.name); - } - } - - None -} - -/// Create a long option that is required and takes an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn reqopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Req, - } -} - -/// Create a long option that is optional and takes an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn optopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Optional, - } -} - -/// Create a long option that is optional and does not take an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -pub fn optflag(short_name: &str, long_name: &str, desc: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: "".to_owned(), - desc: desc.to_owned(), - hasarg: No, - occur: Optional, - } -} - -/// Create a long option that can occur more than once and does not -/// take an argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -pub fn optflagmulti(short_name: &str, long_name: &str, desc: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: "".to_owned(), - desc: desc.to_owned(), - hasarg: No, - occur: Multi, - } -} - -/// Create a long option that is optional and takes an optional argument. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn optflagopt(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Maybe, - occur: Optional, - } -} - -/// Create a long option that is optional, takes an argument, and may occur -/// multiple times. -/// -/// * `short_name` - e.g. `"h"` for a `-h` option, or `""` for none -/// * `long_name` - e.g. `"help"` for a `--help` option, or `""` for none -/// * `desc` - Description for usage help -/// * `hint` - Hint that is used in place of the argument in the usage help, -/// e.g. `"FILE"` for a `-o FILE` option -pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg: Yes, - occur: Multi, - } -} - -/// Create a generic option group, stating all parameters explicitly -pub fn opt(short_name: &str, - long_name: &str, - desc: &str, - hint: &str, - hasarg: HasArg, - occur: Occur) - -> OptGroup { - let len = short_name.len(); - assert!(len == 1 || len == 0); - OptGroup { - short_name: short_name.to_owned(), - long_name: long_name.to_owned(), - hint: hint.to_owned(), - desc: desc.to_owned(), - hasarg, - occur, - } -} - -impl fmt::Display for Fail { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ArgumentMissing(ref nm) => write!(f, "Argument to option '{}' missing.", *nm), - UnrecognizedOption(ref nm) => write!(f, "Unrecognized option: '{}'.", *nm), - OptionMissing(ref nm) => write!(f, "Required option '{}' missing.", *nm), - OptionDuplicated(ref nm) => write!(f, "Option '{}' given more than once.", *nm), - UnexpectedArgument(ref nm) => write!(f, "Option '{}' does not take an argument.", *nm), - } - } -} - -/// Parse command line arguments according to the provided options. -/// -/// On success returns `Ok(Matches)`. Use methods such as `opt_present` -/// `opt_str`, etc. to interrogate results. -/// # Panics -/// -/// Returns `Err(Fail)` on failure: use the `Debug` implementation of `Fail` to display -/// information about it. -pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { - let opts: Vec = optgrps.iter().map(|x| x.long_to_short()).collect(); - let n_opts = opts.len(); - - fn f(_x: usize) -> Vec { - Vec::new() - } - - let mut vals: Vec<_> = (0..n_opts).map(f).collect(); - let mut free: Vec = Vec::new(); - let l = args.len(); - let mut i = 0; - while i < l { - let cur = args[i].clone(); - let curlen = cur.len(); - if !is_arg(&cur[..]) { - free.push(cur); - } else if cur == "--" { - let mut j = i + 1; - while j < l { - free.push(args[j].clone()); - j += 1; - } - break; - } else { - let mut names; - let mut i_arg = None; - if cur.as_bytes()[1] == b'-' { - let tail = &cur[2..curlen]; - let tail_eq: Vec<&str> = tail.splitn(2, '=').collect(); - if tail_eq.len() <= 1 { - names = vec![Long(tail.to_owned())]; - } else { - names = vec![Long(tail_eq[0].to_owned())]; - i_arg = Some(tail_eq[1].to_owned()); - } - } else { - let mut j = 1; - names = Vec::new(); - while j < curlen { - let ch = cur[j..].chars().next().unwrap(); - let opt = Short(ch); - - // In a series of potential options (eg. -aheJ), if we - // see one which takes an argument, we assume all - // subsequent characters make up the argument. This - // allows options such as -L/usr/local/lib/foo to be - // interpreted correctly - - let opt_id = match find_opt(&opts, opt.clone()) { - Some(id) => id, - None => return Err(UnrecognizedOption(opt.to_string())), - }; - - names.push(opt); - - let arg_follows = match opts[opt_id].hasarg { - Yes | Maybe => true, - No => false, - }; - - let next = j + ch.len_utf8(); - if arg_follows && next < curlen { - i_arg = Some((&cur[next..curlen]).to_owned()); - break; - } - - j = next; - } - } - let mut name_pos = 0; - for nm in &names { - name_pos += 1; - let optid = match find_opt(&opts, (*nm).clone()) { - Some(id) => id, - None => return Err(UnrecognizedOption(nm.to_string())), - }; - match opts[optid].hasarg { - No => { - if name_pos == names.len() && !i_arg.is_none() { - return Err(UnexpectedArgument(nm.to_string())); - } - let v = &mut vals[optid]; - v.push(Given); - } - Maybe => { - if !i_arg.is_none() { - let v = &mut vals[optid]; - v.push(Val((i_arg.clone()).unwrap())); - } else if name_pos < names.len() || i + 1 == l || is_arg(&args[i + 1][..]) { - let v = &mut vals[optid]; - v.push(Given); - } else { - i += 1; - let v = &mut vals[optid]; - v.push(Val(args[i].clone())); - } - } - Yes => { - if !i_arg.is_none() { - let v = &mut vals[optid]; - v.push(Val(i_arg.clone().unwrap())); - } else if i + 1 == l { - return Err(ArgumentMissing(nm.to_string())); - } else { - i += 1; - let v = &mut vals[optid]; - v.push(Val(args[i].clone())); - } - } - } - } - } - i += 1; - } - for i in 0..n_opts { - let n = vals[i].len(); - let occ = opts[i].occur; - if occ == Req && n == 0 { - return Err(OptionMissing(opts[i].name.to_string())); - } - if occ != Multi && n > 1 { - return Err(OptionDuplicated(opts[i].name.to_string())); - } - } - Ok(Matches { - opts, - vals, - free, - }) -} - -/// Derive a usage message from a set of long options. -pub fn usage(brief: &str, opts: &[OptGroup]) -> String { - - let desc_sep = format!("\n{}", repeat(" ").take(24).collect::()); - - let rows = opts.iter().map(|optref| { - let OptGroup{short_name, - long_name, - hint, - desc, - hasarg, - ..} = (*optref).clone(); - - let mut row = repeat(" ").take(4).collect::(); - - // short option - match short_name.len() { - 0 => {} - 1 => { - row.push('-'); - row.push_str(&short_name[..]); - row.push(' '); - } - _ => panic!("the short name should only be 1 ascii char long"), - } - - // long option - match long_name.len() { - 0 => {} - _ => { - row.push_str("--"); - row.push_str(&long_name[..]); - row.push(' '); - } - } - - // arg - match hasarg { - No => {} - Yes => row.push_str(&hint[..]), - Maybe => { - row.push('['); - row.push_str(&hint[..]); - row.push(']'); - } - } - - // FIXME(https://github.com/rust-lang-nursery/getopts/issues/7) - // should be graphemes not codepoints - // - // here we just need to indent the start of the description - let rowlen = row.chars().count(); - if rowlen < 24 { - for _ in 0..24 - rowlen { - row.push(' '); - } - } else { - row.push_str(&desc_sep[..]); - } - - // Normalize desc to contain words separated by one space character - let mut desc_normalized_whitespace = String::new(); - for word in desc.split_whitespace() { - desc_normalized_whitespace.push_str(word); - desc_normalized_whitespace.push(' '); - } - - // FIXME(https://github.com/rust-lang-nursery/getopts/issues/7) - // should be graphemes not codepoints - let mut desc_rows = Vec::new(); - each_split_within(&desc_normalized_whitespace[..], 54, |substr| { - desc_rows.push(substr.to_owned()); - true - }); - - // FIXME(https://github.com/rust-lang-nursery/getopts/issues/7) - // should be graphemes not codepoints - // - // wrapped description - row.push_str(&desc_rows.join(&desc_sep[..])); - - row - }); - - format!("{}\n\nOptions:\n{}\n", - brief, - rows.collect::>().join("\n")) -} - -fn format_option(opt: &OptGroup) -> String { - let mut line = String::new(); - - if opt.occur != Req { - line.push('['); - } - - // Use short_name is possible, but fallback to long_name. - if !opt.short_name.is_empty() { - line.push('-'); - line.push_str(&opt.short_name[..]); - } else { - line.push_str("--"); - line.push_str(&opt.long_name[..]); - } - - if opt.hasarg != No { - line.push(' '); - if opt.hasarg == Maybe { - line.push('['); - } - line.push_str(&opt.hint[..]); - if opt.hasarg == Maybe { - line.push(']'); - } - } - - if opt.occur != Req { - line.push(']'); - } - if opt.occur == Multi { - line.push_str(".."); - } - - line -} - -/// Derive a short one-line usage summary from a set of long options. -pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String { - let mut line = format!("Usage: {} ", program_name); - line.push_str(&opts.iter() - .map(format_option) - .collect::>() - .join(" ")[..]); - line -} - -#[derive(Copy, Clone)] -enum SplitWithinState { - A, // leading whitespace, initial state - B, // words - C, // internal and trailing whitespace -} -#[derive(Copy, Clone)] -enum Whitespace { - Ws, // current char is whitespace - Cr, // current char is not whitespace -} -#[derive(Copy, Clone)] -enum LengthLimit { - UnderLim, // current char makes current substring still fit in limit - OverLim, // current char makes current substring no longer fit in limit -} - - -/// Splits a string into substrings with possibly internal whitespace, -/// each of them at most `lim` bytes long. The substrings have leading and trailing -/// whitespace removed, and are only cut at whitespace boundaries. -/// -/// Note: Function was moved here from `std::str` because this module is the only place that -/// uses it, and because it was too specific for a general string function. -/// -/// # Panics -/// -/// Panics during iteration if the string contains a non-whitespace -/// sequence longer than the limit. -fn each_split_within(ss: &str, lim: usize, mut it: F) -> bool - where F: FnMut(&str) -> bool -{ - // Just for fun, let's write this as a state machine: - - let mut slice_start = 0; - let mut last_start = 0; - let mut last_end = 0; - let mut state = A; - let mut fake_i = ss.len(); - let mut lim = lim; - - let mut cont = true; - - // if the limit is larger than the string, lower it to save cycles - if lim >= fake_i { - lim = fake_i; - } - - let mut machine = |cont: &mut bool, (i, c): (usize, char)| -> bool { - let whitespace = if c.is_whitespace() { - Ws - } else { - Cr - }; - let limit = if (i - slice_start + 1) <= lim { - UnderLim - } else { - OverLim - }; - - state = match (state, whitespace, limit) { - (A, Ws, _) => A, - (A, Cr, _) => { - slice_start = i; - last_start = i; - B - } - - (B, Cr, UnderLim) => B, - (B, Cr, OverLim) if (i - last_start + 1) > lim => { - panic!("word starting with {} longer than limit!", - &ss[last_start..i + 1]) - } - (B, Cr, OverLim) => { - *cont = it(&ss[slice_start..last_end]); - slice_start = last_start; - B - } - (B, Ws, UnderLim) => { - last_end = i; - C - } - (B, Ws, OverLim) => { - last_end = i; - *cont = it(&ss[slice_start..last_end]); - A - } - - (C, Cr, UnderLim) => { - last_start = i; - B - } - (C, Cr, OverLim) => { - *cont = it(&ss[slice_start..last_end]); - slice_start = i; - last_start = i; - last_end = i; - B - } - (C, Ws, OverLim) => { - *cont = it(&ss[slice_start..last_end]); - A - } - (C, Ws, UnderLim) => C, - }; - - *cont - }; - - ss.char_indices().all(|x| machine(&mut cont, x)); - - // Let the automaton 'run out' by supplying trailing whitespace - while cont && - match state { - B | C => true, - A => false, - } { - machine(&mut cont, (fake_i, ' ')); - fake_i += 1; - } - cont -} - -#[test] -fn test_split_within() { - fn t(s: &str, i: usize, u: &[String]) { - let mut v = Vec::new(); - each_split_within(s, i, |s| { - v.push(s.to_string()); - true - }); - assert!(v.iter().zip(u).all(|(a, b)| a == b)); - } - t("", 0, &[]); - t("", 15, &[]); - t("hello", 15, &["hello".to_string()]); - t("\nMary had a little lamb\nLittle lamb\n", - 15, - &["Mary had a".to_string(), "little lamb".to_string(), "Little lamb".to_string()]); - t("\nMary had a little lamb\nLittle lamb\n", - ::std::usize::MAX, - &["Mary had a little lamb\nLittle lamb".to_string()]); -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::result::Result::{Err, Ok}; - use std::result; - - // Tests for reqopt - #[test] - fn test_reqopt() { - let long_args = vec!["--test=20".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!(m.opt_present("t")); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => { - panic!("test_reqopt failed (long arg)"); - } - } - let short_args = vec!["-t".to_string(), "20".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => { - panic!("test_reqopt failed (short arg)"); - } - } - } - - #[test] - fn test_reqopt_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_reqopt_no_arg() { - let long_args = vec!["--test".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_reqopt_multi() { - let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; - let opts = vec![reqopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionDuplicated(_)) => {} - _ => panic!(), - } - } - - // Tests for optopt - #[test] - fn test_optopt() { - let long_args = vec!["--test=20".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - let short_args = vec!["-t".to_string(), "20".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - } - - #[test] - fn test_optopt_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(!m.opt_present("test")); - assert!(!m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optopt_no_arg() { - let long_args = vec!["--test".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optopt_multi() { - let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; - let opts = vec![optopt("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionDuplicated(_)) => {} - _ => panic!(), - } - } - - // Tests for optflag - #[test] - fn test_optflag() { - let long_args = vec!["--test".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert!(m.opt_present("t")); - } - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert!(m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optflag_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(!m.opt_present("test")); - assert!(!m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optflag_long_arg() { - let args = vec!["--test=20".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Err(UnexpectedArgument(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optflag_multi() { - let args = vec!["--test".to_string(), "-t".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Err(OptionDuplicated(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optflag_short_arg() { - let args = vec!["-t".to_string(), "20".to_string()]; - let opts = vec![optflag("t", "test", "testing")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - // The next variable after the flag is just a free argument - - assert!(m.free[0] == "20"); - } - _ => panic!(), - } - } - - // Tests for optflagmulti - #[test] - fn test_optflagmulti_short1() { - let args = vec!["-v".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("v"), 1); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_short2a() { - let args = vec!["-v".to_string(), "-v".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("v"), 2); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_short2b() { - let args = vec!["-vv".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("v"), 2); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_long1() { - let args = vec!["--verbose".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("verbose"), 1); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_long2() { - let args = vec!["--verbose".to_string(), "--verbose".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("verbose"), 2); - } - _ => panic!(), - } - } - - #[test] - fn test_optflagmulti_mix() { - let args = vec!["--verbose".to_string(), - "-v".to_string(), - "-vv".to_string(), - "verbose".to_string()]; - let opts = vec![optflagmulti("v", "verbose", "verbosity")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert_eq!(m.opt_count("verbose"), 4); - assert_eq!(m.opt_count("v"), 4); - } - _ => panic!(), - } - } - - // Tests for optmulti - #[test] - fn test_optmulti() { - let long_args = vec!["--test=20".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - let short_args = vec!["-t".to_string(), "20".to_string()]; - match getopts(&short_args, &opts) { - Ok(ref m) => { - assert!((m.opt_present("test"))); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!((m.opt_present("t"))); - assert_eq!(m.opt_str("t").unwrap(), "20"); - } - _ => panic!(), - } - } - - #[test] - fn test_optmulti_missing() { - let args = vec!["blah".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(!m.opt_present("test")); - assert!(!m.opt_present("t")); - } - _ => panic!(), - } - } - - #[test] - fn test_optmulti_no_arg() { - let long_args = vec!["--test".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - let short_args = vec!["-t".to_string()]; - match getopts(&short_args, &opts) { - Err(ArgumentMissing(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_optmulti_multi() { - let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(m.opt_present("test")); - assert_eq!(m.opt_str("test").unwrap(), "20"); - assert!(m.opt_present("t")); - assert_eq!(m.opt_str("t").unwrap(), "20"); - let pair = m.opt_strs("test"); - assert!(pair[0] == "20"); - assert!(pair[1] == "30"); - } - _ => panic!(), - } - } - - #[test] - fn test_unrecognized_option() { - let long_args = vec!["--untest".to_string()]; - let opts = vec![optmulti("t", "test", "testing", "TEST")]; - let rs = getopts(&long_args, &opts); - match rs { - Err(UnrecognizedOption(_)) => {} - _ => panic!(), - } - let short_args = vec!["-u".to_string()]; - match getopts(&short_args, &opts) { - Err(UnrecognizedOption(_)) => {} - _ => panic!(), - } - } - - #[test] - fn test_combined() { - let args = vec!["prog".to_string(), - "free1".to_string(), - "-s".to_string(), - "20".to_string(), - "free2".to_string(), - "--flag".to_string(), - "--long=30".to_string(), - "-f".to_string(), - "-m".to_string(), - "40".to_string(), - "-m".to_string(), - "50".to_string(), - "-n".to_string(), - "-A B".to_string(), - "-n".to_string(), - "-60 70".to_string()]; - let opts = vec![optopt("s", "something", "something", "SOMETHING"), - optflag("", "flag", "a flag"), - reqopt("", "long", "hi", "LONG"), - optflag("f", "", "another flag"), - optmulti("m", "", "mmmmmm", "YUM"), - optmulti("n", "", "nothing", "NOTHING"), - optopt("", "notpresent", "nothing to see here", "NOPE")]; - let rs = getopts(&args, &opts); - match rs { - Ok(ref m) => { - assert!(m.free[0] == "prog"); - assert!(m.free[1] == "free1"); - assert_eq!(m.opt_str("s").unwrap(), "20"); - assert!(m.free[2] == "free2"); - assert!((m.opt_present("flag"))); - assert_eq!(m.opt_str("long").unwrap(), "30"); - assert!((m.opt_present("f"))); - let pair = m.opt_strs("m"); - assert!(pair[0] == "40"); - assert!(pair[1] == "50"); - let pair = m.opt_strs("n"); - assert!(pair[0] == "-A B"); - assert!(pair[1] == "-60 70"); - assert!((!m.opt_present("notpresent"))); - } - _ => panic!(), - } - } - - #[test] - fn test_multi() { - let opts = vec![optopt("e", "", "encrypt", "ENCRYPT"), - optopt("", "encrypt", "encrypt", "ENCRYPT"), - optopt("f", "", "flag", "FLAG")]; - - let args_single = vec!["-e".to_string(), "foo".to_string()]; - let matches_single = &match getopts(&args_single, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(_) => panic!(), - }; - assert!(matches_single.opts_present(&["e".to_string()])); - assert!(matches_single.opts_present(&["encrypt".to_string(), "e".to_string()])); - assert!(matches_single.opts_present(&["e".to_string(), "encrypt".to_string()])); - assert!(!matches_single.opts_present(&["encrypt".to_string()])); - assert!(!matches_single.opts_present(&["thing".to_string()])); - assert!(!matches_single.opts_present(&[])); - - assert_eq!(matches_single.opts_str(&["e".to_string()]).unwrap(), "foo"); - assert_eq!(matches_single.opts_str(&["e".to_string(), "encrypt".to_string()]).unwrap(), - "foo"); - assert_eq!(matches_single.opts_str(&["encrypt".to_string(), "e".to_string()]).unwrap(), - "foo"); - - let args_both = vec!["-e".to_string(), - "foo".to_string(), - "--encrypt".to_string(), - "foo".to_string()]; - let matches_both = &match getopts(&args_both, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(_) => panic!(), - }; - assert!(matches_both.opts_present(&["e".to_string()])); - assert!(matches_both.opts_present(&["encrypt".to_string()])); - assert!(matches_both.opts_present(&["encrypt".to_string(), "e".to_string()])); - assert!(matches_both.opts_present(&["e".to_string(), "encrypt".to_string()])); - assert!(!matches_both.opts_present(&["f".to_string()])); - assert!(!matches_both.opts_present(&["thing".to_string()])); - assert!(!matches_both.opts_present(&[])); - - assert_eq!(matches_both.opts_str(&["e".to_string()]).unwrap(), "foo"); - assert_eq!(matches_both.opts_str(&["encrypt".to_string()]).unwrap(), - "foo"); - assert_eq!(matches_both.opts_str(&["e".to_string(), "encrypt".to_string()]).unwrap(), - "foo"); - assert_eq!(matches_both.opts_str(&["encrypt".to_string(), "e".to_string()]).unwrap(), - "foo"); - } - - #[test] - fn test_nospace() { - let args = vec!["-Lfoo".to_string(), "-M.".to_string()]; - let opts = vec![optmulti("L", "", "library directory", "LIB"), - optmulti("M", "", "something", "MMMM")]; - let matches = &match getopts(&args, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(_) => panic!(), - }; - assert!(matches.opts_present(&["L".to_string()])); - assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "foo"); - assert!(matches.opts_present(&["M".to_string()])); - assert_eq!(matches.opts_str(&["M".to_string()]).unwrap(), "."); - - } - - #[test] - fn test_nospace_conflict() { - let args = vec!["-vvLverbose".to_string(), "-v".to_string()]; - let opts = vec![optmulti("L", "", "library directory", "LIB"), - optflagmulti("v", "verbose", "Verbose")]; - let matches = &match getopts(&args, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(e) => panic!("{}", e), - }; - assert!(matches.opts_present(&["L".to_string()])); - assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "verbose"); - assert!(matches.opts_present(&["v".to_string()])); - assert_eq!(3, matches.opt_count("v")); - } - - #[test] - fn test_long_to_short() { - let mut short = Opt { - name: Name::Long("banana".to_string()), - hasarg: HasArg::Yes, - occur: Occur::Req, - aliases: Vec::new(), - }; - short.aliases = vec![Opt { - name: Name::Short('b'), - hasarg: HasArg::Yes, - occur: Occur::Req, - aliases: Vec::new(), - }]; - let verbose = reqopt("b", "banana", "some bananas", "VAL"); - - assert!(verbose.long_to_short() == short); - } - - #[test] - fn test_aliases_long_and_short() { - let opts = vec![optflagmulti("a", "apple", "Desc")]; - - let args = vec!["-a".to_string(), "--apple".to_string(), "-a".to_string()]; - - let matches = getopts(&args, &opts).unwrap(); - assert_eq!(3, matches.opt_count("a")); - assert_eq!(3, matches.opt_count("apple")); - } - - #[test] - fn test_usage() { - let optgroups = vec![reqopt("b", "banana", "Desc", "VAL"), - optopt("a", "012345678901234567890123456789", "Desc", "VAL"), - optflag("k", "kiwi", "Desc"), - optflagopt("p", "", "Desc", "VAL"), - optmulti("l", "", "Desc", "VAL")]; - - let expected = -"Usage: fruits - -Options: - -b --banana VAL Desc - -a --012345678901234567890123456789 VAL - Desc - -k --kiwi Desc - -p [VAL] Desc - -l VAL Desc -"; - - let generated_usage = usage("Usage: fruits", &optgroups); - - assert_eq!(generated_usage, expected); - } - - #[test] - fn test_usage_description_wrapping() { - // indentation should be 24 spaces - // lines wrap after 78: or rather descriptions wrap after 54 - - let optgroups = vec![optflag("k", - "kiwi", - // 54 - "This is a long description which won't be wrapped..+.."), - optflag("a", - "apple", - "This is a long description which _will_ be wrapped..+..")]; - - let expected = -"Usage: fruits - -Options: - -k --kiwi This is a long description which won't be wrapped..+.. - -a --apple This is a long description which _will_ be - wrapped..+.. -"; - - let usage = usage("Usage: fruits", &optgroups); - - assert!(usage == expected) - } - - #[test] - fn test_usage_description_multibyte_handling() { - let optgroups = vec![optflag("k", - "k\u{2013}w\u{2013}", - "The word kiwi is normally spelled with two i's"), - optflag("a", - "apple", - "This \u{201C}description\u{201D} has some characters that \ - could confuse the line wrapping; an apple costs 0.51€ in \ - some parts of Europe.")]; - - let expected = -"Usage: fruits - -Options: - -k --k–w– The word kiwi is normally spelled with two i's - -a --apple This “description” has some characters that could - confuse the line wrapping; an apple costs 0.51€ in - some parts of Europe. -"; - - let usage = usage("Usage: fruits", &optgroups); - - assert!(usage == expected) - } - - #[test] - fn test_short_usage() { - let optgroups = vec![reqopt("b", "banana", "Desc", "VAL"), - optopt("a", "012345678901234567890123456789", "Desc", "VAL"), - optflag("k", "kiwi", "Desc"), - optflagopt("p", "", "Desc", "VAL"), - optmulti("l", "", "Desc", "VAL")]; - - let expected = "Usage: fruits -b VAL [-a VAL] [-k] [-p [VAL]] [-l VAL]..".to_string(); - let generated_usage = short_usage("fruits", &optgroups); - - assert_eq!(generated_usage, expected); - } - - #[test] - fn test_args_with_equals() { - let args = vec!["--one".to_string(), "A=B".to_string(), - "--two=C=D".to_string()]; - let opts = vec![optopt("o", "one", "One", "INFO"), - optopt("t", "two", "Two", "INFO")]; - let matches = &match getopts(&args, &opts) { - result::Result::Ok(m) => m, - result::Result::Err(e) => panic!("{}", e) - }; - assert_eq!(matches.opts_str(&["o".to_string()]).unwrap(), "A=B"); - assert_eq!(matches.opts_str(&["t".to_string()]).unwrap(), "C=D"); - } -} diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index cd893b9784ab..d8c366d2413d 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -711,6 +711,12 @@ impl<'a> IntoCow<'a, str> for &'a str { } } +impl<'a> IntoCow<'a, str> for Cow<'a, str> { + fn into_cow(self) -> Cow<'a, str> { + self + } +} + impl<'a, T: Clone> IntoCow<'a, [T]> for Vec { fn into_cow(self) -> Cow<'a, [T]> { Cow::Owned(self) diff --git a/src/liblibc b/src/liblibc index 56444a4545bd..a7e78a78e17c 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 56444a4545bd71430d64b86b8a71714cfdbe9f5d +Subproject commit a7e78a78e17c8776d7780008ccb3ce541ec64ae9 diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 1163c1a98d5a..007093981d3e 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -34,13 +34,12 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(rustc_private)] #![feature(staged_api)] #![feature(lang_items)] #![feature(optin_builtin_traits)] -#[macro_use] extern crate syntax; extern crate syntax_pos; extern crate rustc_errors; @@ -156,7 +155,7 @@ impl IntoIterator for TokenStream { type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { - TokenTreeIter { cursor: self.0.trees(), next: None } + TokenTreeIter { cursor: self.0.trees(), stack: Vec::new() } } } @@ -554,7 +553,7 @@ impl Literal { #[unstable(feature = "proc_macro", issue = "38356")] pub struct TokenTreeIter { cursor: tokenstream::Cursor, - next: Option, + stack: Vec, } #[unstable(feature = "proc_macro", issue = "38356")] @@ -563,9 +562,10 @@ impl Iterator for TokenTreeIter { fn next(&mut self) -> Option { loop { - let next = - unwrap_or!(self.next.take().or_else(|| self.cursor.next_as_stream()), return None); - let tree = TokenTree::from_internal(next, &mut self.next); + let tree = self.stack.pop().or_else(|| { + let next = self.cursor.next_as_stream()?; + Some(TokenTree::from_internal(next, &mut self.stack)) + })?; if tree.span.0 == DUMMY_SP { if let TokenNode::Group(Delimiter::None, stream) = tree.kind { self.cursor.insert(stream.0); @@ -598,12 +598,12 @@ impl Delimiter { } impl TokenTree { - fn from_internal(stream: tokenstream::TokenStream, next: &mut Option) + fn from_internal(stream: tokenstream::TokenStream, stack: &mut Vec) -> TokenTree { use syntax::parse::token::*; let (tree, is_joint) = stream.as_tree(); - let (mut span, token) = match tree { + let (span, token) = match tree { tokenstream::TokenTree::Token(span, token) => (span, token), tokenstream::TokenTree::Delimited(span, delimed) => { let delimiter = Delimiter::from_internal(delimed.delim); @@ -615,34 +615,32 @@ impl TokenTree { }; let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone }; + macro_rules! tt { + ($e:expr) => (TokenTree { span: Span(span), kind: $e }) + } macro_rules! op { - ($op:expr) => { TokenNode::Op($op, op_kind) } - } - - macro_rules! joint { - ($first:expr, $rest:expr) => { joint($first, $rest, is_joint, &mut span, next) } - } - - fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span, - next: &mut Option) - -> TokenNode { - let (first_span, rest_span) = (*span, *span); - *span = first_span; - let tree = tokenstream::TokenTree::Token(rest_span, rest); - *next = Some(if is_joint { tree.joint() } else { tree.into() }); - TokenNode::Op(first, Spacing::Joint) + ($a:expr) => (TokenNode::Op($a, op_kind)); + ($a:expr, $b:expr) => ({ + stack.push(tt!(TokenNode::Op($b, op_kind).into())); + TokenNode::Op($a, Spacing::Joint) + }); + ($a:expr, $b:expr, $c:expr) => ({ + stack.push(tt!(TokenNode::Op($c, op_kind))); + stack.push(tt!(TokenNode::Op($b, Spacing::Joint))); + TokenNode::Op($a, Spacing::Joint) + }) } let kind = match token { Eq => op!('='), Lt => op!('<'), - Le => joint!('<', Eq), - EqEq => joint!('=', Eq), - Ne => joint!('!', Eq), - Ge => joint!('>', Eq), + Le => op!('<', '='), + EqEq => op!('=', '='), + Ne => op!('!', '='), + Ge => op!('>', '='), Gt => op!('>'), - AndAnd => joint!('&', BinOp(And)), - OrOr => joint!('|', BinOp(Or)), + AndAnd => op!('&', '&'), + OrOr => op!('|', '|'), Not => op!('!'), Tilde => op!('~'), BinOp(Plus) => op!('+'), @@ -653,37 +651,46 @@ impl TokenTree { BinOp(Caret) => op!('^'), BinOp(And) => op!('&'), BinOp(Or) => op!('|'), - BinOp(Shl) => joint!('<', Lt), - BinOp(Shr) => joint!('>', Gt), - BinOpEq(Plus) => joint!('+', Eq), - BinOpEq(Minus) => joint!('-', Eq), - BinOpEq(Star) => joint!('*', Eq), - BinOpEq(Slash) => joint!('/', Eq), - BinOpEq(Percent) => joint!('%', Eq), - BinOpEq(Caret) => joint!('^', Eq), - BinOpEq(And) => joint!('&', Eq), - BinOpEq(Or) => joint!('|', Eq), - BinOpEq(Shl) => joint!('<', Le), - BinOpEq(Shr) => joint!('>', Ge), + BinOp(Shl) => op!('<', '<'), + BinOp(Shr) => op!('>', '>'), + BinOpEq(Plus) => op!('+', '='), + BinOpEq(Minus) => op!('-', '='), + BinOpEq(Star) => op!('*', '='), + BinOpEq(Slash) => op!('/', '='), + BinOpEq(Percent) => op!('%', '='), + BinOpEq(Caret) => op!('^', '='), + BinOpEq(And) => op!('&', '='), + BinOpEq(Or) => op!('|', '='), + BinOpEq(Shl) => op!('<', '<', '='), + BinOpEq(Shr) => op!('>', '>', '='), At => op!('@'), Dot => op!('.'), - DotDot => joint!('.', Dot), - DotDotDot => joint!('.', DotDot), - DotDotEq => joint!('.', DotEq), + DotDot => op!('.', '.'), + DotDotDot => op!('.', '.', '.'), + DotDotEq => op!('.', '.', '='), Comma => op!(','), Semi => op!(';'), Colon => op!(':'), - ModSep => joint!(':', Colon), - RArrow => joint!('-', Gt), - LArrow => joint!('<', BinOp(Minus)), - FatArrow => joint!('=', Gt), + ModSep => op!(':', ':'), + RArrow => op!('-', '>'), + LArrow => op!('<', '-'), + FatArrow => op!('=', '>'), Pound => op!('#'), Dollar => op!('$'), Question => op!('?'), - Underscore => op!('_'), - Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)), - Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)), + Ident(ident, false) | Lifetime(ident) => TokenNode::Term(Term(ident.name)), + Ident(ident, true) => TokenNode::Term(Term(Symbol::intern(&format!("r#{}", ident)))), + Literal(..) => TokenNode::Literal(self::Literal(token)), + DocComment(c) => { + let stream = vec![ + tt!(TokenNode::Term(Term::intern("doc"))), + tt!(op!('=')), + tt!(TokenNode::Literal(self::Literal(Literal(Lit::Str_(c), None)))), + ].into_iter().collect(); + stack.push(tt!(TokenNode::Group(Delimiter::Bracket, stream))); + op!('#') + } Interpolated(_) => { __internal::with_sess(|(sess, _)| { @@ -692,7 +699,7 @@ impl TokenTree { }) } - DotEq => joint!('.', Eq), + DotEq => op!('.', '='), OpenDelim(..) | CloseDelim(..) => unreachable!(), Whitespace | Comment | Shebang(..) | Eof => unreachable!(), }; @@ -714,11 +721,39 @@ impl TokenTree { }, TokenNode::Term(symbol) => { let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt() }; + let sym_str = symbol.0.as_str(); let token = - if symbol.0.as_str().starts_with("'") { Lifetime(ident) } else { Ident(ident) }; + if sym_str.starts_with("'") { Lifetime(ident) } + else if sym_str.starts_with("r#") { + let name = Symbol::intern(&sym_str[2..]); + let ident = ast::Ident { name, ctxt: self.span.0.ctxt() }; + Ident(ident, true) + } else { Ident(ident, false) }; return TokenTree::Token(self.span.0, token).into(); } - TokenNode::Literal(token) => return TokenTree::Token(self.span.0, token.0).into(), + TokenNode::Literal(self::Literal(Literal(Lit::Integer(ref a), b))) + if a.as_str().starts_with("-") => + { + let minus = BinOp(BinOpToken::Minus); + let integer = Symbol::intern(&a.as_str()[1..]); + let integer = Literal(Lit::Integer(integer), b); + let a = TokenTree::Token(self.span.0, minus); + let b = TokenTree::Token(self.span.0, integer); + return vec![a, b].into_iter().collect() + } + TokenNode::Literal(self::Literal(Literal(Lit::Float(ref a), b))) + if a.as_str().starts_with("-") => + { + let minus = BinOp(BinOpToken::Minus); + let float = Symbol::intern(&a.as_str()[1..]); + let float = Literal(Lit::Float(float), b); + let a = TokenTree::Token(self.span.0, minus); + let b = TokenTree::Token(self.span.0, float); + return vec![a, b].into_iter().collect() + } + TokenNode::Literal(token) => { + return TokenTree::Token(self.span.0, token.0).into() + } }; let token = match op { @@ -743,7 +778,6 @@ impl TokenTree { '#' => Pound, '$' => Dollar, '?' => Question, - '_' => Underscore, _ => panic!("unsupported character {}", op), }; diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index dd88dd933f69..8d6c7d68dfe2 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -27,6 +27,7 @@ fn main() { "InstrProfilingFile.c", "InstrProfilingMerge.c", "InstrProfilingMergeFile.c", + "InstrProfilingNameVar.c", "InstrProfilingPlatformDarwin.c", "InstrProfilingPlatformLinux.c", "InstrProfilingPlatformOther.c", @@ -42,6 +43,8 @@ fn main() { cfg.define("strdup", Some("_strdup")); cfg.define("open", Some("_open")); cfg.define("fdopen", Some("_fdopen")); + cfg.define("getpid", Some("_getpid")); + cfg.define("fileno", Some("_fileno")); } else { // Turn off various features of gcc and such, mostly copying // compiler-rt's build system already @@ -50,6 +53,7 @@ fn main() { cfg.flag("-fomit-frame-pointer"); cfg.flag("-ffreestanding"); cfg.define("VISIBILITY_HIDDEN", None); + cfg.define("COMPILER_RT_HAS_UNAME", Some("1")); } for src in profile_sources { diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 7e84a69dd791..2aae0f24d484 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -56,3 +56,4 @@ byteorder = { version = "1.1", features = ["i128"]} # later crate stop compiling. If you can remove this and everything # compiles, then please feel free to do so! flate2 = "1.0" +tempdir = "0.3" diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs index 24294ec49cee..278e0f9a26e4 100644 --- a/src/librustc/benches/lib.rs +++ b/src/librustc/benches/lib.rs @@ -10,7 +10,6 @@ #![deny(warnings)] -#![feature(slice_patterns)] #![feature(test)] extern crate test; diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index ff2c36416bfd..1247db55f585 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -473,8 +473,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Keep track of the previous guard expressions let mut prev_guards = Vec::new(); - // Track if the previous pattern contained bindings or wildcards - let mut prev_has_bindings = false; for arm in arms { // Add an exit node for when we've visited all the @@ -493,40 +491,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Visit the guard expression let guard_exit = self.expr(&guard, guard_start); - let this_has_bindings = pat.contains_bindings_or_wild(); - - // If both this pattern and the previous pattern - // were free of bindings, they must consist only - // of "constant" patterns. Note we cannot match an - // all-constant pattern, fail the guard, and then - // match *another* all-constant pattern. This is - // because if the previous pattern matches, then - // we *cannot* match this one, unless all the - // constants are the same (which is rejected by - // `check_match`). - // - // We can use this to be smarter about the flow - // along guards. If the previous pattern matched, - // then we know we will not visit the guard in - // this one (whether or not the guard succeeded), - // if the previous pattern failed, then we know - // the guard for that pattern will not have been - // visited. Thus, it is not possible to visit both - // the previous guard and the current one when - // both patterns consist only of constant - // sub-patterns. - // - // However, if the above does not hold, then all - // previous guards need to be wired to visit the - // current guard pattern. - if prev_has_bindings || this_has_bindings { - while let Some(prev) = prev_guards.pop() { - self.add_contained_edge(prev, guard_start); - } + // #47295: We used to have very special case code + // here for when a pair of arms are both formed + // solely from constants, and if so, not add these + // edges. But this was not actually sound without + // other constraints that we stopped enforcing at + // some point. + while let Some(prev) = prev_guards.pop() { + self.add_contained_edge(prev, guard_start); } - prev_has_bindings = this_has_bindings; - // Push the guard onto the list of previous guards prev_guards.push(guard_exit); diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index c8d0362f17c8..f1f383d7ad12 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -1,295 +1,4 @@ -# Dependency graph for incremental compilation +To learn more about how dependency tracking works in rustc, see the [rustc +guide]. -This module contains the infrastructure for managing the incremental -compilation dependency graph. This README aims to explain how it ought -to be used. In this document, we'll first explain the overall -strategy, and then share some tips for handling specific scenarios. - -The high-level idea is that we want to instrument the compiler to -track which parts of the AST and other IR are read/written by what. -This way, when we come back later, we can look at this graph and -determine what work needs to be redone. - -### The dependency graph - -The nodes of the graph are defined by the enum `DepNode`. They represent -one of three things: - -1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself. -2. Data nodes (like `TypeOfItem(DefId)`) represent some computed - information about a particular item. -3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some - procedure that is executing. Usually this procedure is - performing some kind of check for errors. You can think of them as - computed values where the value being computed is `()` (and the - value may fail to be computed, if an error results). - -An edge `N1 -> N2` is added between two nodes if either: - -- the value of `N1` is used to compute `N2`; -- `N1` is read by the procedure `N2`; -- the procedure `N1` writes the value `N2`. - -The latter two conditions are equivalent to the first one if you think -of procedures as values. - -### Basic tracking - -There is a very general strategy to ensure that you have a correct, if -sometimes overconservative, dependency graph. The two main things you have -to do are (a) identify shared state and (b) identify the current tasks. - -### Identifying shared state - -Identify "shared state" that will be written by one pass and read by -another. In particular, we need to identify shared state that will be -read "across items" -- that is, anything where changes in one item -could invalidate work done for other items. So, for example: - -1. The signature for a function is "shared state". -2. The computed type of some expression in the body of a function is - not shared state, because if it changes it does not itself - invalidate other functions (though it may be that it causes new - monomorphizations to occur, but that's handled independently). - -Put another way: if the HIR for an item changes, we are going to -recompile that item for sure. But we need the dep tracking map to tell -us what *else* we have to recompile. Shared state is anything that is -used to communicate results from one item to another. - -### Identifying the current task, tracking reads/writes, etc - -FIXME(#42293). This text needs to be rewritten for the new red-green -system, which doesn't fully exist yet. - -#### Dependency tracking map - -`DepTrackingMap` is a particularly convenient way to correctly store -shared state. A `DepTrackingMap` is a special hashmap that will add -edges automatically when `get` and `insert` are called. The idea is -that, when you get/insert a value for the key `K`, we will add an edge -from/to the node `DepNode::Variant(K)` (for some variant specific to -the map). - -Each `DepTrackingMap` is parameterized by a special type `M` that -implements `DepTrackingMapConfig`; this trait defines the key and value -types of the map, and also defines a fn for converting from the key to -a `DepNode` label. You don't usually have to muck about with this by -hand, there is a macro for creating it. You can see the complete set -of `DepTrackingMap` definitions in `librustc/middle/ty/maps.rs`. - -As an example, let's look at the `adt_defs` map. The `adt_defs` map -maps from the def-id of a struct/enum to its `AdtDef`. It is defined -using this macro: - -```rust -dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> } -// ~~~~~~~ ~~~~~~~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ -// | | Key type Value type -// | DepNode variant -// Name of map id type -``` - -this indicates that a map id type `AdtDefs` will be created. The key -of the map will be a `DefId` and value will be -`ty::AdtDefMaster<'tcx>`. The `DepNode` will be created by -`DepNode::ItemSignature(K)` for a given key. - -Once that is done, you can just use the `DepTrackingMap` like any -other map: - -```rust -let mut map: DepTrackingMap = DepTrackingMap::new(dep_graph); -map.insert(key, value); // registers dep_graph.write -map.get(key; // registers dep_graph.read -``` - -#### Memoization - -One particularly interesting case is memoization. If you have some -shared state that you compute in a memoized fashion, the correct thing -to do is to define a `RefCell` for it and use the -`memoize` helper: - -```rust -map.memoize(key, || /* compute value */) -``` - -This will create a graph that looks like - - ... -> MapVariant(key) -> CurrentTask - -where `MapVariant` is the `DepNode` variant that the map is associated with, -and `...` are whatever edges the `/* compute value */` closure creates. - -In particular, using the memoize helper is much better than writing -the obvious code yourself: - -```rust -if let Some(result) = map.get(key) { - return result; -} -let value = /* compute value */; -map.insert(key, value); -``` - -If you write that code manually, the dependency graph you get will -include artificial edges that are not necessary. For example, imagine that -two tasks, A and B, both invoke the manual memoization code, but A happens -to go first. The resulting graph will be: - - ... -> A -> MapVariant(key) -> B - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // caused by A writing to MapVariant(key) - ~~~~~~~~~~~~~~~~~~~~ // caused by B reading from MapVariant(key) - -This graph is not *wrong*, but it encodes a path from A to B that -should not exist. In contrast, using the memoized helper, you get: - - ... -> MapVariant(key) -> A - | - +----------> B - -which is much cleaner. - -**Be aware though that the closure is executed with `MapVariant(key)` -pushed onto the stack as the current task!** That means that you must -add explicit `read` calls for any shared state that it accesses -implicitly from its environment. See the section on "explicit calls to -read and write when starting a new subtask" above for more details. - -### How to decide where to introduce a new task - -Certainly, you need at least one task on the stack: any attempt to -`read` or `write` shared state will panic if there is no current -task. But where does it make sense to introduce subtasks? The basic -rule is that a subtask makes sense for any discrete unit of work you -may want to skip in the future. Adding a subtask separates out the -reads/writes from *that particular subtask* versus the larger -context. An example: you might have a 'meta' task for all of borrow -checking, and then subtasks for borrow checking individual fns. (Seen -in this light, memoized computations are just a special case where we -may want to avoid redoing the work even within the context of one -compilation.) - -The other case where you might want a subtask is to help with refining -the reads/writes for some later bit of work that needs to be memoized. -For example, we create a subtask for type-checking the body of each -fn. However, in the initial version of incr. comp. at least, we do -not expect to actually *SKIP* type-checking -- we only expect to skip -trans. However, it's still useful to create subtasks for type-checking -individual items, because, otherwise, if a fn sig changes, we won't -know which callers are affected -- in fact, because the graph would be -so coarse, we'd just have to retrans everything, since we can't -distinguish which fns used which fn sigs. - -### Testing the dependency graph - -There are various ways to write tests against the dependency graph. -The simplest mechanism are the -`#[rustc_if_this_changed]` and `#[rustc_then_this_would_need]` -annotations. These are used in compile-fail tests to test whether the -expected set of paths exist in the dependency graph. As an example, -see `src/test/compile-fail/dep-graph-caller-callee.rs`. - -The idea is that you can annotate a test like: - -```rust -#[rustc_if_this_changed] -fn foo() { } - -#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK -fn bar() { foo(); } - -#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path -fn baz() { } -``` - -This will check whether there is a path in the dependency graph from -`Hir(foo)` to `TypeckTables(bar)`. An error is reported for each -`#[rustc_then_this_would_need]` annotation that indicates whether a -path exists. `//~ ERROR` annotations can then be used to test if a -path is found (as demonstrated above). - -### Debugging the dependency graph - -#### Dumping the graph - -The compiler is also capable of dumping the dependency graph for your -debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The -graph will be dumped to `dep_graph.{txt,dot}` in the current -directory. You can override the filename with the `RUST_DEP_GRAPH` -environment variable. - -Frequently, though, the full dep graph is quite overwhelming and not -particularly helpful. Therefore, the compiler also allows you to filter -the graph. You can filter in three ways: - -1. All edges originating in a particular set of nodes (usually a single node). -2. All edges reaching a particular set of nodes. -3. All edges that lie between given start and end nodes. - -To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should -look like one of the following: - -``` -source_filter // nodes originating from source_filter --> target_filter // nodes that can reach target_filter -source_filter -> target_filter // nodes in between source_filter and target_filter -``` - -`source_filter` and `target_filter` are a `&`-separated list of strings. -A node is considered to match a filter if all of those strings appear in its -label. So, for example: - -``` -RUST_DEP_GRAPH_FILTER='-> TypeckTables' -``` - -would select the predecessors of all `TypeckTables` nodes. Usually though you -want the `TypeckTables` node for some particular fn, so you might write: - -``` -RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar' -``` - -This will select only the `TypeckTables` nodes for fns with `bar` in their name. - -Perhaps you are finding that when you change `foo` you need to re-type-check `bar`, -but you don't think you should have to. In that case, you might do: - -``` -RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckTables & bar' -``` - -This will dump out all the nodes that lead from `Hir(foo)` to -`TypeckTables(bar)`, from which you can (hopefully) see the source -of the erroneous edge. - -#### Tracking down incorrect edges - -Sometimes, after you dump the dependency graph, you will find some -path that should not exist, but you will not be quite sure how it came -to be. **When the compiler is built with debug assertions,** it can -help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE` -environment variable to a filter. Every edge created in the dep-graph -will be tested against that filter -- if it matches, a `bug!` is -reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`). - -The syntax for these filters is the same as described in the previous -section. However, note that this filter is applied to every **edge** -and doesn't handle longer paths in the graph, unlike the previous -section. - -Example: - -You find that there is a path from the `Hir` of `foo` to the type -check of `bar` and you don't think there should be. You dump the -dep-graph as described in the previous section and open `dep-graph.txt` -to see something like: - - Hir(foo) -> Collect(bar) - Collect(bar) -> TypeckTables(bar) - -That first edge looks suspicious to you. So you set -`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and -then observe the backtrace. Voila, bug fixed! +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 7d8709a82f4d..d1f3736556c5 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -67,11 +67,12 @@ use hir::{HirId, ItemLocalId}; use ich::{Fingerprint, StableHashingContext}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; -use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty}; -use ty::subst::Substs; use std::fmt; use std::hash::Hash; use syntax_pos::symbol::InternedString; +use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal}; +use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty}; +use ty::subst::Substs; // erase!() just makes tokens go away. It's used to specify which macro argument // is repeated (i.e. which sub-expression of the macro we are in) but don't need @@ -80,6 +81,10 @@ macro_rules! erase { ($x:tt) => ({}) } +macro_rules! replace { + ($x:tt with $($y:tt)*) => ($($y)*) +} + macro_rules! is_anon_attr { (anon) => (true); ($attr:ident) => (false); @@ -111,7 +116,7 @@ macro_rules! define_dep_nodes { (<$tcx:tt> $( [$($attr:ident),* ] - $variant:ident $(( $($tuple_arg:tt),* ))* + $variant:ident $(( $tuple_arg_ty:ty $(,)* ))* $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* ,)* ) => ( @@ -134,7 +139,7 @@ macro_rules! define_dep_nodes { // tuple args $({ - return <( $($tuple_arg,)* ) as DepNodeParams> + return <$tuple_arg_ty as DepNodeParams> ::CAN_RECONSTRUCT_QUERY_KEY; })* @@ -186,7 +191,7 @@ macro_rules! define_dep_nodes { DepKind :: $variant => { // tuple args $({ - $(erase!($tuple_arg);)* + erase!($tuple_arg_ty); return true; })* @@ -205,7 +210,7 @@ macro_rules! define_dep_nodes { pub enum DepConstructor<$tcx> { $( - $variant $(( $($tuple_arg),* ))* + $variant $(( $tuple_arg_ty ))* $({ $($struct_arg_name : $struct_arg_ty),* })* ),* } @@ -227,15 +232,14 @@ macro_rules! define_dep_nodes { { match dep { $( - DepConstructor :: $variant $(( $($tuple_arg),* ))* + DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))* $({ $($struct_arg_name),* })* => { // tuple args $({ - let tupled_args = ( $($tuple_arg,)* ); - let hash = DepNodeParams::to_fingerprint(&tupled_args, - tcx); + erase!($tuple_arg_ty); + let hash = DepNodeParams::to_fingerprint(&arg, tcx); let dep_node = DepNode { kind: DepKind::$variant, hash @@ -247,7 +251,7 @@ macro_rules! define_dep_nodes { tcx.sess.opts.debugging_opts.query_dep_graph) { tcx.dep_graph.register_dep_node_debug_str(dep_node, || { - tupled_args.to_debug_str(tcx) + arg.to_debug_str(tcx) }); } @@ -575,6 +579,9 @@ define_dep_nodes!( <'tcx> [] GetPanicStrategy(CrateNum), [] IsNoBuiltins(CrateNum), [] ImplDefaultness(DefId), + [] CheckItemWellFormed(DefId), + [] CheckTraitItemWellFormed(DefId), + [] CheckImplItemWellFormed(DefId), [] ReachableNonGenerics(CrateNum), [] NativeLibraries(CrateNum), [] PluginRegistrarFn(CrateNum), @@ -582,10 +589,12 @@ define_dep_nodes!( <'tcx> [input] CrateDisambiguator(CrateNum), [input] CrateHash(CrateNum), [input] OriginalCrateName(CrateNum), + [input] ExtraFileName(CrateNum), [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId }, [] AllTraitImplementations(CrateNum), + [] DllimportForeignItems(CrateNum), [] IsDllimportForeignItem(DefId), [] IsStaticallyIncludedForeignItem(DefId), [] NativeLibraryKind(DefId), @@ -609,8 +618,6 @@ define_dep_nodes!( <'tcx> [input] MissingExternCrateItem(CrateNum), [input] UsedCrateSource(CrateNum), [input] PostorderCnums, - [] HasCloneClosures(CrateNum), - [] HasCopyClosures(CrateNum), // This query is not expected to have inputs -- as a result, it's // not a good candidate for "replay" because it's essentially a @@ -631,7 +638,9 @@ define_dep_nodes!( <'tcx> [] CodegenUnit(InternedString), [] CompileCodegenUnit(InternedString), [input] OutputFilenames, - [anon] NormalizeTy, + [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>), + [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>), + [] DropckOutlives(CanonicalTyGoal<'tcx>), [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, @@ -641,7 +650,13 @@ define_dep_nodes!( <'tcx> [] GetSymbolExportLevel(DefId), + [] WasmCustomSections(CrateNum), + [input] Features, + + [] ProgramClausesFor(DefId), + [] WasmImportModuleMap(CrateNum), + [] ForeignModules(CrateNum), ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { @@ -679,43 +694,43 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T } } -impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) { +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefId { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { - tcx.def_path_hash(self.0).0 + tcx.def_path_hash(*self).0 } fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { - tcx.item_path_str(self.0) + tcx.item_path_str(*self) } } -impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIndex,) { +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefIndex { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { - tcx.hir.definitions().def_path_hash(self.0).0 + tcx.hir.definitions().def_path_hash(*self).0 } fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { - tcx.item_path_str(DefId::local(self.0)) + tcx.item_path_str(DefId::local(*self)) } } -impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (CrateNum,) { +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for CrateNum { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { let def_id = DefId { - krate: self.0, + krate: *self, index: CRATE_DEF_INDEX, }; tcx.def_path_hash(def_id).0 } fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { - tcx.crate_name(self.0).as_str().to_string() + tcx.crate_name(*self).as_str().to_string() } } @@ -743,17 +758,17 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, De } } -impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (HirId,) { +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for HirId { const CAN_RECONSTRUCT_QUERY_KEY: bool = false; // We actually would not need to specialize the implementation of this // method but it's faster to combine the hashes than to instantiate a full // hashing context and stable-hashing state. fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { - let (HirId { + let HirId { owner, local_id: ItemLocalId(local_id), - },) = *self; + } = *self; let def_path_hash = tcx.def_path_hash(DefId::local(owner)); let local_id = Fingerprint::from_smaller_hash(local_id as u64); diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 07c6c85b89da..d60c22064d3a 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -9,8 +9,7 @@ // except according to those terms. use errors::DiagnosticBuilder; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, - StableHashingContextProvider}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sync::Lrc; @@ -20,7 +19,7 @@ use std::hash::Hash; use ty::TyCtxt; use util::common::{ProfileQueriesMsg, profq_msg}; -use ich::Fingerprint; +use ich::{StableHashingContext, StableHashingContextProvider, Fingerprint}; use super::debug::EdgeFilter; use super::dep_node::{DepNode, DepKind, WorkProductId}; @@ -189,21 +188,21 @@ impl DepGraph { /// `arg` parameter. /// /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/incremental-compilation.html - pub fn with_task(&self, + pub fn with_task<'gcx, C, A, R>(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> (R, DepNodeIndex) - where C: DepGraphSafe + StableHashingContextProvider, - R: HashStable, + where C: DepGraphSafe + StableHashingContextProvider<'gcx>, + R: HashStable>, { self.with_task_impl(key, cx, arg, task, |data, key| data.borrow_mut().push_task(key), |data, key| data.borrow_mut().pop_task(key)) } - fn with_task_impl(&self, + fn with_task_impl<'gcx, C, A, R>(&self, key: DepNode, cx: C, arg: A, @@ -211,25 +210,27 @@ impl DepGraph { push: fn(&RefCell, DepNode), pop: fn(&RefCell, DepNode) -> DepNodeIndex) -> (R, DepNodeIndex) - where C: DepGraphSafe + StableHashingContextProvider, - R: HashStable, + where C: DepGraphSafe + StableHashingContextProvider<'gcx>, + R: HashStable>, { if let Some(ref data) = self.data { push(&data.current, key); - if cfg!(debug_assertions) { - profq_msg(ProfileQueriesMsg::TaskBegin(key.clone())) - }; // In incremental mode, hash the result of the task. We don't // do anything with the hash yet, but we are computing it // anyway so that // - we make sure that the infrastructure works and // - we can get an idea of the runtime cost. - let mut hcx = cx.create_stable_hashing_context(); + let mut hcx = cx.get_stable_hashing_context(); + + if cfg!(debug_assertions) { + profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone())) + }; let result = task(cx, arg); + if cfg!(debug_assertions) { - profq_msg(ProfileQueriesMsg::TaskEnd) + profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) }; let dep_node_index = pop(&data.current, key); @@ -274,7 +275,7 @@ impl DepGraph { (result, dep_node_index) } else { if key.kind.fingerprint_needed_for_crate_hash() { - let mut hcx = cx.create_stable_hashing_context(); + let mut hcx = cx.get_stable_hashing_context(); let result = task(cx, arg); let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); @@ -314,14 +315,14 @@ impl DepGraph { /// Execute something within an "eval-always" task which is a task // that runs whenever anything changes. - pub fn with_eval_always_task(&self, + pub fn with_eval_always_task<'gcx, C, A, R>(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> (R, DepNodeIndex) - where C: DepGraphSafe + StableHashingContextProvider, - R: HashStable, + where C: DepGraphSafe + StableHashingContextProvider<'gcx>, + R: HashStable>, { self.with_task_impl(key, cx, arg, task, |data, key| data.borrow_mut().push_eval_always_task(key), @@ -475,10 +476,8 @@ impl DepGraph { fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO); } - let nodes: IndexVec<_, (DepNode, Fingerprint)> = - current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| { - (dep_node, fingerprints[idx]) - }).collect(); + let fingerprints = fingerprints.clone().convert_index_type(); + let nodes = current_dep_graph.nodes.clone().convert_index_type(); let total_edge_count: usize = current_dep_graph.edges.iter() .map(|v| v.len()) @@ -502,6 +501,7 @@ impl DepGraph { SerializedDepGraph { nodes, + fingerprints, edge_list_indices, edge_list_data, } @@ -647,8 +647,15 @@ impl DepGraph { return None } None => { - bug!("try_mark_green() - Forcing the DepNode \ - should have set its color") + if !tcx.sess.has_errors() { + bug!("try_mark_green() - Forcing the DepNode \ + should have set its color") + } else { + // If the query we just forced has resulted + // in some kind of compilation error, we + // don't expect that the corresponding + // dep-node color has been updated. + } } } } else { diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs index 504b60e763e2..669a99019aa6 100644 --- a/src/librustc/dep_graph/prev.rs +++ b/src/librustc/dep_graph/prev.rs @@ -23,7 +23,7 @@ impl PreviousDepGraph { pub fn new(data: SerializedDepGraph) -> PreviousDepGraph { let index: FxHashMap<_, _> = data.nodes .iter_enumerated() - .map(|(idx, &(dep_node, _))| (dep_node, idx)) + .map(|(idx, &dep_node)| (dep_node, idx)) .collect(); PreviousDepGraph { data, index } } @@ -41,7 +41,7 @@ impl PreviousDepGraph { #[inline] pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { - self.data.nodes[dep_node_index].0 + self.data.nodes[dep_node_index] } #[inline] @@ -58,14 +58,14 @@ impl PreviousDepGraph { pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option { self.index .get(dep_node) - .map(|&node_index| self.data.nodes[node_index].1) + .map(|&node_index| self.data.fingerprints[node_index]) } #[inline] pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fingerprint { - self.data.nodes[dep_node_index].1 + self.data.fingerprints[dep_node_index] } pub fn node_count(&self) -> usize { diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs index c96040ab9b6e..60fc813a25d5 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc/dep_graph/serialized.rs @@ -20,7 +20,10 @@ newtype_index!(SerializedDepNodeIndex); #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - pub nodes: IndexVec, + pub nodes: IndexVec, + /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to + /// the DepNode at the same index in the nodes vector. + pub fingerprints: IndexVec, /// For each DepNode, stores the list of edges originating from that /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, /// which holds the actual DepNodeIndices of the target nodes. @@ -35,6 +38,7 @@ impl SerializedDepGraph { pub fn new() -> SerializedDepGraph { SerializedDepGraph { nodes: IndexVec::new(), + fingerprints: IndexVec::new(), edge_list_indices: IndexVec::new(), edge_list_data: Vec::new(), } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index b3a904f2f5fe..2662e7099919 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -887,65 +887,6 @@ foo(3_i8); // therefore the type-checker complains with this error code. ``` -Here is a more subtle instance of the same problem, that can -arise with for-loops in Rust: - -```compile_fail -let vs: Vec = vec![1, 2, 3, 4]; -for v in &vs { - match v { - 1 => {}, - _ => {}, - } -} -``` - -The above fails because of an analogous type mismatch, -though may be harder to see. Again, here are some -explanatory comments for the same example: - -```compile_fail -{ - let vs = vec![1, 2, 3, 4]; - - // `for`-loops use a protocol based on the `Iterator` - // trait. Each item yielded in a `for` loop has the - // type `Iterator::Item` -- that is, `Item` is the - // associated type of the concrete iterator impl. - for v in &vs { -// ~ ~~~ -// | | -// | We borrow `vs`, iterating over a sequence of -// | *references* of type `&Elem` (where `Elem` is -// | vector's element type). Thus, the associated -// | type `Item` must be a reference `&`-type ... -// | -// ... and `v` has the type `Iterator::Item`, as dictated by -// the `for`-loop protocol ... - - match v { - 1 => {} -// ~ -// | -// ... but *here*, `v` is forced to have some integral type; -// only types like `u8`,`i8`,`u16`,`i16`, et cetera can -// match the pattern `1` ... - - _ => {} - } - -// ... therefore, the compiler complains, because it sees -// an attempt to solve the equations -// `some integral-type` = type-of-`v` -// = `Iterator::Item` -// = `&Elem` (i.e. `some reference type`) -// -// which cannot possibly all be true. - - } -} -``` - To avoid those issues, you have to make the types match correctly. So we can fix the previous examples like this: @@ -1764,12 +1705,12 @@ The `main` function was incorrectly declared. Erroneous code example: ```compile_fail,E0580 -fn main() -> i32 { // error: main function has wrong type - 0 +fn main(x: i32) { // error: main function has wrong type + println!("{}", x); } ``` -The `main` function prototype should never take arguments or return type. +The `main` function prototype should never take arguments. Example: ``` @@ -1789,8 +1730,6 @@ allowed as function return types. Erroneous code example: ```compile_fail,E0562 -#![feature(conservative_impl_trait)] - fn main() { let count_to_ten: impl Iterator = 0..10; // error: `impl Trait` not allowed outside of function and inherent method @@ -1804,8 +1743,6 @@ fn main() { Make sure `impl Trait` only appears in return-type position. ``` -#![feature(conservative_impl_trait)] - fn count_to_n(n: usize) -> impl Iterator { 0..n } @@ -2074,6 +2011,81 @@ a (non-transparent) struct containing a single float, while `Grams` is a transparent wrapper around a float. This can make a difference for the ABI. "##, +E0909: r##" +The `impl Trait` return type captures lifetime parameters that do not +appear within the `impl Trait` itself. + +Erroneous code example: + +```compile-fail,E0909 +use std::cell::Cell; + +trait Trait<'a> { } + +impl<'a, 'b> Trait<'b> for Cell<&'a u32> { } + +fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> +where 'x: 'y +{ + x +} +``` + +Here, the function `foo` returns a value of type `Cell<&'x u32>`, +which references the lifetime `'x`. However, the return type is +declared as `impl Trait<'y>` -- this indicates that `foo` returns +"some type that implements `Trait<'y>`", but it also indicates that +the return type **only captures data referencing the lifetime `'y`**. +In this case, though, we are referencing data with lifetime `'x`, so +this function is in error. + +To fix this, you must reference the lifetime `'x` from the return +type. For example, changing the return type to `impl Trait<'y> + 'x` +would work: + +``` +use std::cell::Cell; + +trait Trait<'a> { } + +impl<'a,'b> Trait<'b> for Cell<&'a u32> { } + +fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x +where 'x: 'y +{ + x +} +``` +"##, + +E0910: r##" +This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed +on something other than a struct or enum. + +Examples of erroneous code: + +```compile_fail,E0910 +# #![feature(non_exhaustive)] + +#[non_exhaustive] +trait Foo { } +``` +"##, + +E0911: r##" +This error indicates that a `#[non_exhaustive]` attribute had a value. The +`#[non_exhaustive]` should be empty. + +Examples of erroneous code: + +```compile_fail,E0911 +# #![feature(non_exhaustive)] + +#[non_exhaustive(anything)] +struct Foo; +``` +"##, + } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index d7194e9c2cab..956cd17f38f2 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -14,6 +14,7 @@ //! conflicts between multiple such attributes attached to the same //! item. +use syntax_pos::Span; use ty::TyCtxt; use hir; @@ -25,6 +26,10 @@ enum Target { Struct, Union, Enum, + Const, + ForeignMod, + Expression, + Statement, Other, } @@ -35,6 +40,8 @@ impl Target { hir::ItemStruct(..) => Target::Struct, hir::ItemUnion(..) => Target::Union, hir::ItemEnum(..) => Target::Enum, + hir::ItemConst(..) => Target::Const, + hir::ItemForeignMod(..) => Target::ForeignMod, _ => Target::Other, } } @@ -55,25 +62,80 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { .emit(); } + let mut has_wasm_import_module = false; for attr in &item.attrs { - if let Some(name) = attr.name() { - if name == "inline" { - self.check_inline(attr, item, target) + if attr.check_name("inline") { + self.check_inline(attr, &item.span, target) + } else if attr.check_name("non_exhaustive") { + self.check_non_exhaustive(attr, item, target) + } else if attr.check_name("wasm_import_module") { + has_wasm_import_module = true; + if attr.value_str().is_none() { + self.tcx.sess.span_err(attr.span, "\ + must be of the form #[wasm_import_module = \"...\"]"); + } + if target != Target::ForeignMod { + self.tcx.sess.span_err(attr.span, "\ + must only be attached to foreign modules"); + } + } else if attr.check_name("wasm_custom_section") { + if target != Target::Const { + self.tcx.sess.span_err(attr.span, "only allowed on consts"); + } + + if attr.value_str().is_none() { + self.tcx.sess.span_err(attr.span, "must be of the form \ + #[wasm_custom_section = \"foo\"]"); } } } + if target == Target::ForeignMod && + !has_wasm_import_module && + self.tcx.sess.target.target.arch == "wasm32" && + false // FIXME: eventually enable this warning when stable + { + self.tcx.sess.span_warn(item.span, "\ + must have a #[wasm_import_module = \"...\"] attribute, this \ + will become a hard error before too long"); + } + self.check_repr(item, target); } /// Check if an `#[inline]` is applied to a function. - fn check_inline(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) { + fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) { if target != Target::Fn { struct_span_err!(self.tcx.sess, attr.span, E0518, "attribute should be applied to function") - .span_label(item.span, "not a function") + .span_label(*span, "not a function") + .emit(); + } + } + + /// Check if the `#[non_exhaustive]` attribute on an `item` is valid. + fn check_non_exhaustive(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) { + match target { + Target::Struct | Target::Enum => { /* Valid */ }, + _ => { + struct_span_err!(self.tcx.sess, + attr.span, + E0910, + "attribute can only be applied to a struct or enum") + .span_label(item.span, "not a struct or enum") + .emit(); + return; + } + } + + if attr.meta_item_list().is_some() || attr.value_str().is_some() { + struct_span_err!(self.tcx.sess, + attr.span, + E0911, + "attribute should be empty") + .span_label(item.span, "not empty") .emit(); } } @@ -164,10 +226,12 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } _ => continue, }; - struct_span_err!(self.tcx.sess, hint.span, E0517, - "attribute should be applied to {}", allowed_targets) - .span_label(item.span, format!("not {} {}", article, allowed_targets)) - .emit(); + self.emit_repr_error( + hint.span, + item.span, + &format!("attribute should be applied to {}", allowed_targets), + &format!("not {} {}", article, allowed_targets), + ) } // Just point at all repr hints if there are any incompatibilities. @@ -189,17 +253,75 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { "conflicting representation hints"); } } + + fn emit_repr_error( + &self, + hint_span: Span, + label_span: Span, + hint_message: &str, + label_message: &str, + ) { + struct_span_err!(self.tcx.sess, hint_span, E0517, "{}", hint_message) + .span_label(label_span, label_message) + .emit(); + } + + fn check_stmt_attributes(&self, stmt: &hir::Stmt) { + // When checking statements ignore expressions, they will be checked later + if let hir::Stmt_::StmtDecl(_, _) = stmt.node { + for attr in stmt.node.attrs() { + if attr.check_name("inline") { + self.check_inline(attr, &stmt.span, Target::Statement); + } + if attr.check_name("repr") { + self.emit_repr_error( + attr.span, + stmt.span, + &format!("attribute should not be applied to a statement"), + &format!("not a struct, enum or union"), + ); + } + } + } + } + + fn check_expr_attributes(&self, expr: &hir::Expr) { + for attr in expr.attrs.iter() { + if attr.check_name("inline") { + self.check_inline(attr, &expr.span, Target::Expression); + } + if attr.check_name("repr") { + self.emit_repr_error( + attr.span, + expr.span, + &format!("attribute should not be applied to an expression"), + &format!("not defining a struct, enum or union"), + ); + } + } + } } impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None + NestedVisitorMap::OnlyBodies(&self.tcx.hir) } fn visit_item(&mut self, item: &'tcx hir::Item) { let target = Target::from_item(item); self.check_attributes(item, target); - intravisit::walk_item(self, item); + intravisit::walk_item(self, item) + } + + + fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) { + self.check_stmt_attributes(stmt); + intravisit::walk_stmt(self, stmt) + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + self.check_expr_attributes(expr); + intravisit::walk_expr(self, expr) } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index b804cf7bf5a3..9f51eb8c35a8 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -420,7 +420,10 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime LifetimeName::Name(name) => { visitor.visit_name(lifetime.span, name); } - LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {} + LifetimeName::Fresh(_) | + LifetimeName::Static | + LifetimeName::Implicit | + LifetimeName::Underscore => {} } } @@ -444,10 +447,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_vis(&item.vis); visitor.visit_name(item.span, item.name); match item.node { - ItemExternCrate(opt_name) => { + ItemExternCrate(orig_name) => { visitor.visit_id(item.id); - if let Some(name) = opt_name { - visitor.visit_name(item.span, name); + if let Some(orig_name) = orig_name { + visitor.visit_name(item.span, orig_name); } } ItemUse(ref path, _) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 49611689fc4a..5f9f37094f57 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -43,8 +43,8 @@ use dep_graph::DepGraph; use hir; use hir::HirVec; -use hir::map::{Definitions, DefKey, DefPathData}; -use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX, DefIndexAddressSpace}; +use hir::map::{DefKey, DefPathData, Definitions}; +use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; use hir::def::{Def, PathResolution}; use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES}; use middle::cstore::CrateStore; @@ -63,10 +63,10 @@ use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::print::pprust; use syntax::ptr::P; -use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind}; +use syntax::codemap::{self, respan, CompilerDesugaringKind, Spanned}; use syntax::std_inject; -use syntax::symbol::{Symbol, keywords}; -use syntax::tokenstream::{TokenStream, TokenTree, Delimited}; +use syntax::symbol::{keywords, Symbol}; +use syntax::tokenstream::{Delimited, TokenStream, TokenTree}; use syntax::parse::token::Token; use syntax::util::small_vector::SmallVector; use syntax::visit::{self, Visitor}; @@ -80,13 +80,13 @@ pub struct LoweringContext<'a> { // Use to assign ids to hir nodes that do not directly correspond to an ast node sess: &'a Session, - cstore: &'a dyn CrateStore, + cstore: &'a CrateStore, // As we walk the AST we must keep track of the current 'parent' def id (in // the form of a DefIndex) so that if we create a new node which introduces // a definition, then we can properly create the def id. parent_def: Option, - resolver: &'a mut dyn Resolver, + resolver: &'a mut Resolver, name_map: FxHashMap, /// The items being lowered are collected here. @@ -107,6 +107,12 @@ pub struct LoweringContext<'a> { is_in_loop_condition: bool, is_in_trait_impl: bool, + /// What to do when we encounter either an "anonymous lifetime + /// reference". The term "anonymous" is meant to encompass both + /// `'_` lifetimes as well as fully elided cases where nothing is + /// written at all (e.g., `&T` or `std::cell::Ref`). + anonymous_lifetime_mode: AnonymousLifetimeMode, + // This is a list of in-band type definitions being generated by // Argument-position `impl Trait`. // When traversing a signature such as `fn foo(x: impl Trait)`, @@ -121,13 +127,15 @@ pub struct LoweringContext<'a> { // (i.e. it doesn't appear in the in_scope_lifetimes list), it is added // to this list. The results of this list are then added to the list of // lifetime definitions in the corresponding impl or function generics. - lifetimes_to_define: Vec<(Span, Name)>, + lifetimes_to_define: Vec<(Span, hir::LifetimeName)>, + // Whether or not in-band lifetimes are being collected. This is used to // indicate whether or not we're in a place where new lifetimes will result // in in-band lifetime definitions, such a function or an impl header. // This will always be false unless the `in_band_lifetimes` feature is // enabled. is_collecting_in_band_lifetimes: bool, + // Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB. // When `is_collectin_in_band_lifetimes` is true, each lifetime is checked // against this list to see if it is already in-scope, or if a definition @@ -154,8 +162,13 @@ pub trait Resolver { /// Given suffix ["b","c","d"], creates a HIR path for `[::crate_root]::b::c::d` and resolves /// it based on `is_value`. - fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>, - components: &[&str], is_value: bool) -> hir::Path; + fn resolve_str_path( + &mut self, + span: Span, + crate_root: Option<&str>, + components: &[&str], + is_value: bool, + ) -> hir::Path; } #[derive(Clone, Copy, Debug)] @@ -176,12 +189,13 @@ enum ImplTraitContext { Disallowed, } -pub fn lower_crate(sess: &Session, - cstore: &dyn CrateStore, - dep_graph: &DepGraph, - krate: &Crate, - resolver: &mut dyn Resolver) - -> hir::Crate { +pub fn lower_crate( + sess: &Session, + cstore: &CrateStore, + dep_graph: &DepGraph, + krate: &Crate, + resolver: &mut Resolver, +) -> hir::Crate { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to // incr. comp. yet. @@ -204,6 +218,7 @@ pub fn lower_crate(sess: &Session, catch_scopes: Vec::new(), loop_scopes: Vec::new(), is_in_loop_condition: false, + anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, type_def_lifetime_params: DefIdMap(), current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], item_local_id_counters: NodeMap(), @@ -222,7 +237,7 @@ enum ParamMode { /// Any path in a type context. Explicit, /// The `module::Type` in `module::Type::method` in an expression. - Optional + Optional, } struct LoweredNodeId { @@ -236,6 +251,51 @@ enum ParenthesizedGenericArgs { Err, } +/// What to do when we encounter an **anonymous** lifetime +/// reference. Anonymous lifetime references come in two flavors. You +/// have implicit, or fully elided, references to lifetimes, like the +/// one in `&T` or `Ref`, and you have `'_` lifetimes, like `&'_ T` +/// or `Ref<'_, T>`. These often behave the same, but not always: +/// +/// - certain usages of implicit references are deprecated, like +/// `Ref`, and we sometimes just give hard errors in those cases +/// as well. +/// - for object bounds there is a difference: `Box` is not +/// the same as `Box`. +/// +/// We describe the effects of the various modes in terms of three cases: +/// +/// - **Modern** -- includes all uses of `'_`, but also the lifetime arg +/// of a `&` (e.g., the missing lifetime in something like `&T`) +/// - **Dyn Bound** -- if you have something like `Box`, +/// there is an elided lifetime bound (`Box`). These +/// elided bounds follow special rules. Note that this only covers +/// cases where *nothing* is written; the `'_` in `Box` is a case of "modern" elision. +/// - **Deprecated** -- this coverse cases like `Ref`, where the lifetime +/// parameter to ref is completely elided. `Ref<'_, T>` would be the modern, +/// non-deprecated equivalent. +/// +/// Currently, the handling of lifetime elision is somewhat spread out +/// between HIR lowering and -- as described below -- the +/// `resolve_lifetime` module. Often we "fallthrough" to that code by generating +/// an "elided" or "underscore" lifetime name. In the future, we probably want to move +/// everything into HIR lowering. +#[derive(Copy, Clone)] +enum AnonymousLifetimeMode { + /// For **Modern** cases, create a new anonymous region parameter + /// and reference that. + /// + /// For **Dyn Bound** cases, pass responsibility to + /// `resolve_lifetime` code. + /// + /// For **Deprecated** cases, report an error. + CreateParameter, + + /// Pass responsibility to `resolve_lifetime` code for all cases. + PassThrough, +} + impl<'a> LoweringContext<'a> { fn lower_crate(mut self, c: &Crate) -> hir::Crate { /// Full-crate AST visitor that inserts into a fresh @@ -252,13 +312,15 @@ impl<'a> LoweringContext<'a> { self.lctx.allocate_hir_id_counter(item.id, item); match item.node { - ItemKind::Struct(_, ref generics) | - ItemKind::Union(_, ref generics) | - ItemKind::Enum(_, ref generics) | - ItemKind::Ty(_, ref generics) | - ItemKind::Trait(_, _, ref generics, ..) => { + ItemKind::Struct(_, ref generics) + | ItemKind::Union(_, ref generics) + | ItemKind::Enum(_, ref generics) + | ItemKind::Ty(_, ref generics) + | ItemKind::Trait(_, _, ref generics, ..) => { let def_id = self.lctx.resolver.definitions().local_def_id(item.id); - let count = generics.params.iter() + let count = generics + .params + .iter() .filter(|param| param.is_lifetime_param()) .count(); self.lctx.type_def_lifetime_params.insert(def_id, count); @@ -285,7 +347,8 @@ impl<'a> LoweringContext<'a> { impl<'lcx, 'interner> ItemLowerer<'lcx, 'interner> { fn with_trait_impl_ref(&mut self, trait_impl_ref: &Option, f: F) - where F: FnOnce(&mut Self) + where + F: FnOnce(&mut Self), { let old = self.lctx.is_in_trait_impl; self.lctx.is_in_trait_impl = if let &None = trait_impl_ref { @@ -311,22 +374,24 @@ impl<'a> LoweringContext<'a> { if item_lowered { let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node { - hir::Item_::ItemImpl(_,_,_,ref generics,..) | - hir::Item_::ItemTrait(_,_,ref generics,..) => - generics.lifetimes().cloned().collect::>(), + hir::Item_::ItemImpl(_, _, _, ref generics, ..) + | hir::Item_::ItemTrait(_, _, ref generics, ..) => { + generics.lifetimes().cloned().collect::>() + } _ => Vec::new(), }; - self.lctx.with_parent_impl_lifetime_defs(&item_lifetimes, |this| { - let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl(_,_,_,_,ref opt_trait_ref,_,_) = item.node { - this.with_trait_impl_ref(opt_trait_ref, |this| { - visit::walk_item(this, item) - }); - } else { - visit::walk_item(this, item); - } - }); + self.lctx + .with_parent_impl_lifetime_defs(&item_lifetimes, |this| { + let this = &mut ItemLowerer { lctx: this }; + if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node { + this.with_trait_impl_ref(opt_trait_ref, |this| { + visit::walk_item(this, item) + }); + } else { + visit::walk_item(this, item); + } + }); } } @@ -379,27 +444,26 @@ impl<'a> LoweringContext<'a> { } } - fn allocate_hir_id_counter(&mut self, - owner: NodeId, - debug: &T) { + fn allocate_hir_id_counter(&mut self, owner: NodeId, debug: &T) { if self.item_local_id_counters.insert(owner, 0).is_some() { - bug!("Tried to allocate item_local_id_counter for {:?} twice", debug); + bug!( + "Tried to allocate item_local_id_counter for {:?} twice", + debug + ); } // Always allocate the first HirId for the owner itself self.lower_node_id_with_owner(owner, owner); } - fn lower_node_id_generic(&mut self, - ast_node_id: NodeId, - alloc_hir_id: F) - -> LoweredNodeId - where F: FnOnce(&mut Self) -> hir::HirId + fn lower_node_id_generic(&mut self, ast_node_id: NodeId, alloc_hir_id: F) -> LoweredNodeId + where + F: FnOnce(&mut Self) -> hir::HirId, { if ast_node_id == DUMMY_NODE_ID { return LoweredNodeId { node_id: DUMMY_NODE_ID, hir_id: hir::DUMMY_HIR_ID, - } + }; } let min_size = ast_node_id.as_usize() + 1; @@ -427,11 +491,12 @@ impl<'a> LoweringContext<'a> { } fn with_hir_id_owner(&mut self, owner: NodeId, f: F) - where F: FnOnce(&mut Self) + where + F: FnOnce(&mut Self), { let counter = self.item_local_id_counters - .insert(owner, HIR_ID_COUNTER_LOCKED) - .unwrap(); + .insert(owner, HIR_ID_COUNTER_LOCKED) + .unwrap(); let def_index = self.resolver.definitions().opt_def_index(owner).unwrap(); self.current_hir_id_owner.push((def_index, counter)); f(self); @@ -440,7 +505,9 @@ impl<'a> LoweringContext<'a> { debug_assert!(def_index == new_def_index); debug_assert!(new_counter >= counter); - let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap(); + let prev = self.item_local_id_counters + .insert(owner, new_counter) + .unwrap(); debug_assert!(prev == HIR_ID_COUNTER_LOCKED); } @@ -452,9 +519,8 @@ impl<'a> LoweringContext<'a> { /// properly. Calling the method twice with the same NodeId is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> LoweredNodeId { self.lower_node_id_generic(ast_node_id, |this| { - let &mut (def_index, ref mut local_id_counter) = this.current_hir_id_owner - .last_mut() - .unwrap(); + let &mut (def_index, ref mut local_id_counter) = + this.current_hir_id_owner.last_mut().unwrap(); let local_id = *local_id_counter; *local_id_counter += 1; hir::HirId { @@ -464,14 +530,9 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_node_id_with_owner(&mut self, - ast_node_id: NodeId, - owner: NodeId) - -> LoweredNodeId { + fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> LoweredNodeId { self.lower_node_id_generic(ast_node_id, |this| { - let local_id_counter = this.item_local_id_counters - .get_mut(&owner) - .unwrap(); + let local_id_counter = this.item_local_id_counters.get_mut(&owner).unwrap(); let local_id = *local_id_counter; // We want to be sure not to modify the counter in the map while it @@ -489,8 +550,7 @@ impl<'a> LoweringContext<'a> { }) } - fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>) - -> hir::BodyId { + fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>) -> hir::BodyId { let body = hir::Body { arguments: decl.map_or(hir_vec![], |decl| { decl.inputs.iter().map(|x| self.lower_arg(x)).collect() @@ -524,8 +584,7 @@ impl<'a> LoweringContext<'a> { Symbol::gensym(s) } - fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, span: Span) -> Span - { + fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, span: Span) -> Span { let mark = Mark::fresh(Mark::root()); mark.set_expn_info(codemap::ExpnInfo { call_site: span, @@ -539,73 +598,139 @@ impl<'a> LoweringContext<'a> { span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } - // Creates a new hir::GenericParam for every new lifetime and type parameter - // encountered while evaluating `f`. Definitions are created with the parent - // provided. If no `parent_id` is provided, no definitions will be returned. + /// Creates a new hir::GenericParam for every new lifetime and + /// type parameter encountered while evaluating `f`. Definitions + /// are created with the parent provided. If no `parent_id` is + /// provided, no definitions will be returned. + /// + /// Presuming that in-band lifetimes are enabled, then + /// `self.anonymous_lifetime_mode` will be updated to match the + /// argument while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_id: Option, - f: F - ) -> (Vec, T) where F: FnOnce(&mut LoweringContext) -> T + parent_id: DefId, + anonymous_lifetime_mode: AnonymousLifetimeMode, + f: F, + ) -> (Vec, T) + where + F: FnOnce(&mut LoweringContext) -> T, { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); + let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; + self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes; + if self.is_collecting_in_band_lifetimes { + self.anonymous_lifetime_mode = anonymous_lifetime_mode; + } assert!(self.in_band_ty_params.is_empty()); - let res = f(self); self.is_collecting_in_band_lifetimes = false; + self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; let in_band_ty_params = self.in_band_ty_params.split_off(0); let lifetimes_to_define = self.lifetimes_to_define.split_off(0); - let mut params = match parent_id { - Some(parent_id) => lifetimes_to_define.into_iter().map(|(span, name)| { - let def_node_id = self.next_id().node_id; + let params = lifetimes_to_define + .into_iter() + .map(|(span, hir_name)| { + let def_node_id = self.next_id().node_id; - // Add a definition for the in-band lifetime def - self.resolver.definitions().create_def_with_parent( - parent_id.index, - def_node_id, - DefPathData::LifetimeDef(name.as_str()), - DefIndexAddressSpace::High, - Mark::root(), - span - ); + // Get the name we'll use to make the def-path. Note + // that collisions are ok here and this shouldn't + // really show up for end-user. + let str_name = match hir_name { + hir::LifetimeName::Name(n) => n.as_str(), + hir::LifetimeName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(), + hir::LifetimeName::Implicit + | hir::LifetimeName::Underscore + | hir::LifetimeName::Static => { + span_bug!(span, "unexpected in-band lifetime name: {:?}", hir_name) + } + }; - hir::GenericParam::Lifetime(hir::LifetimeDef { - lifetime: hir::Lifetime { - id: def_node_id, - span, - name: hir::LifetimeName::Name(name), - }, - bounds: Vec::new().into(), - pure_wrt_drop: false, - in_band: true, - }) - }).collect(), - None => Vec::new(), - }; + // Add a definition for the in-band lifetime def + self.resolver.definitions().create_def_with_parent( + parent_id.index, + def_node_id, + DefPathData::LifetimeDef(str_name), + DefIndexAddressSpace::High, + Mark::root(), + span, + ); - params.extend(in_band_ty_params.into_iter().map(|tp| hir::GenericParam::Type(tp))); + hir::GenericParam::Lifetime(hir::LifetimeDef { + lifetime: hir::Lifetime { + id: def_node_id, + span, + name: hir_name, + }, + bounds: Vec::new().into(), + pure_wrt_drop: false, + in_band: true, + }) + }) + .chain( + in_band_ty_params + .into_iter() + .map(|tp| hir::GenericParam::Type(tp)), + ) + .collect(); (params, res) } + /// When there is a reference to some lifetime `'a`, and in-band + /// lifetimes are enabled, then we want to push that lifetime into + /// the vector of names to define later. In that case, it will get + /// added to the appropriate generics. + fn maybe_collect_in_band_lifetime(&mut self, span: Span, name: Name) { + if !self.is_collecting_in_band_lifetimes { + return; + } + + if self.in_scope_lifetimes.contains(&name) { + return; + } + + let hir_name = hir::LifetimeName::Name(name); + + if self.lifetimes_to_define + .iter() + .any(|(_, lt_name)| *lt_name == hir_name) + { + return; + } + + self.lifetimes_to_define.push((span, hir_name)); + } + + /// When we have either an elided or `'_` lifetime in an impl + /// header, we convert it to + fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> hir::LifetimeName { + assert!(self.is_collecting_in_band_lifetimes); + let index = self.lifetimes_to_define.len(); + let hir_name = hir::LifetimeName::Fresh(index); + self.lifetimes_to_define.push((span, hir_name)); + hir_name + } + // Evaluates `f` with the lifetimes in `lt_defs` in-scope. // This is used to track which lifetimes have already been defined, and // which are new in-band lifetimes that need to have a definition created // for them. - fn with_in_scope_lifetime_defs( + fn with_in_scope_lifetime_defs<'l, T, F>( &mut self, - lt_defs: &[LifetimeDef], - f: F - ) -> T where F: FnOnce(&mut LoweringContext) -> T + lt_defs: impl Iterator, + f: F, + ) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { let old_len = self.in_scope_lifetimes.len(); - let lt_def_names = lt_defs.iter().map(|lt_def| lt_def.lifetime.ident.name); + let lt_def_names = lt_defs.map(|lt_def| lt_def.lifetime.ident.name); self.in_scope_lifetimes.extend(lt_def_names); let res = f(self); @@ -619,11 +744,9 @@ impl<'a> LoweringContext<'a> { // This should only be used with generics that have already had their // in-band lifetimes added. In practice, this means that this function is // only used when lowering a child item of a trait or impl. - fn with_parent_impl_lifetime_defs( - &mut self, - lt_defs: &[hir::LifetimeDef], - f: F - ) -> T where F: FnOnce(&mut LoweringContext) -> T + fn with_parent_impl_lifetime_defs(&mut self, lt_defs: &[hir::LifetimeDef], f: F) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { let old_len = self.in_scope_lifetimes.len(); let lt_def_names = lt_defs.iter().map(|lt_def| lt_def.lifetime.name.name()); @@ -635,47 +758,57 @@ impl<'a> LoweringContext<'a> { res } - // Appends in-band lifetime defs and argument-position `impl Trait` defs - // to the existing set of generics. + /// Appends in-band lifetime defs and argument-position `impl + /// Trait` defs to the existing set of generics. + /// + /// Presuming that in-band lifetimes are enabled, then + /// `self.anonymous_lifetime_mode` will be updated to match the + /// argument while `f` is running (and restored afterwards). fn add_in_band_defs( &mut self, generics: &Generics, - parent_id: Option, - f: F + parent_id: DefId, + anonymous_lifetime_mode: AnonymousLifetimeMode, + f: F, ) -> (hir::Generics, T) - where F: FnOnce(&mut LoweringContext) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { - let (in_band_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs( - &generics.params - .iter() - .filter_map(|p| match *p { - GenericParam::Lifetime(ref ld) => Some(ld.clone()), - _ => None, - }) - .collect::>(), - |this| { - this.collect_in_band_defs(parent_id, |this| { - (this.lower_generics(generics), f(this)) - }) - } - ); + let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( + generics.params.iter().filter_map(|p| match p { + GenericParam::Lifetime(ld) => Some(ld), + _ => None, + }), + |this| { + this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { + (this.lower_generics(generics), f(this)) + }) + }, + ); - lowered_generics.params = - lowered_generics.params.iter().cloned().chain(in_band_defs).collect(); + lowered_generics.params = lowered_generics + .params + .iter() + .cloned() + .chain(in_band_defs) + .collect(); (lowered_generics, res) } fn with_catch_scope(&mut self, catch_id: NodeId, f: F) -> T - where F: FnOnce(&mut LoweringContext) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { let len = self.catch_scopes.len(); self.catch_scopes.push(catch_id); let result = f(self); - assert_eq!(len + 1, self.catch_scopes.len(), - "catch scopes should be added and removed in stack order"); + assert_eq!( + len + 1, + self.catch_scopes.len(), + "catch scopes should be added and removed in stack order" + ); self.catch_scopes.pop().unwrap(); @@ -683,17 +816,19 @@ impl<'a> LoweringContext<'a> { } fn lower_body(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId - where F: FnOnce(&mut LoweringContext) -> hir::Expr + where + F: FnOnce(&mut LoweringContext) -> hir::Expr, { let prev = mem::replace(&mut self.is_generator, false); let result = f(self); let r = self.record_body(result, decl); self.is_generator = prev; - return r + return r; } fn with_loop_scope(&mut self, loop_id: NodeId, f: F) -> T - where F: FnOnce(&mut LoweringContext) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { // We're no longer in the base loop's condition; we're in another loop. let was_in_loop_condition = self.is_in_loop_condition; @@ -703,8 +838,11 @@ impl<'a> LoweringContext<'a> { self.loop_scopes.push(loop_id); let result = f(self); - assert_eq!(len + 1, self.loop_scopes.len(), - "Loop scopes should be added and removed in stack order"); + assert_eq!( + len + 1, + self.loop_scopes.len(), + "Loop scopes should be added and removed in stack order" + ); self.loop_scopes.pop().unwrap(); @@ -714,7 +852,8 @@ impl<'a> LoweringContext<'a> { } fn with_loop_condition_scope(&mut self, f: F) -> T - where F: FnOnce(&mut LoweringContext) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = true; @@ -727,7 +866,8 @@ impl<'a> LoweringContext<'a> { } fn with_new_scopes(&mut self, f: F) -> T - where F: FnOnce(&mut LoweringContext) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -744,7 +884,8 @@ impl<'a> LoweringContext<'a> { } fn with_parent_def(&mut self, parent_id: NodeId, f: F) -> T - where F: FnOnce(&mut LoweringContext) -> T + where + F: FnOnce(&mut LoweringContext) -> T, { let old_def = self.parent_def; self.parent_def = { @@ -771,16 +912,19 @@ impl<'a> LoweringContext<'a> { if ident.ctxt == SyntaxContext::empty() { return ident.name; } - *self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident)) + *self.name_map + .entry(ident) + .or_insert_with(|| Symbol::from_ident(ident)) } fn lower_label(&mut self, label: Option { } pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: RangeBounds { match *self { AccumulateVec::Array(ref mut v) => { diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index 511c407d45a7..db1cfb5c7676 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -18,9 +18,9 @@ use std::hash::{Hash, Hasher}; use std::slice; use std::fmt; use std::mem; -use std::collections::range::RangeArgument; -use std::collections::Bound::{Excluded, Included, Unbounded}; use std::mem::ManuallyDrop; +use std::ops::Bound::{Excluded, Included, Unbounded}; +use std::ops::RangeBounds; pub unsafe trait Array { type Element; @@ -106,7 +106,7 @@ impl ArrayVec { } pub fn drain(&mut self, range: R) -> Drain - where R: RangeArgument + where R: RangeBounds { // Memory safety // diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 54565afa4c6c..28e3180063c1 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -132,6 +132,11 @@ impl<'a> Iterator for BitVectorIter<'a> { self.idx += offset + 1; return Some(self.idx - 1); } + + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } } impl FromIterator for BitVector { diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 1945b82c0314..e2b393071ff5 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -334,6 +334,11 @@ impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> { self.next = edge.next_edge[self.direction.repr]; Some((edge_index, edge)) } + + fn size_hint(&self) -> (usize, Option) { + // At most, all the edges in the graph. + (0, Some(self.graph.len_edges())) + } } pub struct DepthFirstTraversal<'g, N, E> @@ -383,8 +388,16 @@ impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> { } next } + + fn size_hint(&self) -> (usize, Option) { + // We will visit every node in the graph exactly once. + let remaining = self.graph.len_nodes() - self.visited.count(); + (remaining, Some(remaining)) + } } +impl<'g, N: Debug, E: Debug> ExactSizeIterator for DepthFirstTraversal<'g, N, E> {} + impl Edge { pub fn source(&self) -> NodeIndex { self.source diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index 223e08de826c..c9495587c468 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -121,7 +121,9 @@ impl IdxSetBuf { /// Creates set holding every element whose index falls in range 0..universe_size. pub fn new_filled(universe_size: usize) -> Self { - Self::new(!0, universe_size) + let mut result = Self::new(!0, universe_size); + result.trim_to(universe_size); + result } /// Creates set holding no elements. @@ -168,6 +170,36 @@ impl IdxSet { } } + /// Sets all elements up to `universe_size` + pub fn set_up_to(&mut self, universe_size: usize) { + for b in &mut self.bits { + *b = !0; + } + self.trim_to(universe_size); + } + + /// Clear all elements above `universe_size`. + fn trim_to(&mut self, universe_size: usize) { + let word_bits = mem::size_of::() * 8; + + // `trim_block` is the first block where some bits have + // to be cleared. + let trim_block = universe_size / word_bits; + + // all the blocks above it have to be completely cleared. + if trim_block < self.bits.len() { + for b in &mut self.bits[trim_block+1..] { + *b = 0; + } + + // at that block, the `universe_size % word_bits` lsbs + // should remain. + let remaining_bits = universe_size % word_bits; + let mask = (1< bool { self.bits.clear_bit(elem.index()) @@ -224,70 +256,6 @@ impl IdxSet { _pd: PhantomData, } } - - /// Calls `f` on each index value held in this set, up to the - /// bound `max_bits` on the size of universe of indexes. - pub fn each_bit(&self, max_bits: usize, f: F) where F: FnMut(T) { - each_bit(self, max_bits, f) - } - - /// Removes all elements from this set. - pub fn reset_to_empty(&mut self) { - for word in self.words_mut() { *word = 0; } - } - - pub fn elems(&self, universe_size: usize) -> Elems { - Elems { i: 0, set: self, universe_size: universe_size } - } -} - -pub struct Elems<'a, T: Idx> { i: usize, set: &'a IdxSet, universe_size: usize } - -impl<'a, T: Idx> Iterator for Elems<'a, T> { - type Item = T; - fn next(&mut self) -> Option { - if self.i >= self.universe_size { return None; } - let mut i = self.i; - loop { - if i >= self.universe_size { - self.i = i; // (mark iteration as complete.) - return None; - } - if self.set.contains(&T::new(i)) { - self.i = i + 1; // (next element to start at.) - return Some(T::new(i)); - } - i = i + 1; - } - } -} - -fn each_bit(words: &IdxSet, max_bits: usize, mut f: F) where F: FnMut(T) { - let usize_bits: usize = mem::size_of::() * 8; - - for (word_index, &word) in words.words().iter().enumerate() { - if word != 0 { - let base_index = word_index * usize_bits; - for offset in 0..usize_bits { - let bit = 1 << offset; - if (word & bit) != 0 { - // NB: we round up the total number of bits - // that we store in any given bit set so that - // it is an even multiple of usize::BITS. This - // means that there may be some stray bits at - // the end that do not correspond to any - // actual value; that's why we first check - // that we are in range of bits_per_block. - let bit_index = base_index + offset as usize; - if bit_index >= max_bits { - return; - } else { - f(Idx::new(bit_index)); - } - } - } - } - } } pub struct Iter<'a, T: Idx> { @@ -316,3 +284,43 @@ impl<'a, T: Idx> Iterator for Iter<'a, T> { } } } + +#[test] +fn test_trim_to() { + use std::cmp; + + for i in 0..256 { + let mut idx_buf: IdxSetBuf = IdxSetBuf::new_filled(128); + idx_buf.trim_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..cmp::min(i, 128)).collect(); + assert_eq!(elems, expected); + } +} + +#[test] +fn test_set_up_to() { + for i in 0..128 { + for mut idx_buf in + vec![IdxSetBuf::new_empty(128), IdxSetBuf::new_filled(128)] + .into_iter() + { + idx_buf.set_up_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } + } +} + +#[test] +fn test_new_filled() { + for i in 0..128 { + let mut idx_buf = IdxSetBuf::new_filled(i); + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } +} diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 11c2bd736876..1fb63afc72fa 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::range::RangeArgument; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range}; +use std::ops::{Index, IndexMut, Range, RangeBounds}; use std::fmt; use std::vec; use std::u32; @@ -330,7 +329,7 @@ macro_rules! newtype_index { ); } -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct IndexVec { pub raw: Vec, _marker: PhantomData @@ -448,13 +447,13 @@ impl IndexVec { } #[inline] - pub fn drain<'a, R: RangeArgument>( + pub fn drain<'a, R: RangeBounds>( &'a mut self, range: R) -> impl Iterator + 'a { self.raw.drain(range) } #[inline] - pub fn drain_enumerated<'a, R: RangeArgument>( + pub fn drain_enumerated<'a, R: RangeBounds>( &'a mut self, range: R) -> impl Iterator + 'a { self.raw.drain(range).enumerate().map(IntoIdx { _marker: PhantomData }) } @@ -503,6 +502,13 @@ impl IndexVec { (c1, c2) } } + + pub fn convert_index_type(self) -> IndexVec { + IndexVec { + raw: self.raw, + _marker: PhantomData, + } + } } impl IndexVec { diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 81246aea1b56..622fb423b51e 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -26,15 +26,14 @@ #![feature(unboxed_closures)] #![feature(fn_traits)] #![feature(unsize)] -#![feature(i128_type)] -#![feature(i128)] -#![feature(conservative_impl_trait)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] +#![cfg_attr(stage0, feature(i128_type, i128))] #![feature(specialization)] #![feature(optin_builtin_traits)] -#![feature(underscore_lifetimes)] +#![cfg_attr(stage0, feature(underscore_lifetimes))] #![feature(macro_vis_matcher)] #![feature(allow_internal_unstable)] -#![feature(universal_impl_trait)] +#![cfg_attr(stage0, feature(universal_impl_trait))] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] @@ -76,6 +75,14 @@ pub mod flock; pub mod sync; pub mod owning_ref; +pub struct OnDrop(pub F); + +impl Drop for OnDrop { + fn drop(&mut self) { + (self.0)(); + } +} + // See comments in src/librustc/lib.rs #[doc(hidden)] pub fn __noop_fix_for_27438() {} diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs index a72cc6b57ead..37512e4bcd57 100644 --- a/src/librustc_data_structures/obligation_forest/node_index.rs +++ b/src/librustc_data_structures/obligation_forest/node_index.rs @@ -8,18 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::nonzero::NonZero; +use std::num::NonZeroU32; use std::u32; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct NodeIndex { - index: NonZero, + index: NonZeroU32, } impl NodeIndex { pub fn new(value: usize) -> NodeIndex { assert!(value < (u32::MAX as usize)); - NodeIndex { index: NonZero::new((value as u32) + 1).unwrap() } + NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() } } pub fn get(self) -> usize { diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 70733bc6aeda..a8f689e5c81a 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -165,29 +165,6 @@ impl Hasher for StableHasher { } } - -/// Something that can provide a stable hashing context. -pub trait StableHashingContextProvider { - type ContextType; - fn create_stable_hashing_context(&self) -> Self::ContextType; -} - -impl<'a, T: StableHashingContextProvider> StableHashingContextProvider for &'a T { - type ContextType = T::ContextType; - - fn create_stable_hashing_context(&self) -> Self::ContextType { - (**self).create_stable_hashing_context() - } -} - -impl<'a, T: StableHashingContextProvider> StableHashingContextProvider for &'a mut T { - type ContextType = T::ContextType; - - fn create_stable_hashing_context(&self) -> Self::ContextType { - (**self).create_stable_hashing_context() - } -} - /// Something that implements `HashStable` can be hashed in a way that is /// stable across multiple compilation sessions. pub trait HashStable { diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index d7cd459e5771..184ef1369761 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -26,11 +26,6 @@ //! //! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false. //! -//! `rustc_global!` gives us a way to declare variables which are intended to be -//! global for the current rustc session. This currently maps to thread-locals, -//! since rustdoc uses the rustc libraries in multiple threads. -//! These globals should eventually be moved into the `Session` structure. -//! //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync //! depending on the value of cfg!(parallel_queries). @@ -228,31 +223,6 @@ pub fn assert_sync() {} pub fn assert_send_val(_t: &T) {} pub fn assert_send_sync_val(_t: &T) {} -#[macro_export] -#[allow_internal_unstable] -macro_rules! rustc_global { - // empty (base case for the recursion) - () => {}; - - // process multiple declarations - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( - thread_local!($(#[$attr])* $vis static $name: $t = $init); - rustc_global!($($rest)*); - ); - - // handle a single declaration - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( - thread_local!($(#[$attr])* $vis static $name: $t = $init); - ); -} - -#[macro_export] -macro_rules! rustc_access_global { - ($name:path, $callback:expr) => { - $name.with($callback) - } -} - impl Debug for LockCell { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.debug_struct("LockCell") @@ -363,6 +333,13 @@ impl Lock { } } +impl Default for Lock { + #[inline] + fn default() -> Self { + Lock::new(T::default()) + } +} + // FIXME: Probably a bad idea impl Clone for Lock { #[inline] diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 6a1d9e565342..3bff79ed3a6f 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -28,6 +28,7 @@ rustc_plugin = { path = "../librustc_plugin" } rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } rustc_save_analysis = { path = "../librustc_save_analysis" } +rustc_traits = { path = "../librustc_traits" } rustc_trans_utils = { path = "../librustc_trans_utils" } rustc_typeck = { path = "../librustc_typeck" } serialize = { path = "../libserialize" } diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md index 839d1831f954..fef249a9e4eb 100644 --- a/src/librustc_driver/README.md +++ b/src/librustc_driver/README.md @@ -1,7 +1,3 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - The `driver` crate is effectively the "main" function for the rust compiler. It orchestrates the compilation process and "knits together" the code from the other crates within rustc. This crate itself does @@ -9,4 +5,6 @@ not contain any of the "main logic" of the compiler (though it does have some code related to pretty printing or other minor compiler options). +For more information about how the driver works, see the [rustc guide]. +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f020f86b6860..c6ebc9926805 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -31,6 +31,7 @@ use rustc_incremental; use rustc_resolve::{MakeGlobMap, Resolver, ResolverArenas}; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::{self, CStore}; +use rustc_traits; use rustc_trans_utils::trans_crate::TransCrate; use rustc_typeck as typeck; use rustc_privacy; @@ -89,7 +90,7 @@ pub fn compile_input(trans: Box, } if sess.profile_queries() { - profile::begin(); + profile::begin(sess); } // We need nested scopes here, because the intermediate results can keep @@ -181,7 +182,7 @@ pub fn compile_input(trans: Box, let arenas = AllArenas::new(); // Construct the HIR map - let hir_map = time(sess.time_passes(), + let hir_map = time(sess, "indexing hir", || hir_map::map_crate(sess, cstore, &mut hir_forest, &defs)); @@ -517,10 +518,10 @@ pub fn phase_1_parse_input<'a>(control: &CompileController, sess.diagnostic().set_continue_after_error(control.continue_parse_after_error); if sess.profile_queries() { - profile::begin(); + profile::begin(sess); } - let krate = time(sess.time_passes(), "parsing", || { + let krate = time(sess, "parsing", || { match *input { Input::File(ref file) => { parse::parse_crate_from_file(file, &sess.parse_sess) @@ -645,11 +646,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, -> Result, CompileIncomplete> where F: FnOnce(&ast::Crate) -> CompileResult, { - let time_passes = sess.time_passes(); - let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test, - sess.opts.debugging_opts.epoch); + sess.opts.debugging_opts.edition); // these need to be set "early" so that expansion sees `quote` if enabled. sess.init_features(features); @@ -664,7 +663,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, ); if sess.opts.incremental.is_some() { - time(time_passes, "garbage collect incremental cache directory", || { + time(sess, "garbage collect incremental cache directory", || { if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) { warn!("Error while trying to garbage collect incremental \ compilation cache directory: {}", e); @@ -674,22 +673,22 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, // If necessary, compute the dependency graph (in the background). let future_dep_graph = if sess.opts.build_dep_graph() { - Some(rustc_incremental::load_dep_graph(sess, time_passes)) + Some(rustc_incremental::load_dep_graph(sess)) } else { None }; - time(time_passes, "recursion limit", || { + time(sess, "recursion limit", || { middle::recursion_limit::update_limits(sess, &krate); }); - krate = time(time_passes, "crate injection", || { - let alt_std_name = sess.opts.alt_std_name.clone(); + krate = time(sess, "crate injection", || { + let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s); syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name) }); let mut addl_plugins = Some(addl_plugins); - let registrars = time(time_passes, "plugin loading", || { + let registrars = time(sess, "plugin loading", || { plugin::load::load_plugins(sess, &cstore, &krate, @@ -699,7 +698,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, let mut registry = registry.unwrap_or(Registry::new(sess, krate.span)); - time(time_passes, "plugin registration", || { + time(sess, "plugin registration", || { if sess.features_untracked().rustc_diagnostic_macros { registry.register_macro("__diagnostic_used", diagnostics::plugin::expand_diagnostic_used); @@ -752,7 +751,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives; syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote); - krate = time(time_passes, "expansion", || { + krate = time(sess, "expansion", || { // Windows dlls do not have rpaths, so they don't know how to find their // dependencies. It's up to us to tell the system where to find all the // dependent dlls. Note that this uses cfg!(windows) as opposed to @@ -814,7 +813,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, krate }); - krate = time(time_passes, "maybe building test harness", || { + krate = time(sess, "maybe building test harness", || { syntax::test::modify_for_testing(&sess.parse_sess, &mut resolver, sess.opts.test, @@ -833,7 +832,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, // bunch of checks in the `modify` function below. For now just skip this // step entirely if we're rustdoc as it's not too useful anyway. if !sess.opts.actually_rustdoc { - krate = time(time_passes, "maybe creating a macro crate", || { + krate = time(sess, "maybe creating a macro crate", || { let crate_types = sess.crate_types.borrow(); let num_crate_types = crate_types.len(); let is_proc_macro_crate = crate_types.contains(&config::CrateTypeProcMacro); @@ -848,7 +847,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, }); } - krate = time(time_passes, "creating allocators", || { + krate = time(sess, "creating allocators", || { allocator::expand::modify(&sess.parse_sess, &mut resolver, krate, @@ -869,21 +868,17 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, println!("{}", json::as_json(&krate)); } - time(time_passes, + time(sess, "AST validation", || ast_validation::check_crate(sess, &krate)); - time(time_passes, "name resolution", || -> CompileResult { + time(sess, "name resolution", || -> CompileResult { resolver.resolve_crate(&krate); Ok(()) })?; - if resolver.found_unresolved_macro { - sess.parse_sess.span_diagnostic.abort_if_errors(); - } - // Needs to go *after* expansion to be able to check the results of macro expansion. - time(time_passes, "complete gated feature checking", || { + time(sess, "complete gated feature checking", || { sess.track_errors(|| { syntax::feature_gate::check_crate(&krate, &sess.parse_sess, @@ -893,20 +888,28 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, }) })?; + // Unresolved macros might be due to mistyped `#[macro_use]`, + // so abort after checking for unknown attributes. (#49074) + if resolver.found_unresolved_macro { + sess.parse_sess.span_diagnostic.abort_if_errors(); + } + // Lower ast -> hir. // First, we need to collect the dep_graph. let dep_graph = match future_dep_graph { None => DepGraph::new_disabled(), Some(future) => { - let prev_graph = time(time_passes, "blocked while dep-graph loading finishes", || { + let prev_graph = time(sess, "blocked while dep-graph loading finishes", || { future.open() - .expect("Could not join with background dep_graph thread") + .unwrap_or_else(|e| rustc_incremental::LoadResult::Error { + message: format!("could not decode incremental cache: {:?}", e) + }) .open(sess) }); DepGraph::new(prev_graph) } }; - let hir_forest = time(time_passes, "lowering ast -> hir", || { + let hir_forest = time(sess, "lowering ast -> hir", || { let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, &mut resolver); if sess.opts.debugging_opts.hir_stats { @@ -916,7 +919,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, hir_map::Forest::new(hir_crate, &dep_graph) }); - time(time_passes, + time(sess, "early lint checks", || lint::check_ast_crate(sess, &krate)); @@ -944,6 +947,7 @@ pub fn default_provide(providers: &mut ty::maps::Providers) { traits::provide(providers); reachable::provide(providers); rustc_passes::provide(providers); + rustc_traits::provide(providers); middle::region::provide(providers); cstore::provide(providers); lint::provide(providers); @@ -973,22 +977,20 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate, mpsc::Receiver>, CompileResult) -> R { - let time_passes = sess.time_passes(); - - let query_result_on_disk_cache = time(time_passes, + let query_result_on_disk_cache = time(sess, "load query result cache", || rustc_incremental::load_query_result_cache(sess)); - time(time_passes, + time(sess, "looking for entry point", - || middle::entry::find_entry_point(sess, &hir_map)); + || middle::entry::find_entry_point(sess, &hir_map, name)); - sess.plugin_registrar_fn.set(time(time_passes, "looking for plugin registrar", || { + sess.plugin_registrar_fn.set(time(sess, "looking for plugin registrar", || { plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map) })); sess.derive_registrar_fn.set(derive_registrar::find(&hir_map)); - time(time_passes, + time(sess, "loop checking", || loops::check_crate(sess, &hir_map)); @@ -1020,11 +1022,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate, // tcx available. rustc_incremental::dep_graph_tcx_init(tcx); - time(sess.time_passes(), "attribute checking", || { + time(sess, "attribute checking", || { hir::check_attr::check_crate(tcx) }); - time(time_passes, + time(sess, "stability checking", || stability::check_unstable_api_usage(tcx)); @@ -1037,18 +1039,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate, } } - time(time_passes, + time(sess, "rvalue promotion", || rvalue_promotion::check_crate(tcx)); analysis.access_levels = - time(time_passes, "privacy checking", || rustc_privacy::check_crate(tcx)); + time(sess, "privacy checking", || rustc_privacy::check_crate(tcx)); - time(time_passes, + time(sess, "intrinsic checking", || middle::intrinsicck::check_crate(tcx)); - time(time_passes, + time(sess, "match checking", || mir::matchck_crate(tcx)); @@ -1056,19 +1058,19 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate, // "not all control paths return a value" is reported here. // // maybe move the check to a MIR pass? - time(time_passes, + time(sess, "liveness checking", || middle::liveness::check_crate(tcx)); - time(time_passes, + time(sess, "borrow checking", || borrowck::check_crate(tcx)); - time(time_passes, + time(sess, "MIR borrow checking", || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id); }); - time(time_passes, + time(sess, "MIR effect checking", || for def_id in tcx.body_owners() { mir::transform::check_unsafety::check_unsafety(tcx, def_id) @@ -1083,13 +1085,17 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate, return Ok(f(tcx, analysis, rx, sess.compile_status())); } - time(time_passes, "death checking", || middle::dead::check_crate(tcx)); + time(sess, "death checking", || middle::dead::check_crate(tcx)); - time(time_passes, "unused lib feature checking", || { + time(sess, "unused lib feature checking", || { stability::check_unused_or_stable_features(tcx) }); - time(time_passes, "lint checking", || lint::check_crate(tcx)); + time(sess, "lint checking", || lint::check_crate(tcx)); + + time(sess, + "dumping chalk-like clauses", + || rustc_traits::lowering::dump_program_clauses(tcx)); return Ok(f(tcx, analysis, rx, tcx.sess.compile_status())); }) @@ -1101,18 +1107,16 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(trans: &TransCrate, tcx: TyCtxt<'a, 'tcx, 'tcx>, rx: mpsc::Receiver>) -> Box { - let time_passes = tcx.sess.time_passes(); - - time(time_passes, + time(tcx.sess, "resolving dependency formats", || ::rustc::middle::dependency_format::calculate(tcx)); let translation = - time(time_passes, "translation", move || { + time(tcx.sess, "translation", move || { trans.trans_crate(tcx, rx) }); if tcx.sess.profile_queries() { - profile::dump("profile_queries".to_string()) + profile::dump(&tcx.sess, "profile_queries".to_string()) } translation diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 8c0e89716cff..b461431c7bbb 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -24,6 +24,7 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(set_stdio)] +#![feature(rustc_stack_internals)] extern crate arena; extern crate getopts; @@ -46,6 +47,7 @@ extern crate rustc_metadata; extern crate rustc_mir; extern crate rustc_resolve; extern crate rustc_save_analysis; +extern crate rustc_traits; extern crate rustc_trans_utils; extern crate rustc_typeck; extern crate serialize; @@ -62,6 +64,7 @@ use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::OnDrop; use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::CompileIncomplete; use rustc::session::config::{Input, PrintRequest, ErrorOutputType}; @@ -443,9 +446,20 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box { // The FileLoader provides a way to load files from sources other than the file system. pub fn run_compiler<'a>(args: &[String], callbacks: &mut CompilerCalls<'a>, - file_loader: Option>, + file_loader: Option>, emitter_dest: Option>) -> (CompileResult, Option) +{ + syntax::with_globals(|| { + run_compiler_impl(args, callbacks, file_loader, emitter_dest) + }) +} + +fn run_compiler_impl<'a>(args: &[String], + callbacks: &mut CompilerCalls<'a>, + file_loader: Option>, + emitter_dest: Option>) + -> (CompileResult, Option) { macro_rules! do_or_return {($expr: expr, $sess: expr) => { match $expr { @@ -503,30 +517,35 @@ pub fn run_compiler<'a>(args: &[String], target_features::add_configuration(&mut cfg, &sess, &*trans); sess.parse_sess.config = cfg; - let plugins = sess.opts.debugging_opts.extra_plugins.clone(); + let result = { + let plugins = sess.opts.debugging_opts.extra_plugins.clone(); - let cstore = CStore::new(trans.metadata_loader()); + let cstore = CStore::new(trans.metadata_loader()); - do_or_return!(callbacks.late_callback(&*trans, - &matches, - &sess, - &cstore, - &input, - &odir, - &ofile), Some(sess)); + do_or_return!(callbacks.late_callback(&*trans, + &matches, + &sess, + &cstore, + &input, + &odir, + &ofile), Some(sess)); - let control = callbacks.build_controller(&sess, &matches); + let _sess_abort_error = OnDrop(|| sess.diagnostic().print_error_count()); - (driver::compile_input(trans, - &sess, - &cstore, - &input_file_path, - &input, - &odir, - &ofile, - Some(plugins), - &control), - Some(sess)) + let control = callbacks.build_controller(&sess, &matches); + + driver::compile_input(trans, + &sess, + &cstore, + &input_file_path, + &input, + &odir, + &ofile, + Some(plugins), + &control) + }; + + (result, Some(sess)) } // Extract output directory and file from matches. @@ -914,7 +933,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { pub fn enable_save_analysis(control: &mut CompileController) { control.keep_ast = true; control.after_analysis.callback = box |state| { - time(state.session.time_passes(), "save analysis", || { + time(state.session, "save analysis", || { save::process_crate(state.tcx.unwrap(), state.expanded_crate.unwrap(), state.analysis.unwrap(), @@ -1135,6 +1154,15 @@ fn usage(verbose: bool, include_unstable_options: bool) { verbose_help); } +fn print_wall_help() { + println!(" +The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by +default. Use `rustc -W help` to see all available lints. It's more common to put +warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using +the command line flag directly. +"); +} + fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) { println!(" Available lint options: @@ -1379,6 +1407,13 @@ pub fn handle_options(args: &[String]) -> Option { return None; } + // Handle the special case of -Wall. + let wall = matches.opt_strs("W"); + if wall.iter().any(|x| *x == "all") { + print_wall_help(); + return None; + } + // Don't handle -W help here, because we might first load plugins. let r = matches.opt_strs("Z"); if r.iter().any(|x| *x == "help") { @@ -1433,16 +1468,56 @@ pub fn in_rustc_thread(f: F) -> Result> // Temporarily have stack size set to 16MB to deal with nom-using crates failing const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB - let mut cfg = thread::Builder::new().name("rustc".to_string()); + #[cfg(unix)] + let spawn_thread = unsafe { + // Fetch the current resource limits + let mut rlim = libc::rlimit { + rlim_cur: 0, + rlim_max: 0, + }; + if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 { + let err = io::Error::last_os_error(); + error!("in_rustc_thread: error calling getrlimit: {}", err); + true + } else if rlim.rlim_max < STACK_SIZE as libc::rlim_t { + true + } else { + std::rt::deinit_stack_guard(); + rlim.rlim_cur = STACK_SIZE as libc::rlim_t; + if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 { + let err = io::Error::last_os_error(); + error!("in_rustc_thread: error calling setrlimit: {}", err); + std::rt::update_stack_guard(); + true + } else { + std::rt::update_stack_guard(); + false + } + } + }; - // FIXME: Hacks on hacks. If the env is trying to override the stack size - // then *don't* set it explicitly. - if env::var_os("RUST_MIN_STACK").is_none() { - cfg = cfg.stack_size(STACK_SIZE); + // We set the stack size at link time. See src/rustc/rustc.rs. + #[cfg(windows)] + let spawn_thread = false; + + #[cfg(not(any(windows,unix)))] + let spawn_thread = true; + + // The or condition is added from backward compatibility. + if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() { + let mut cfg = thread::Builder::new().name("rustc".to_string()); + + // FIXME: Hacks on hacks. If the env is trying to override the stack size + // then *don't* set it explicitly. + if env::var_os("RUST_MIN_STACK").is_none() { + cfg = cfg.stack_size(STACK_SIZE); + } + + let thread = cfg.spawn(f); + thread.unwrap().join() + } else { + Ok(f()) } - - let thread = cfg.spawn(f); - thread.unwrap().join() } /// Get a list of extra command-line flags provided by the user, as strings. @@ -1456,6 +1531,12 @@ fn extra_compiler_flags() -> Option<(Vec, bool)> { args.push(arg.to_string_lossy().to_string()); } + // Avoid printing help because of empty args. This can suggest the compiler + // itself is not the program root (consider RLS). + if args.len() < 2 { + return None; + } + let matches = if let Some(matches) = handle_options(&args) { matches } else { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 4ae6a93d6983..c5e7fdb30d36 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -584,6 +584,13 @@ impl<'a, 'hir> Iterator for NodesMatchingUII<'a, 'hir> { &mut NodesMatchingSuffix(ref mut iter) => iter.next(), } } + + fn size_hint(&self) -> (usize, Option) { + match self { + &NodesMatchingDirect(ref iter) => iter.size_hint(), + &NodesMatchingSuffix(ref iter) => iter.size_hint(), + } + } } impl UserIdentifiedItem { diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs index 061077d05a43..a362556717bd 100644 --- a/src/librustc_driver/profile/mod.rs +++ b/src/librustc_driver/profile/mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::session::Session; use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan}; use std::sync::mpsc::{Receiver}; use std::io::{Write}; @@ -17,11 +18,11 @@ use std::time::{Duration, Instant}; pub mod trace; /// begin a profile thread, if not already running -pub fn begin() { +pub fn begin(sess: &Session) { use std::thread; use std::sync::mpsc::{channel}; let (tx, rx) = channel(); - if profq_set_chan(tx) { + if profq_set_chan(sess, tx) { thread::spawn(move||profile_queries_thread(rx)); } } @@ -30,7 +31,7 @@ pub fn begin() { /// wait for this dump to complete. /// /// wraps the RPC (send/recv channel logic) of requesting a dump. -pub fn dump(path:String) { +pub fn dump(sess: &Session, path: String) { use std::sync::mpsc::{channel}; let (tx, rx) = channel(); let params = ProfQDumpParams{ @@ -39,7 +40,7 @@ pub fn dump(path:String) { // is written; false for now dump_profq_msg_log:true, }; - profq_msg(ProfileQueriesMsg::Dump(params)); + profq_msg(sess, ProfileQueriesMsg::Dump(params)); let _ = rx.recv().unwrap(); } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index becdbb54e5be..9efd8844977f 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -18,7 +18,7 @@ use rustc_lint; use rustc_resolve::MakeGlobMap; use rustc::middle::region; use rustc::ty::subst::Subst; -use rustc::traits::{ObligationCause, Reveal}; +use rustc::traits::ObligationCause; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::maps::OnDiskCache; use rustc::infer::{self, InferOk, InferResult}; @@ -29,6 +29,7 @@ use rustc::hir::map as hir_map; use rustc::session::{self, config}; use rustc::session::config::{OutputFilenames, OutputTypes}; use rustc_data_structures::sync::Lrc; +use syntax; use syntax::ast; use syntax::abi::Abi; use syntax::codemap::{CodeMap, FilePathMapping, FileName}; @@ -93,9 +94,19 @@ fn errors(msgs: &[&str]) -> (Box, usize) { } fn test_env(source_string: &str, - (emitter, expected_err_count): (Box, usize), + args: (Box, usize), body: F) where F: FnOnce(Env) +{ + syntax::with_globals(|| { + test_env_impl(source_string, args, body) + }); +} + +fn test_env_impl(source_string: &str, + (emitter, expected_err_count): (Box, usize), + body: F) + where F: FnOnce(Env) { let mut options = config::basic_options(); options.debugging_opts.verbose = true; @@ -153,7 +164,7 @@ fn test_env(source_string: &str, |tcx| { tcx.infer_ctxt().enter(|infcx| { let mut region_scope_tree = region::ScopeTree::default(); - let param_env = ty::ParamEnv::empty(Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); body(Env { infcx: &infcx, region_scope_tree: &mut region_scope_tree, @@ -287,7 +298,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.tcx.intern_tup(&[ty1, ty2], false) + self.infcx.tcx.intern_tup(&[ty1, ty2]) } pub fn t_param(&self, index: u32) -> Ty<'tcx> { @@ -444,8 +455,7 @@ fn sub_free_bound_false_infer() { //! does NOT hold for any instantiation of `_#1`. test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { - let t_infer1 = env.infcx.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(DUMMY_SP)); + let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP)); let t_rptr_bound1 = env.t_rptr_late_bound(1); env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.isize), env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); @@ -593,8 +603,8 @@ fn walk_ty() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let usize_ty = tcx.types.usize; - let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty], false); - let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty], false); + let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty]); + let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty]); let walked: Vec<_> = tup2_ty.walk().collect(); assert_eq!(walked, [tup2_ty, tup1_ty, int_ty, usize_ty, int_ty, usize_ty, tup1_ty, int_ty, @@ -608,8 +618,8 @@ fn walk_ty_skip_subtree() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let usize_ty = tcx.types.usize; - let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty], false); - let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty], false); + let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty]); + let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty]); // types we expect to see (in order), plus a boolean saying // whether to skip the subtree. diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 2536fc648c70..945ecce7ab3e 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -92,7 +92,8 @@ impl<'a> DiagnosticBuilder<'a> { Level::Bug | Level::Fatal | Level::PhaseFatal | - Level::Error => { + Level::Error | + Level::FailureNote => { true } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index f481b36daa34..ca5d3f55a0fe 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -12,7 +12,7 @@ use self::Destination::*; use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan}; -use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper, DiagnosticId}; +use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapperDyn, DiagnosticId}; use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; use styled_buffer::StyledBuffer; @@ -21,7 +21,7 @@ use atty; use std::borrow::Cow; use std::io::prelude::*; use std::io; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::cmp::min; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter}; use termcolor::{WriteColor, Color, Buffer}; @@ -33,6 +33,11 @@ const ANONYMIZED_LINE_NUM: &str = "LL"; pub trait Emitter { /// Emit a structured diagnostic. fn emit(&mut self, db: &DiagnosticBuilder); + + /// Check if should show explanations about "rustc --explain" + fn should_show_explain(&self) -> bool { + true + } } impl Emitter for EmitterWriter { @@ -80,6 +85,10 @@ impl Emitter for EmitterWriter { &children, &suggestions); } + + fn should_show_explain(&self) -> bool { + !self.short_message + } } /// maximum number of lines we will print for each error; arbitrary. @@ -111,10 +120,9 @@ impl ColorConfig { pub struct EmitterWriter { dst: Destination, - cm: Option>, + cm: Option>, short_message: bool, teach: bool, - error_codes: HashSet, ui_testing: bool, } @@ -124,37 +132,9 @@ struct FileWithAnnotatedLines { multiline_depth: usize, } -impl Drop for EmitterWriter { - fn drop(&mut self) { - if !self.short_message && !self.error_codes.is_empty() { - let mut error_codes = self.error_codes.clone().into_iter().collect::>(); - let mut dst = self.dst.writable(); - error_codes.sort(); - if error_codes.len() > 1 { - let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() }; - writeln!(dst, - "You've got a few errors: {}{}", - error_codes[..limit].join(", "), - if error_codes.len() > 9 { "..." } else { "" } - ).expect("failed to give tips..."); - writeln!(dst, - "If you want more information on an error, try using \ - \"rustc --explain {}\"", - &error_codes[0]).expect("failed to give tips..."); - } else { - writeln!(dst, - "If you want more information on this error, try using \ - \"rustc --explain {}\"", - &error_codes[0]).expect("failed to give tips..."); - } - dst.flush().expect("failed to emit errors"); - } - } -} - impl EmitterWriter { pub fn stderr(color_config: ColorConfig, - code_map: Option>, + code_map: Option>, short_message: bool, teach: bool) -> EmitterWriter { @@ -164,13 +144,12 @@ impl EmitterWriter { cm: code_map, short_message, teach, - error_codes: HashSet::new(), ui_testing: false, } } pub fn new(dst: Box, - code_map: Option>, + code_map: Option>, short_message: bool, teach: bool) -> EmitterWriter { @@ -179,7 +158,6 @@ impl EmitterWriter { cm: code_map, short_message, teach, - error_codes: HashSet::new(), ui_testing: false, } } @@ -993,18 +971,26 @@ impl EmitterWriter { buffer.prepend(0, " ", Style::NoStyle); } draw_note_separator(&mut buffer, 0, max_line_num_len + 1); - buffer.append(0, &level.to_string(), Style::HeaderMsg); - buffer.append(0, ": ", Style::NoStyle); + let level_str = level.to_string(); + if !level_str.is_empty() { + buffer.append(0, &level_str, Style::HeaderMsg); + buffer.append(0, ": ", Style::NoStyle); + } self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None); } else { - buffer.append(0, &level.to_string(), Style::Level(level.clone())); + let level_str = level.to_string(); + if !level_str.is_empty() { + buffer.append(0, &level_str, Style::Level(level.clone())); + } // only render error codes, not lint codes if let Some(DiagnosticId::Error(ref code)) = *code { buffer.append(0, "[", Style::Level(level.clone())); buffer.append(0, &code, Style::Level(level.clone())); buffer.append(0, "]", Style::Level(level.clone())); } - buffer.append(0, ": ", Style::HeaderMsg); + if !level_str.is_empty() { + buffer.append(0, ": ", Style::HeaderMsg); + } for &(ref text, _) in msg.iter() { buffer.append(0, text, Style::HeaderMsg); } @@ -1020,14 +1006,12 @@ impl EmitterWriter { if primary_span != &&DUMMY_SP { (cm.lookup_char_pos(primary_span.lo()), cm) } else { - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message, - &mut self.error_codes)?; + emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; return Ok(()); } } else { // If we don't have span information, emit and exit - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message, - &mut self.error_codes)?; + emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; return Ok(()); }; if let Ok(pos) = @@ -1200,8 +1184,7 @@ impl EmitterWriter { } // final step: take our styled buffer, render it, then output it - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message, - &mut self.error_codes)?; + emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; Ok(()) @@ -1212,14 +1195,15 @@ impl EmitterWriter { level: &Level, max_line_num_len: usize) -> io::Result<()> { - use std::borrow::Borrow; - if let Some(ref cm) = self.cm { let mut buffer = StyledBuffer::new(); // Render the suggestion message - buffer.append(0, &level.to_string(), Style::Level(level.clone())); - buffer.append(0, ": ", Style::HeaderMsg); + let level_str = level.to_string(); + if !level_str.is_empty() { + buffer.append(0, &level_str, Style::Level(level.clone())); + buffer.append(0, ": ", Style::HeaderMsg); + } self.msg_to_buffer(&mut buffer, &[(suggestion.msg.to_owned(), Style::NoStyle)], max_line_num_len, @@ -1227,7 +1211,7 @@ impl EmitterWriter { Some(Style::HeaderMsg)); // Render the replacements for each suggestion - let suggestions = suggestion.splice_lines(cm.borrow()); + let suggestions = suggestion.splice_lines(&**cm); let mut row_num = 2; for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) { @@ -1289,8 +1273,7 @@ impl EmitterWriter { let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS); buffer.puts(row_num, 0, &msg, Style::NoStyle); } - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message, - &mut self.error_codes)?; + emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; } Ok(()) } @@ -1321,7 +1304,7 @@ impl EmitterWriter { draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1); } match emit_to_destination(&buffer.render(), level, &mut self.dst, - self.short_message, &mut self.error_codes) { + self.short_message) { Ok(()) => (), Err(e) => panic!("failed to emit error: {}", e) } @@ -1416,8 +1399,7 @@ fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool { fn emit_to_destination(rendered_buffer: &Vec>, lvl: &Level, dst: &mut Destination, - short_message: bool, - error_codes: &mut HashSet) + short_message: bool) -> io::Result<()> { use lock; @@ -1436,16 +1418,13 @@ fn emit_to_destination(rendered_buffer: &Vec>, // same buffering approach. Instead, we use a global Windows mutex, which we acquire long // enough to output the full error message, then we release. let _buffer_lock = lock::acquire_global_lock("rustc_errors"); - for line in rendered_buffer { + for (pos, line) in rendered_buffer.iter().enumerate() { for part in line { dst.apply_style(lvl.clone(), part.style)?; write!(dst, "{}", part.text)?; - if !short_message && part.text.len() == 12 && part.text.starts_with("error[E") { - error_codes.insert(part.text[6..11].to_owned()); - } dst.reset()?; } - if !short_message { + if !short_message && (!lvl.is_failure_note() || pos != rendered_buffer.len() - 1) { write!(dst, "\n")?; } } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 924ed71ef0d6..37ae64cef572 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -17,8 +17,8 @@ #![allow(unused_attributes)] #![feature(range_contains)] #![cfg_attr(unix, feature(libc))] -#![feature(conservative_impl_trait)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] +#![cfg_attr(stage0, feature(i128_type))] #![feature(optin_builtin_traits)] extern crate atty; @@ -36,7 +36,7 @@ use self::Level::*; use emitter::{Emitter, EmitterWriter}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::StableHasher; @@ -106,6 +106,8 @@ pub struct SubstitutionPart { pub snippet: String, } +pub type CodeMapperDyn = CodeMapper + sync::Send + sync::Sync; + pub trait CodeMapper { fn lookup_char_pos(&self, pos: BytePos) -> Loc; fn span_to_lines(&self, sp: Span) -> FileLinesResult; @@ -119,7 +121,8 @@ pub trait CodeMapper { impl CodeSuggestion { /// Returns the assembled code suggestions and whether they should be shown with an underline. - pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, Vec)> { + pub fn splice_lines(&self, cm: &CodeMapperDyn) + -> Vec<(String, Vec)> { use syntax_pos::{CharPos, Loc, Pos}; fn push_trailing(buf: &mut String, @@ -290,7 +293,7 @@ impl Handler { pub fn with_tty_emitter(color_config: ColorConfig, can_emit_warnings: bool, treat_err_as_bug: bool, - cm: Option>) + cm: Option>) -> Handler { Handler::with_tty_emitter_and_flags( color_config, @@ -303,7 +306,7 @@ impl Handler { } pub fn with_tty_emitter_and_flags(color_config: ColorConfig, - cm: Option>, + cm: Option>, flags: HandlerFlags) -> Handler { let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false)); @@ -509,12 +512,14 @@ impl Handler { pub fn span_unimpl>(&self, sp: S, msg: &str) -> ! { self.span_bug(sp, &format!("unimplemented {}", msg)); } + pub fn failure(&self, msg: &str) { + DiagnosticBuilder::new(self, FailureNote, msg).emit() + } pub fn fatal(&self, msg: &str) -> FatalError { if self.flags.treat_err_as_bug { self.bug(msg); } - let mut db = DiagnosticBuilder::new(self, Fatal, msg); - db.emit(); + DiagnosticBuilder::new(self, Fatal, msg).emit(); FatalError } pub fn err(&self, msg: &str) { @@ -553,22 +558,55 @@ impl Handler { pub fn has_errors(&self) -> bool { self.err_count() > 0 } - pub fn abort_if_errors(&self) { - let s; - match self.err_count() { - 0 => { - if let Some(bug) = self.delayed_span_bug.borrow_mut().take() { - DiagnosticBuilder::new_diagnostic(self, bug).emit(); + + pub fn print_error_count(&self) { + let s = match self.err_count() { + 0 => return, + 1 => "aborting due to previous error".to_string(), + _ => format!("aborting due to {} previous errors", self.err_count()) + }; + + let _ = self.fatal(&s); + + let can_show_explain = self.emitter.borrow().should_show_explain(); + let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty(); + if can_show_explain && are_there_diagnostics { + let mut error_codes = + self.tracked_diagnostic_codes.borrow() + .clone() + .into_iter() + .filter_map(|x| match x { + DiagnosticId::Error(ref s) => Some(s.clone()), + _ => None, + }) + .collect::>(); + if !error_codes.is_empty() { + error_codes.sort(); + if error_codes.len() > 1 { + let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() }; + self.failure(&format!("Some errors occurred: {}{}", + error_codes[..limit].join(", "), + if error_codes.len() > 9 { "..." } else { "." })); + self.failure(&format!("For more information about an error, try \ + `rustc --explain {}`.", + &error_codes[0])); + } else { + self.failure(&format!("For more information about this error, try \ + `rustc --explain {}`.", + &error_codes[0])); } - return; - } - 1 => s = "aborting due to previous error".to_string(), - _ => { - s = format!("aborting due to {} previous errors", self.err_count()); } } + } - self.fatal(&s).raise(); + pub fn abort_if_errors(&self) { + if self.err_count() == 0 { + if let Some(bug) = self.delayed_span_bug.borrow_mut().take() { + DiagnosticBuilder::new_diagnostic(self, bug).emit(); + } + return; + } + FatalError.raise(); } pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) { if lvl == Warning && !self.flags.can_emit_warnings { @@ -654,6 +692,7 @@ pub enum Level { Note, Help, Cancelled, + FailureNote, } impl fmt::Display for Level { @@ -682,9 +721,10 @@ impl Level { spec.set_fg(Some(Color::Cyan)) .set_intense(true); } + FailureNote => {} Cancelled => unreachable!(), } - return spec + spec } pub fn to_str(self) -> &'static str { @@ -694,7 +734,15 @@ impl Level { Warning => "warning", Note => "note", Help => "help", + FailureNote => "", Cancelled => panic!("Shouldn't call on cancelled error"), } } + + pub fn is_failure_note(&self) -> bool { + match *self { + FailureNote => true, + _ => false, + } + } } diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml index eabc3ab03b19..dd05679589e7 100644 --- a/src/librustc_incremental/Cargo.toml +++ b/src/librustc_incremental/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } log = "0.4" -rand = "0.3" +rand = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } serialize = { path = "../libserialize" } diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 65fbd9d0bf8f..cad72ff778b5 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -15,10 +15,10 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] -#![feature(conservative_impl_trait)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] #![feature(fs_read_write)] -#![feature(i128_type)] -#![feature(inclusive_range_syntax)] +#![cfg_attr(stage0, feature(i128_type))] +#![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(specialization)] extern crate graphviz; @@ -39,6 +39,7 @@ pub use assert_dep_graph::assert_dep_graph; pub use persist::dep_graph_tcx_init; pub use persist::load_dep_graph; pub use persist::load_query_result_cache; +pub use persist::LoadResult; pub use persist::save_dep_graph; pub use persist::save_trans_partition; pub use persist::save_work_products; diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 0e6d328d947b..44d6e532f79b 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -14,7 +14,7 @@ use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph}; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc::ty::maps::OnDiskCache; -use rustc::util::common::time; +use rustc::util::common::time_ext; use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::opaque::Decoder; use std::path::Path; @@ -89,7 +89,8 @@ impl LoadResult { pub fn open(self, sess: &Session) -> PreviousDepGraph { match self { LoadResult::Error { message } => { - sess.fatal(&message) /* never returns */ + sess.warn(&message); + PreviousDepGraph::new(SerializedDepGraph::new()) }, LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { @@ -147,12 +148,14 @@ impl MaybeAsync { } /// Launch a thread and load the dependency graph in the background. -pub fn load_dep_graph(sess: &Session, time_passes: bool) -> +pub fn load_dep_graph(sess: &Session) -> MaybeAsync> { // Since `sess` isn't `Sync`, we perform all accesses to `sess` // before we fire the background thread. + let time_passes = sess.time_passes(); + if sess.opts.incremental.is_none() { // No incremental compilation. return MaybeAsync::Sync(LoadResult::Ok { @@ -167,7 +170,7 @@ pub fn load_dep_graph(sess: &Session, time_passes: bool) -> let expected_hash = sess.opts.dep_tracking_hash(); MaybeAsync::Async(std::thread::spawn(move || { - time(time_passes, "background load prev dep-graph", move || { + time_ext(time_passes, None, "background load prev dep-graph", move || { match load_data(report_incremental_info, &path) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::Error { message } => LoadResult::Error { message }, diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs index 2f864aaefba8..755a550b5bca 100644 --- a/src/librustc_incremental/persist/mod.rs +++ b/src/librustc_incremental/persist/mod.rs @@ -27,6 +27,7 @@ pub use self::fs::prepare_session_directory; pub use self::load::dep_graph_tcx_init; pub use self::load::load_dep_graph; pub use self::load::load_query_result_cache; +pub use self::load::LoadResult; pub use self::save::save_dep_graph; pub use self::save::save_work_products; pub use self::work_product::save_trans_partition; diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index d44d1d6f2602..a5bc1106ba0b 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -33,14 +33,14 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { return; } - time(sess.time_passes(), "persist query result cache", || { + time(sess, "persist query result cache", || { save_in(sess, query_cache_path(sess), |e| encode_query_cache(tcx, e)); }); if tcx.sess.opts.debugging_opts.incremental_queries { - time(sess.time_passes(), "persist dep-graph", || { + time(sess, "persist dep-graph", || { save_in(sess, dep_graph_path(sess), |e| encode_dep_graph(tcx, e)); @@ -162,7 +162,7 @@ fn encode_dep_graph(tcx: TyCtxt, let mut counts: FxHashMap<_, Stat> = FxHashMap(); - for (i, &(node, _)) in serialized_graph.nodes.iter_enumerated() { + for (i, &node) in serialized_graph.nodes.iter_enumerated() { let stat = counts.entry(node.kind).or_insert(Stat { kind: node.kind, node_counter: 0, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c6698cbd0068..c0728cb2b666 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -33,7 +33,7 @@ use rustc::hir::def_id::DefId; use rustc::cfg; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; -use rustc::traits::{self, Reveal}; +use rustc::traits; use rustc::hir::map as hir_map; use util::nodemap::NodeSet; use lint::{LateContext, LintContext, LintArray}; @@ -46,6 +46,7 @@ use syntax::attr; use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; +use syntax::errors::DiagnosticBuilder; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::FnKind; @@ -525,7 +526,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { if def.has_dtor(cx.tcx) { return; } - let param_env = ty::ParamEnv::empty(Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); if !ty.moves_by_default(cx.tcx, param_env, item.span) { return; } @@ -1082,7 +1083,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { if !cx.access_levels.is_reachable(it.id) { let msg = "function is marked #[no_mangle], but not exported"; let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg); - let insertion_span = it.span.with_hi(it.span.lo()); + let insertion_span = it.span.shrink_to_lo(); if it.vis == hir::Visibility::Inherited { err.span_suggestion(insertion_span, "try making it public", @@ -1107,7 +1108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { !cx.access_levels.is_reachable(it.id) { let msg = "static is marked #[no_mangle], but not exported"; let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg); - let insertion_span = it.span.with_hi(it.span.lo()); + let insertion_span = it.span.shrink_to_lo(); if it.vis == hir::Visibility::Inherited { err.span_suggestion(insertion_span, "try making it public", @@ -1316,48 +1317,115 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub { } } -/// Lint for trait and lifetime bounds that are (accidentally) accepted by the parser, but -/// ignored later. +/// Lint for trait and lifetime bounds in type aliases being mostly ignored: +/// They are relevant when using associated types, but otherwise neither checked +/// at definition site nor enforced at use site. -pub struct IgnoredGenericBounds; +pub struct TypeAliasBounds; declare_lint! { - IGNORED_GENERIC_BOUNDS, + TYPE_ALIAS_BOUNDS, Warn, - "these generic bounds are ignored" + "bounds in type aliases are not enforced" } -impl LintPass for IgnoredGenericBounds { +impl LintPass for TypeAliasBounds { fn get_lints(&self) -> LintArray { - lint_array!(IGNORED_GENERIC_BOUNDS) + lint_array!(TYPE_ALIAS_BOUNDS) } } -impl EarlyLintPass for IgnoredGenericBounds { - fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) { - let type_alias_generics = match item.node { - ast::ItemKind::Ty(_, ref generics) => generics, +impl TypeAliasBounds { + fn is_type_variable_assoc(qpath: &hir::QPath) -> bool { + match *qpath { + hir::QPath::TypeRelative(ref ty, _) => { + // If this is a type variable, we found a `T::Assoc`. + match ty.node { + hir::TyPath(hir::QPath::Resolved(None, ref path)) => { + match path.def { + Def::TyParam(_) => true, + _ => false + } + } + _ => false + } + } + hir::QPath::Resolved(..) => false, + } + } + + fn suggest_changing_assoc_types(ty: &hir::Ty, err: &mut DiagnosticBuilder) { + // Access to associates types should use `::Assoc`, which does not need a + // bound. Let's see if this type does that. + + // We use a HIR visitor to walk the type. + use rustc::hir::intravisit::{self, Visitor}; + use syntax::ast::NodeId; + struct WalkAssocTypes<'a, 'db> where 'db: 'a { + err: &'a mut DiagnosticBuilder<'db> + } + impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> { + fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> + { + intravisit::NestedVisitorMap::None + } + + fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) { + if TypeAliasBounds::is_type_variable_assoc(qpath) { + self.err.span_help(span, + "use fully disambiguated paths (i.e., `::Assoc`) to refer to \ + associated types in type aliases"); + } + intravisit::walk_qpath(self, qpath, id, span) + } + } + + // Let's go for a walk! + let mut visitor = WalkAssocTypes { err }; + visitor.visit_ty(ty); + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { + let (ty, type_alias_generics) = match item.node { + hir::ItemTy(ref ty, ref generics) => (&*ty, generics), _ => return, }; + let mut suggested_changing_assoc_types = false; // There must not be a where clause if !type_alias_generics.where_clause.predicates.is_empty() { let spans : Vec<_> = type_alias_generics.where_clause.predicates.iter() .map(|pred| pred.span()).collect(); - cx.span_lint(IGNORED_GENERIC_BOUNDS, spans, - "where clauses are ignored in type aliases"); + let mut err = cx.struct_span_lint(TYPE_ALIAS_BOUNDS, spans, + "where clauses are not enforced in type aliases"); + err.help("the clause will not be checked when the type alias is used, \ + and should be removed"); + if !suggested_changing_assoc_types { + TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + suggested_changing_assoc_types = true; + } + err.emit(); } // The parameters must not have bounds for param in type_alias_generics.params.iter() { let spans : Vec<_> = match param { - &ast::GenericParam::Lifetime(ref l) => l.bounds.iter().map(|b| b.span).collect(), - &ast::GenericParam::Type(ref ty) => ty.bounds.iter().map(|b| b.span()).collect(), + &hir::GenericParam::Lifetime(ref l) => l.bounds.iter().map(|b| b.span).collect(), + &hir::GenericParam::Type(ref ty) => ty.bounds.iter().map(|b| b.span()).collect(), }; if !spans.is_empty() { - cx.span_lint( - IGNORED_GENERIC_BOUNDS, + let mut err = cx.struct_span_lint( + TYPE_ALIAS_BOUNDS, spans, - "bounds on generic parameters are ignored in type aliases", + "bounds on generic parameters are not enforced in type aliases", ); + err.help("the bound will not be checked when the type alias is used, \ + and should be removed"); + if !suggested_changing_assoc_types { + TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); + suggested_changing_assoc_types = true; + } + err.emit(); } } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 779aa3a9037c..d024adad9d03 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -27,11 +27,11 @@ #![cfg_attr(test, feature(test))] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(macro_vis_matcher)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] -#![feature(slice_patterns)] +#![cfg_attr(stage0, feature(never_type))] #[macro_use] extern crate syntax; @@ -48,7 +48,7 @@ use rustc::session; use rustc::util; use session::Session; -use syntax::epoch::Epoch; +use syntax::edition::Edition; use lint::LintId; use lint::FutureIncompatibleInfo; @@ -109,7 +109,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UnusedImportBraces, AnonymousParameters, UnusedDocComment, - IgnoredGenericBounds, ); add_early_builtin_with_new!(sess, @@ -139,6 +138,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { MutableTransmutes, UnionsWithDropFields, UnreachablePub, + TypeAliasBounds, ); add_builtin_with_new!(sess, @@ -197,93 +197,90 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { FutureIncompatibleInfo { id: LintId::of(PRIVATE_IN_PUBLIC), reference: "issue #34537 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), reference: "issue #34537 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY), reference: "issue #35203 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(SAFE_EXTERN_STATICS), reference: "issue #36247 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(INVALID_TYPE_PARAM_DEFAULT), reference: "issue #36887 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP), reference: "issue #37872 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(LEGACY_IMPORTS), reference: "issue #38260 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), reference: "issue #39207 ", - epoch: None, - }, - FutureIncompatibleInfo { - id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT), - reference: "issue #39216 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(MISSING_FRAGMENT_SPECIFIER), reference: "issue #40107 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN), reference: "issue #41620 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(ANONYMOUS_PARAMETERS), reference: "issue #41686 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES), reference: "issue #42238 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS), reference: "issue #42868 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(SAFE_PACKED_BORROWS), reference: "issue #46043 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS), reference: "issue #46205 ", - epoch: None, - }, - FutureIncompatibleInfo { - id: LintId::of(COERCE_NEVER), - reference: "issue #46325 ", - epoch: None, + edition: None, }, FutureIncompatibleInfo { id: LintId::of(TYVAR_BEHIND_RAW_POINTER), reference: "issue #46906 ", - epoch: Some(Epoch::Epoch2018), - } + edition: Some(Edition::Edition2018), + }, + FutureIncompatibleInfo { + id: LintId::of(UNSTABLE_NAME_COLLISION), + reference: "issue #48919 ", + edition: None, + // Note: this item represents future incompatibility of all unstable functions in the + // standard library, and thus should never be removed or changed to an error. + }, ]); // Register renamed and removed lints @@ -315,4 +312,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { "converted into hard error, see https://github.com/rust-lang/rust/issues/36892"); store.register_removed("extra_requirement_in_impl", "converted into hard error, see https://github.com/rust-lang/rust/issues/37166"); + store.register_removed("coerce_never", + "converted into hard error, see https://github.com/rust-lang/rust/issues/48950"); + store.register_removed("resolve_trait_on_defaulted_unit", + "converted into hard error, see https://github.com/rust-lang/rust/issues/48950"); } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 266f322e3977..445fe0cc4019 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -12,7 +12,7 @@ use rustc::hir::map as hir_map; use rustc::ty::subst::Substs; -use rustc::ty::{self, AdtKind, Ty, TyCtxt}; +use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, LayoutOf}; use util::nodemap::FxHashSet; use lint::{LateContext, LintContext, LintArray}; @@ -509,8 +509,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // make sure the fields are actually safe. let mut all_phantom = true; for field in &def.non_enum_variant().fields { - let field_ty = cx.fully_normalize_associated_types_in( - &field.ty(cx, substs) + let field_ty = cx.normalize_erasing_regions( + ParamEnv::reveal_all(), + field.ty(cx, substs), ); // repr(transparent) types are allowed to have arbitrary ZSTs, not just // PhantomData -- skip checking all ZST fields @@ -556,8 +557,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let mut all_phantom = true; for field in &def.non_enum_variant().fields { - let field_ty = cx.fully_normalize_associated_types_in( - &field.ty(cx, substs) + let field_ty = cx.normalize_erasing_regions( + ParamEnv::reveal_all(), + field.ty(cx, substs), ); let r = self.check_type_for_ffi(cache, field_ty); match r { @@ -596,8 +598,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check the contained variants. for variant in &def.variants { for field in &variant.fields { - let arg = cx.fully_normalize_associated_types_in( - &field.ty(cx, substs) + let arg = cx.normalize_erasing_regions( + ParamEnv::reveal_all(), + field.ty(cx, substs), ); let r = self.check_type_for_ffi(cache, arg); match r { @@ -716,7 +719,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { // it is only OK to use this function because extern fns cannot have // any generic types right now: - let ty = self.cx.tcx.fully_normalize_associated_types_in(&ty); + let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); match self.check_type_for_ffi(&mut FxHashSet(), ty) { FfiResult::FfiSafe => {} diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 6ab3172c4fef..aa93b3098e04 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let t = cx.tables.expr_ty(&expr); let ty_warned = match t.sty { - ty::TyTuple(ref tys, _) if tys.is_empty() => return, + ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyNever => return, ty::TyAdt(def, _) => { if def.variants.is_empty() { @@ -301,7 +301,6 @@ impl EarlyLintPass for UnusedParens { Ret(Some(ref value)) => (value, "`return` value", false), Assign(_, ref value) => (value, "assigned value", false), AssignOp(.., ref value) => (value, "assigned value", false), - InPlace(_, ref value) => (value, "emplacement value", false), // either function/method call, or something this lint doesn't care about ref call_or_other => { let args_to_check; @@ -377,11 +376,12 @@ impl UnusedImportBraces { // Trigger the lint if the nested item is a non-self single item let node_ident; match items[0].0.kind { - ast::UseTreeKind::Simple(ident) => { - if ident.name == keywords::SelfValue.name() { + ast::UseTreeKind::Simple(rename) => { + let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier; + if orig_ident.name == keywords::SelfValue.name() { return; } else { - node_ident = ident; + node_ident = rename.unwrap_or(orig_ident); } } ast::UseTreeKind::Glob => { diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index c5cdf6566921..e73c570ed823 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -121,6 +121,7 @@ impl InlineAsmDiagnostic { pub enum Diagnostic { Optimization(OptimizationDiagnostic), InlineAsm(InlineAsmDiagnostic), + PGO(DiagnosticInfoRef), /// LLVM has other types that we do not wrap here. UnknownDiagnostic(DiagnosticInfoRef), @@ -160,6 +161,10 @@ impl Diagnostic { Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)) } + Dk::PGOProfile => { + PGO(di) + } + _ => UnknownDiagnostic(di), } } diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 0ec5700f5f32..dba2e918f6f3 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -322,6 +322,7 @@ pub enum DiagnosticKind { OptimizationRemarkAnalysisAliasing, OptimizationRemarkOther, OptimizationFailure, + PGOProfile, } /// LLVMRustArchiveKind @@ -621,6 +622,7 @@ extern "C" { pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong; pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool, high: *mut u64, low: *mut u64) -> bool; + pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64; // Operations on composite constants @@ -934,6 +936,11 @@ extern "C" { RHS: ValueRef, Name: *const c_char) -> ValueRef; + pub fn LLVMBuildExactUDiv(B: BuilderRef, + LHS: ValueRef, + RHS: ValueRef, + Name: *const c_char) + -> ValueRef; pub fn LLVMBuildSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef, @@ -1201,6 +1208,49 @@ extern "C" { Name: *const c_char) -> ValueRef; + pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef, + Acc: ValueRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef, + Acc: ValueRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef, + Src: ValueRef, + IsSigned: bool) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef, + Src: ValueRef, + IsSigned: bool) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef, + Src: ValueRef, + IsNaN: bool) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef, + Src: ValueRef, + IsNaN: bool) + -> ValueRef; + + pub fn LLVMRustBuildMinNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef; + pub fn LLVMRustBuildMaxNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef; + pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildPtrDiff(B: BuilderRef, @@ -1567,6 +1617,7 @@ extern "C" { pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef); pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; + pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef; pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; @@ -1599,7 +1650,9 @@ extern "C" { OptLevel: CodeGenOptLevel, MergeFunctions: bool, SLPVectorize: bool, - LoopVectorize: bool); + LoopVectorize: bool, + PGOGenPath: *const c_char, + PGOUsePath: *const c_char); pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef, DisableSimplifyLibCalls: bool); @@ -1694,6 +1747,7 @@ extern "C" { pub fn LLVMRustModuleCost(M: ModuleRef) -> u64; pub fn LLVMRustThinLTOAvailable() -> bool; + pub fn LLVMRustPGOAvailable() -> bool; pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef, M: ModuleRef, BC: *const c_char) -> bool; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 789ecd0f6136..86f495c5fac3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,9 +12,8 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use locator::{self, CratePaths}; -use native_libs::relevant_lib; use schema::CrateRoot; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX}; use rustc::hir::svh::Svh; @@ -23,6 +22,7 @@ use rustc::middle::cstore::DepKind; use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_back::PanicStrategy; +use rustc_back::target::TargetTriple; use rustc::session::search_paths::PathKind; use rustc::middle; use rustc::middle::cstore::{validate_crate_name, ExternCrate}; @@ -30,7 +30,6 @@ use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; -use std::cell::{RefCell, Cell}; use std::ops::Deref; use std::path::PathBuf; use std::{cmp, fs}; @@ -63,7 +62,7 @@ fn dump_crates(cstore: &CStore) { info!(" name: {}", data.name()); info!(" cnum: {}", data.cnum); info!(" hash: {}", data.hash()); - info!(" reqd: {:?}", data.dep_kind.get()); + info!(" reqd: {:?}", *data.dep_kind.lock()); let CrateSource { dylib, rlib, rmeta } = data.source.clone(); dylib.map(|dl| info!(" dylib: {}", dl.0.display())); rlib.map(|rl| info!(" rlib: {}", rl.0.display())); @@ -231,9 +230,9 @@ impl<'a> CrateLoader<'a> { .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) .collect(); - let mut cmeta = cstore::CrateMetadata { + let cmeta = cstore::CrateMetadata { name, - extern_crate: Cell::new(None), + extern_crate: Lock::new(None), def_path_table: Lrc::new(def_path_table), trait_impls, proc_macros: crate_root.macro_derive_registrar.map(|_| { @@ -241,35 +240,18 @@ impl<'a> CrateLoader<'a> { }), root: crate_root, blob: metadata, - cnum_map: RefCell::new(cnum_map), + cnum_map: Lock::new(cnum_map), cnum, - codemap_import_info: RefCell::new(vec![]), - attribute_cache: RefCell::new([Vec::new(), Vec::new()]), - dep_kind: Cell::new(dep_kind), + codemap_import_info: RwLock::new(vec![]), + attribute_cache: Lock::new([Vec::new(), Vec::new()]), + dep_kind: Lock::new(dep_kind), source: cstore::CrateSource { dylib, rlib, rmeta, }, - // Initialize this with an empty set. The field is populated below - // after we were able to deserialize its contents. - dllimport_foreign_items: FxHashSet(), }; - let dllimports: FxHashSet<_> = cmeta - .root - .native_libraries - .decode((&cmeta, self.sess)) - .filter(|lib| relevant_lib(self.sess, lib) && - lib.kind == cstore::NativeLibraryKind::NativeUnknown) - .flat_map(|lib| { - assert!(lib.foreign_items.iter().all(|def_id| def_id.krate == cnum)); - lib.foreign_items.into_iter().map(|def_id| def_id.index) - }) - .collect(); - - cmeta.dllimport_foreign_items = dllimports; - let cmeta = Lrc::new(cmeta); self.cstore.set_crate_data(cnum, cmeta.clone()); (cnum, cmeta) @@ -280,6 +262,7 @@ impl<'a> CrateLoader<'a> { ident: Symbol, name: Symbol, hash: Option<&Svh>, + extra_filename: Option<&str>, span: Span, path_kind: PathKind, mut dep_kind: DepKind) @@ -295,6 +278,7 @@ impl<'a> CrateLoader<'a> { ident, crate_name: name, hash: hash.map(|a| &*a), + extra_filename: extra_filename, filesearch: self.sess.target_filesearch(path_kind), target: &self.sess.target.target, triple: &self.sess.opts.target_triple, @@ -314,7 +298,7 @@ impl<'a> CrateLoader<'a> { let mut proc_macro_locator = locator::Context { target: &self.sess.host, - triple: config::host_triple(), + triple: &TargetTriple::from_triple(config::host_triple()), filesearch: self.sess.host_filesearch(path_kind), rejected_via_hash: vec![], rejected_via_triple: vec![], @@ -335,7 +319,9 @@ impl<'a> CrateLoader<'a> { if data.root.macro_derive_registrar.is_some() { dep_kind = DepKind::UnexportedMacrosOnly; } - data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind)); + data.dep_kind.with_lock(|data_dep_kind| { + *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); + }); (cnum, data) } LoadResult::Loaded(library) => { @@ -356,7 +342,7 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - if locate_ctxt.triple == self.sess.opts.target_triple { + if locate_ctxt.triple == &self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.name() == root.name && root.hash == data.hash() { @@ -379,14 +365,14 @@ impl<'a> CrateLoader<'a> { if !visited.insert((cnum, extern_crate.direct)) { return } let cmeta = self.cstore.get_crate_data(cnum); - let old_extern_crate = cmeta.extern_crate.get(); + let mut old_extern_crate = cmeta.extern_crate.borrow_mut(); // Prefer: // - something over nothing (tuple.0); // - direct extern crate to indirect (tuple.1); // - shorter paths to longer (tuple.2). let new_rank = (true, extern_crate.direct, !extern_crate.path_len); - let old_rank = match old_extern_crate { + let old_rank = match *old_extern_crate { None => (false, false, !0), Some(ref c) => (true, c.direct, !c.path_len), }; @@ -395,7 +381,9 @@ impl<'a> CrateLoader<'a> { return; // no change needed } - cmeta.extern_crate.set(Some(extern_crate)); + *old_extern_crate = Some(extern_crate); + drop(old_extern_crate); + // Propagate the extern crate info to dependencies. extern_crate.direct = false; for &dep_cnum in cmeta.cnum_map.borrow().iter() { @@ -423,7 +411,8 @@ impl<'a> CrateLoader<'a> { ::std::iter::once(krate).chain(crate_root.crate_deps .decode(metadata) .map(|dep| { - debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); + info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash, + dep.extra_filename); if dep.kind == DepKind::UnexportedMacrosOnly { return krate; } @@ -432,7 +421,8 @@ impl<'a> CrateLoader<'a> { _ => dep.kind, }; let (local_cnum, ..) = self.resolve_crate( - root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind, + root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, + PathKind::Dependency, dep_kind, ); local_cnum })).collect() @@ -441,8 +431,9 @@ impl<'a> CrateLoader<'a> { fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol) -> ExtensionCrate { info!("read extension crate `extern crate {} as {}`", orig_name, rename); - let target_triple = &self.sess.opts.target_triple[..]; - let is_cross = target_triple != config::host_triple(); + let target_triple = &self.sess.opts.target_triple; + let host_triple = TargetTriple::from_triple(config::host_triple()); + let is_cross = target_triple != &host_triple; let mut target_only = false; let mut locate_ctxt = locator::Context { sess: self.sess, @@ -450,9 +441,10 @@ impl<'a> CrateLoader<'a> { ident: orig_name, crate_name: rename, hash: None, + extra_filename: None, filesearch: self.sess.host_filesearch(PathKind::Crate), target: &self.sess.host, - triple: config::host_triple(), + triple: &host_triple, root: &None, rejected_via_hash: vec![], rejected_via_triple: vec![], @@ -646,7 +638,7 @@ impl<'a> CrateLoader<'a> { // #![panic_runtime] crate. self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime(sess)); - runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit; + runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit; } }); @@ -677,7 +669,7 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (cnum, data) = - self.resolve_crate(&None, name, name, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -784,7 +776,7 @@ impl<'a> CrateLoader<'a> { let symbol = Symbol::intern(name); let dep_kind = DepKind::Explicit; let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime @@ -799,13 +791,15 @@ impl<'a> CrateLoader<'a> { } fn inject_profiler_runtime(&mut self) { - if self.sess.opts.debugging_opts.profile { + if self.sess.opts.debugging_opts.profile || + self.sess.opts.debugging_opts.pgo_gen.is_some() + { info!("loading profiler"); let symbol = Symbol::intern("profiler_builtins"); let dep_kind = DepKind::Implicit; let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -920,6 +914,7 @@ impl<'a> CrateLoader<'a> { name, name, None, + None, DUMMY_SP, PathKind::Crate, DepKind::Implicit); @@ -1052,12 +1047,14 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) { match item.node { - ast::ItemKind::ExternCrate(rename) => { - debug!("resolving extern crate stmt. ident: {} rename: {:?}", item.ident, rename); - let rename = match rename { - Some(rename) => { - validate_crate_name(Some(self.sess), &rename.as_str(), Some(item.span)); - rename + ast::ItemKind::ExternCrate(orig_name) => { + debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", + item.ident, orig_name); + let orig_name = match orig_name { + Some(orig_name) => { + validate_crate_name(Some(self.sess), &orig_name.as_str(), + Some(item.span)); + orig_name } None => item.ident.name, }; @@ -1068,7 +1065,8 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { }; let (cnum, ..) = self.resolve_crate( - &None, item.ident.name, rename, None, item.span, PathKind::Crate, dep_kind, + &None, item.ident.name, orig_name, None, None, + item.span, PathKind::Crate, dep_kind, ); let def_id = definitions.opt_local_def_id(item.id).unwrap(); @@ -1083,6 +1081,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum { - self.resolve_crate(&None, name, name, None, span, PathKind::Crate, DepKind::Explicit).0 + self.resolve_crate(&None, name, name, None, None, span, PathKind::Crate, + DepKind::Explicit).0 } } diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 202efb9276a8..8765d9d8c2be 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -20,10 +20,9 @@ use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; use rustc::session::{Session, CrateDisambiguator}; use rustc_back::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; -use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap}; +use rustc::util::nodemap::{FxHashMap, NodeMap}; -use std::cell::{RefCell, Cell}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use syntax::{ast, attr}; use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; @@ -31,7 +30,7 @@ use syntax_pos; pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference}; pub use rustc::middle::cstore::NativeLibraryKind::*; -pub use rustc::middle::cstore::{CrateSource, LibSource}; +pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule}; pub use cstore_impl::{provide, provide_extern}; @@ -62,13 +61,13 @@ pub struct CrateMetadata { /// Information about the extern crate that caused this crate to /// be loaded. If this is `None`, then the crate was injected /// (e.g., by the allocator) - pub extern_crate: Cell>, + pub extern_crate: Lock>, pub blob: MetadataBlob, - pub cnum_map: RefCell, + pub cnum_map: Lock, pub cnum: CrateNum, - pub codemap_import_info: RefCell>, - pub attribute_cache: RefCell<[Vec>>; 2]>, + pub codemap_import_info: RwLock>, + pub attribute_cache: Lock<[Vec>>; 2]>, pub root: schema::CrateRoot, @@ -81,30 +80,30 @@ pub struct CrateMetadata { pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq>, - pub dep_kind: Cell, + pub dep_kind: Lock, pub source: CrateSource, pub proc_macros: Option)>>, - // Foreign items imported from a dylib (Windows only) - pub dllimport_foreign_items: FxHashSet, } pub struct CStore { - metas: RefCell>>>, + metas: RwLock>>>, /// Map from NodeId's of local extern crate statements to crate numbers - extern_mod_crate_map: RefCell>, - pub metadata_loader: Box, + extern_mod_crate_map: Lock>, + pub metadata_loader: Box, } impl CStore { - pub fn new(metadata_loader: Box) -> CStore { + pub fn new(metadata_loader: Box) -> CStore { CStore { - metas: RefCell::new(IndexVec::new()), - extern_mod_crate_map: RefCell::new(FxHashMap()), + metas: RwLock::new(IndexVec::new()), + extern_mod_crate_map: Lock::new(FxHashMap()), metadata_loader, } } + /// You cannot use this function to allocate a CrateNum in a thread-safe manner. + /// It is currently only used in CrateLoader which is single-threaded code. pub fn next_crate_num(&self) -> CrateNum { CrateNum::new(self.metas.borrow().len() + 1) } @@ -227,16 +226,6 @@ impl CrateMetadata { attr::contains_name(&attrs, "no_builtins") } - pub fn has_copy_closures(&self, sess: &Session) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess); - attr::contains_feature_attr(&attrs, "copy_closures") - } - - pub fn has_clone_closures(&self, sess: &Session) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess); - attr::contains_feature_attr(&attrs, "clone_closures") - } - pub fn panic_strategy(&self) -> PanicStrategy { self.root.panic_strategy.clone() } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 0b50f5c44962..f63edf07fa8b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -12,6 +12,7 @@ use cstore; use encoder; use link_args; use native_libs; +use foreign_modules; use schema; use rustc::ty::maps::QueryConfig; @@ -175,7 +176,10 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) } is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) } panic_strategy => { cdata.panic_strategy() } - extern_crate => { Lrc::new(cdata.extern_crate.get()) } + extern_crate => { + let r = Lrc::new(*cdata.extern_crate.lock()); + r + } is_no_builtins => { cdata.is_no_builtins(tcx.sess) } impl_defaultness => { cdata.get_impl_defaultness(def_id.index) } reachable_non_generics => { @@ -194,6 +198,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, Lrc::new(reachable_non_generics) } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } + foreign_modules => { Lrc::new(cdata.get_foreign_modules(tcx.sess)) } plugin_registrar_fn => { cdata.root.plugin_registrar_fn.map(|index| { DefId { krate: def_id.krate, index } @@ -208,6 +213,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, crate_hash => { cdata.hash() } original_crate_name => { cdata.name() } + extra_filename => { cdata.root.extra_filename.clone() } + + implementations_of_trait => { let mut result = vec![]; let filter = Some(other); @@ -221,11 +229,11 @@ provide! { <'tcx> tcx, def_id, other, cdata, Lrc::new(result) } - is_dllimport_foreign_item => { - cdata.is_dllimport_foreign_item(def_id.index) - } visibility => { cdata.get_visibility(def_id.index) } - dep_kind => { cdata.dep_kind.get() } + dep_kind => { + let r = *cdata.dep_kind.lock(); + r + } crate_name => { cdata.name } item_children => { let mut result = vec![]; @@ -241,17 +249,15 @@ provide! { <'tcx> tcx, def_id, other, cdata, } missing_extern_crate_item => { - match cdata.extern_crate.get() { + let r = match *cdata.extern_crate.borrow() { Some(extern_crate) if !extern_crate.direct => true, _ => false, - } + }; + r } used_crate_source => { Lrc::new(cdata.source.clone()) } - has_copy_closures => { cdata.has_copy_closures(tcx.sess) } - has_clone_closures => { cdata.has_clone_closures(tcx.sess) } - exported_symbols => { let cnum = cdata.cnum; assert!(cnum != LOCAL_CRATE); @@ -264,6 +270,8 @@ provide! { <'tcx> tcx, def_id, other, cdata, Arc::new(cdata.exported_symbols()) } + + wasm_custom_sections => { Lrc::new(cdata.wasm_custom_sections()) } } pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { @@ -297,13 +305,28 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { tcx.native_libraries(id.krate) .iter() .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib)) - .find(|l| l.foreign_items.contains(&id)) + .find(|lib| { + let fm_id = match lib.foreign_module { + Some(id) => id, + None => return false, + }; + tcx.foreign_modules(id.krate) + .iter() + .find(|m| m.def_id == fm_id) + .expect("failed to find foreign module") + .foreign_items + .contains(&id) + }) .map(|l| l.kind) }, native_libraries: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(native_libs::collect(tcx)) }, + foreign_modules: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Lrc::new(foreign_modules::collect(tcx)) + }, link_args: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(link_args::collect(tcx)) @@ -419,13 +442,16 @@ impl CrateStore for cstore::CStore { fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { - self.get_crate_data(cnum).dep_kind.get() + let data = self.get_crate_data(cnum); + let r = *data.dep_kind.lock(); + r } fn export_macros_untracked(&self, cnum: CrateNum) { let data = self.get_crate_data(cnum); - if data.dep_kind.get() == DepKind::UnexportedMacrosOnly { - data.dep_kind.set(DepKind::MacrosOnly) + let mut dep_kind = data.dep_kind.lock(); + if *dep_kind == DepKind::UnexportedMacrosOnly { + *dep_kind = DepKind::MacrosOnly; } } @@ -523,7 +549,7 @@ impl CrateStore for cstore::CStore { tokens: body.into(), legacy: def.legacy, }), - vis: codemap::respan(local_span.empty(), ast::VisibilityKind::Inherited), + vis: codemap::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, }) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f44703b9335e..e938d5c1a97f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -10,11 +10,12 @@ // Decoding metadata from a single crate's metadata -use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; +use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use schema::*; -use rustc_data_structures::sync::Lrc; -use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; +use rustc_data_structures::sync::{Lrc, ReadGuard}; +use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, + DisambiguatedDefPathData}; use rustc::hir; use rustc::middle::cstore::{LinkagePreference, ExternConstBody, ExternBodyNestedBodies}; @@ -29,9 +30,9 @@ use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; use rustc::mir::Mir; +use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; -use std::cell::Ref; use std::collections::BTreeMap; use std::io; use std::mem; @@ -58,6 +59,9 @@ pub struct DecodeContext<'a, 'tcx: 'a> { // interpreter allocation cache interpret_alloc_cache: FxHashMap, + // a cache for sizes of interpreter allocations + // needed to skip already deserialized allocations + interpret_alloc_size: FxHashMap, } /// Abstract over the various ways one can create metadata decoders. @@ -77,6 +81,7 @@ pub trait Metadata<'a, 'tcx>: Copy { last_filemap_index: 0, lazy_state: LazyState::NoNode, interpret_alloc_cache: FxHashMap::default(), + interpret_alloc_size: FxHashMap::default(), } } } @@ -143,7 +148,10 @@ impl<'a, 'tcx: 'a, T: Decodable> Lazy { } impl<'a, 'tcx: 'a, T: Decodable> LazySeq { - pub fn decode>(self, meta: M) -> impl Iterator + 'a { + pub fn decode>( + self, + meta: M, + ) -> impl Iterator + Captures<'tcx> + 'a { let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.len).map(move |_| T::decode(&mut dcx).unwrap()) @@ -282,46 +290,34 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { - const MAX1: usize = usize::max_value() - 1; - let tcx = self.tcx.unwrap(); + let tcx = self.tcx.expect("need tcx for AllocId decoding"); let pos = self.position(); - match usize::decode(self)? { - ::std::usize::MAX => { - let alloc_id = tcx.interpret_interner.reserve(); - trace!("creating alloc id {:?} at {}", alloc_id, pos); - // insert early to allow recursive allocs - self.interpret_alloc_cache.insert(pos, alloc_id); - - let allocation = interpret::Allocation::decode(self)?; - trace!("decoded alloc {:?} {:#?}", alloc_id, allocation); - let allocation = self.tcx.unwrap().intern_const_alloc(allocation); - tcx.interpret_interner.intern_at_reserved(alloc_id, allocation); - - if let Some(glob) = Option::::decode(self)? { - tcx.interpret_interner.cache(glob, alloc_id); - } - - Ok(alloc_id) - }, - MAX1 => { - trace!("creating fn alloc id at {}", pos); - let instance = ty::Instance::decode(self)?; - trace!("decoded fn alloc instance: {:?}", instance); - let id = tcx.interpret_interner.create_fn_alloc(instance); - trace!("created fn alloc id: {:?}", id); - self.interpret_alloc_cache.insert(pos, id); - Ok(id) - }, - shorthand => { - trace!("loading shorthand {}", shorthand); - if let Some(&alloc_id) = self.interpret_alloc_cache.get(&shorthand) { - return Ok(alloc_id); - } - trace!("shorthand {} not cached, loading entire allocation", shorthand); - // need to load allocation - self.with_position(shorthand, |this| interpret::AllocId::decode(this)) - }, + if let Some(cached) = self.interpret_alloc_cache.get(&pos).cloned() { + // if there's no end position we are currently deserializing a recursive + // allocation + if let Some(end) = self.interpret_alloc_size.get(&pos).cloned() { + trace!("{} already cached as {:?}", pos, cached); + // skip ahead + self.opaque.set_position(end); + return Ok(cached) + } } + let id = interpret::specialized_decode_alloc_id( + self, + tcx, + pos, + |this, pos, alloc_id| { this.interpret_alloc_cache.insert(pos, alloc_id); }, + |this, shorthand| { + // need to load allocation + this.with_position(shorthand, |this| interpret::AllocId::decode(this)) + } + )?; + let end_pos = self.position(); + assert!(self + .interpret_alloc_size + .insert(pos, end_pos) + .is_none()); + Ok(id) } } @@ -714,7 +710,7 @@ impl<'a, 'tcx> CrateMetadata { }; // Iterate over all children. - let macros_only = self.dep_kind.get().macros_only(); + let macros_only = self.dep_kind.lock().macros_only(); for child_index in item.children.decode((self, sess)) { if macros_only { continue @@ -950,6 +946,8 @@ impl<'a, 'tcx> CrateMetadata { if vec_.len() < node_index + 1 { vec_.resize(node_index + 1, None); } + // This can overwrite the result produced by another thread, but the value + // written should be the same vec_[node_index] = Some(result.clone()); result } @@ -1034,6 +1032,10 @@ impl<'a, 'tcx> CrateMetadata { self.root.native_libraries.decode((self, sess)).collect() } + pub fn get_foreign_modules(&self, sess: &Session) -> Vec { + self.root.foreign_modules.decode((self, sess)).collect() + } + pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { self.root .dylib_dependency_formats @@ -1070,6 +1072,16 @@ impl<'a, 'tcx> CrateMetadata { .collect() } + pub fn wasm_custom_sections(&self) -> Vec { + let sections = self.root + .wasm_custom_sections + .decode(self) + .map(|def_index| self.local_def_id(def_index)) + .collect::>(); + info!("loaded wasm sections {:?}", sections); + return sections + } + pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) { let entry = self.entry(id); match entry.kind { @@ -1096,10 +1108,6 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn is_dllimport_foreign_item(&self, id: DefIndex) -> bool { - self.dllimport_foreign_items.contains(&id) - } - pub fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -1118,7 +1126,23 @@ impl<'a, 'tcx> CrateMetadata { #[inline] pub fn def_key(&self, index: DefIndex) -> DefKey { - self.def_path_table.def_key(index) + if !self.is_proc_macro(index) { + self.def_path_table.def_key(index) + } else { + // FIXME(#49271) - It would be better if the DefIds were consistent + // with the DefPathTable, but for proc-macro crates + // they aren't. + let name = self.proc_macros + .as_ref() + .unwrap()[index.to_proc_macro_index()].0; + DefKey { + parent: Some(CRATE_DEF_INDEX), + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::MacroDef(name.as_str()), + disambiguator: 0, + } + } + } } // Returns the path leading to the thing with this `id`. @@ -1156,7 +1180,7 @@ impl<'a, 'tcx> CrateMetadata { /// for items inlined from other crates. pub fn imported_filemaps(&'a self, local_codemap: &codemap::CodeMap) - -> Ref<'a, Vec> { + -> ReadGuard<'a, Vec> { { let filemaps = self.codemap_import_info.borrow(); if !filemaps.is_empty() { @@ -1164,6 +1188,14 @@ impl<'a, 'tcx> CrateMetadata { } } + // Lock the codemap_import_info to ensure this only happens once + let mut codemap_import_info = self.codemap_import_info.borrow_mut(); + + if !codemap_import_info.is_empty() { + drop(codemap_import_info); + return self.codemap_import_info.borrow(); + } + let external_codemap = self.root.codemap.decode(self); let imported_filemaps = external_codemap.map(|filemap_to_import| { @@ -1222,8 +1254,10 @@ impl<'a, 'tcx> CrateMetadata { } }).collect(); + *codemap_import_info = imported_filemaps; + drop(codemap_import_info); + // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. - *self.codemap_import_info.borrow_mut() = imported_filemaps; self.codemap_import_info.borrow() } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d95948241748..0da6fc5b9eda 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -14,7 +14,7 @@ use isolated_encoder::IsolatedEncoder; use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, - EncodedMetadata}; + EncodedMetadata, ForeignModule}; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; use rustc::hir::map::definitions::DefPathTable; @@ -196,30 +196,26 @@ impl<'a, 'tcx> SpecializedEncoder> for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { - trace!("encoding {:?} at {}", alloc_id, self.position()); - if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() { - trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand); - return shorthand.encode(self); - } - let start = self.position(); - // cache the allocation shorthand now, because the allocation itself might recursively - // point to itself. - self.interpret_alloc_shorthands.insert(*alloc_id, start); - if let Some(alloc) = self.tcx.interpret_interner.get_alloc(*alloc_id) { - trace!("encoding {:?} with {:#?}", alloc_id, alloc); - usize::max_value().encode(self)?; - alloc.encode(self)?; - self.tcx.interpret_interner - .get_corresponding_static_def_id(*alloc_id) - .encode(self)?; - } else if let Some(fn_instance) = self.tcx.interpret_interner.get_fn(*alloc_id) { - trace!("encoding {:?} with {:#?}", alloc_id, fn_instance); - (usize::max_value() - 1).encode(self)?; - fn_instance.encode(self)?; - } else { - bug!("alloc id without corresponding allocation: {}", alloc_id); - } - Ok(()) + use std::collections::hash_map::Entry; + let tcx = self.tcx; + let pos = self.position(); + let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) { + Entry::Occupied(entry) => Some(entry.get().clone()), + Entry::Vacant(entry) => { + // ensure that we don't place any AllocIds at the very beginning + // of the metadata file, because that would end up making our indices + // not special. This is essentially impossible, but let's make sure + assert!(pos >= interpret::SHORTHAND_START); + entry.insert(pos); + None + }, + }; + interpret::specialized_encode_alloc_id( + self, + tcx, + *alloc_id, + shorthand, + ) } } @@ -416,6 +412,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ()); let native_lib_bytes = self.position() - i; + let foreign_modules = self.tracked( + IsolatedEncoder::encode_foreign_modules, + ()); + // Encode codemap i = self.position(); let codemap = self.encode_codemap(); @@ -439,6 +439,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { &exported_symbols); let exported_symbols_bytes = self.position() - i; + // encode wasm custom sections + let wasm_custom_sections = self.tcx.wasm_custom_sections(LOCAL_CRATE); + let wasm_custom_sections = self.tracked( + IsolatedEncoder::encode_wasm_custom_sections, + &wasm_custom_sections); + // Encode and index the items. i = self.position(); let items = self.encode_info_for_items(); @@ -456,6 +462,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let has_global_allocator = tcx.sess.has_global_allocator.get(); let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), + extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, disambiguator: tcx.sess.local_crate_disambiguator(), @@ -478,10 +485,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { lang_items, lang_items_missing, native_libraries, + foreign_modules, codemap, def_path_table, impls, exported_symbols, + wasm_custom_sections, index, }); @@ -1334,6 +1343,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.lazy_seq(used_libraries.iter().cloned()) } + fn encode_foreign_modules(&mut self, _: ()) -> LazySeq { + let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); + self.lazy_seq(foreign_modules.iter().cloned()) + } + fn encode_crate_deps(&mut self, _: ()) -> LazySeq { let crates = self.tcx.crates(); @@ -1344,6 +1358,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { name: self.tcx.original_crate_name(cnum), hash: self.tcx.crate_hash(cnum), kind: self.tcx.dep_kind(cnum), + extra_filename: self.tcx.extra_filename(cnum), }; (cnum, dep) }) @@ -1448,6 +1463,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { .cloned()) } + fn encode_wasm_custom_sections(&mut self, statics: &[DefId]) -> LazySeq { + info!("encoding custom wasm section constants {:?}", statics); + self.lazy_seq(statics.iter().map(|id| id.index)) + } + fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs new file mode 100644 index 000000000000..c44d891b7f39 --- /dev/null +++ b/src/librustc_metadata/foreign_modules.rs @@ -0,0 +1,48 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir; +use rustc::middle::cstore::ForeignModule; +use rustc::ty::TyCtxt; + +pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { + let mut collector = Collector { + tcx, + modules: Vec::new(), + }; + tcx.hir.krate().visit_all_item_likes(&mut collector); + return collector.modules +} + +struct Collector<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + modules: Vec, +} + +impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { + fn visit_item(&mut self, it: &'tcx hir::Item) { + let fm = match it.node { + hir::ItemForeignMod(ref fm) => fm, + _ => return, + }; + + let foreign_items = fm.items.iter() + .map(|it| self.tcx.hir.local_def_id(it.id)) + .collect(); + self.modules.push(ForeignModule { + foreign_items, + def_id: self.tcx.hir.local_def_id(it.id), + }); + } + + fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {} + fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {} +} diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index da0da622d521..4af5ec9ae08e 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -14,11 +14,13 @@ #![deny(warnings)] #![feature(box_patterns)] -#![feature(conservative_impl_trait)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] #![feature(fs_read_write)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(libc)] +#![feature(macro_lifetime_matcher)] #![feature(proc_macro_internals)] +#![feature(macro_lifetime_matcher)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(specialization)] @@ -54,6 +56,7 @@ mod isolated_encoder; mod schema; mod native_libs; mod link_args; +mod foreign_modules; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index c56674bd6c5a..f553c55ae56f 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -83,7 +83,10 @@ //! 1. Does the filename match an rlib/dylib pattern? That is to say, does the //! filename have the right prefix/suffix? //! 2. Does the filename have the right prefix for the crate name being queried? -//! This is filtering for files like `libfoo*.rlib` and such. +//! This is filtering for files like `libfoo*.rlib` and such. If the crate +//! we're looking for was originally compiled with -C extra-filename, the +//! extra filename will be included in this prefix to reduce reading +//! metadata from crates that would otherwise share our prefix. //! 3. Is the file an actual rust library? This is done by loading the metadata //! from the library and making sure it's actually there. //! 4. Does the name in the metadata agree with the name of the library? @@ -233,9 +236,10 @@ use rustc::util::nodemap::FxHashMap; use errors::DiagnosticBuilder; use syntax::symbol::Symbol; use syntax_pos::Span; -use rustc_back::target::Target; +use rustc_back::target::{Target, TargetTriple}; use std::cmp; +use std::collections::HashSet; use std::fmt; use std::fs; use std::io::{self, Read}; @@ -256,9 +260,10 @@ pub struct Context<'a> { pub ident: Symbol, pub crate_name: Symbol, pub hash: Option<&'a Svh>, + pub extra_filename: Option<&'a str>, // points to either self.sess.target.target or self.sess.host, must match triple pub target: &'a Target, - pub triple: &'a str, + pub triple: &'a TargetTriple, pub filesearch: FileSearch<'a>, pub root: &'a Option, pub rejected_via_hash: Vec, @@ -303,7 +308,12 @@ impl CratePaths { impl<'a> Context<'a> { pub fn maybe_load_library_crate(&mut self) -> Option { - self.find_library_crate() + let mut seen_paths = HashSet::new(); + match self.extra_filename { + Some(s) => self.find_library_crate(s, &mut seen_paths) + .or_else(|| self.find_library_crate("", &mut seen_paths)), + None => self.find_library_crate("", &mut seen_paths) + } } pub fn report_errs(&mut self) -> ! { @@ -394,7 +404,7 @@ impl<'a> Context<'a> { add); if (self.ident == "std" || self.ident == "core") - && self.triple != config::host_triple() { + && self.triple != &TargetTriple::from_triple(config::host_triple()) { err.note(&format!("the `{}` target may not be installed", self.triple)); } err.span_label(self.span, "can't find crate"); @@ -419,7 +429,10 @@ impl<'a> Context<'a> { unreachable!(); } - fn find_library_crate(&mut self) -> Option { + fn find_library_crate(&mut self, + extra_prefix: &str, + seen_paths: &mut HashSet) + -> Option { // If an SVH is specified, then this is a transitive dependency that // must be loaded via -L plus some filtering. if self.hash.is_none() { @@ -434,9 +447,9 @@ impl<'a> Context<'a> { let staticpair = self.staticlibname(); // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = format!("{}{}", dypair.0, self.crate_name); - let rlib_prefix = format!("lib{}", self.crate_name); - let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name); + let dylib_prefix = format!("{}{}{}", dypair.0, self.crate_name, extra_prefix); + let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); + let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix); let mut candidates = FxHashMap(); let mut staticlibs = vec![]; @@ -476,6 +489,7 @@ impl<'a> Context<'a> { } return FileDoesntMatch; }; + info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); @@ -484,6 +498,10 @@ impl<'a> Context<'a> { let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; fs::canonicalize(path) .map(|p| { + if seen_paths.contains(&p) { + return FileDoesntMatch + }; + seen_paths.insert(p.clone()); match found_kind { CrateFlavor::Rlib => { rlibs.insert(p, kind); } CrateFlavor::Rmeta => { rmetas.insert(p, kind); } @@ -698,13 +716,13 @@ impl<'a> Context<'a> { } } - if root.triple != self.triple { + if &root.triple != self.triple { info!("Rejecting via crate triple: expected {} got {}", self.triple, root.triple); self.rejected_via_triple.push(CrateMismatch { path: libpath.to_path_buf(), - got: root.triple, + got: format!("{}", root.triple), }); return None; } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 2504f8dc251f..4bb6d8fb87cf 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -105,14 +105,11 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { } else { None }; - let foreign_items = fm.items.iter() - .map(|it| self.tcx.hir.local_def_id(it.id)) - .collect(); let lib = NativeLibrary { name: n, kind, cfg, - foreign_items, + foreign_module: Some(self.tcx.hir.local_def_id(it.id)), }; self.register_native_lib(Some(m.span), lib); } @@ -218,7 +215,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { name: Symbol::intern(new_name.unwrap_or(name)), kind: if let Some(k) = kind { k } else { cstore::NativeUnknown }, cfg: None, - foreign_items: Vec::new(), + foreign_module: None, }; self.register_native_lib(None, lib); } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 593f08e90bb3..a7ee0e7e9a96 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -15,13 +15,14 @@ use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; use rustc::ich::StableHashingContext; -use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; +use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule}; use rustc::middle::lang_items; use rustc::mir; use rustc::session::CrateDisambiguator; use rustc::ty::{self, Ty, ReprOptions}; use rustc_back::PanicStrategy; +use rustc_back::target::TargetTriple; use rustc_serialize as serialize; use syntax::{ast, attr}; @@ -186,7 +187,8 @@ pub enum LazyState { #[derive(RustcEncodable, RustcDecodable)] pub struct CrateRoot { pub name: Symbol, - pub triple: String, + pub triple: TargetTriple, + pub extra_filename: String, pub hash: hir::svh::Svh, pub disambiguator: CrateDisambiguator, pub panic_strategy: PanicStrategy, @@ -200,10 +202,12 @@ pub struct CrateRoot { pub lang_items: LazySeq<(DefIndex, usize)>, pub lang_items_missing: LazySeq, pub native_libraries: LazySeq, + pub foreign_modules: LazySeq, pub codemap: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>, + pub wasm_custom_sections: LazySeq, pub index: LazySeq, } @@ -213,12 +217,14 @@ pub struct CrateDep { pub name: ast::Name, pub hash: hir::svh::Svh, pub kind: DepKind, + pub extra_filename: String, } impl_stable_hash_for!(struct CrateDep { name, hash, - kind + kind, + extra_filename }); #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 77a3f138fe59..56371d809b26 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -18,7 +18,7 @@ use rustc_data_structures::sync::Lrc; use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; -use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements}; +use dataflow::{Borrows, BorrowData, FlowAtLocation, MovingOutStatements}; use dataflow::move_paths::MovePathIndex; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -250,7 +250,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let new_closure_span = self.find_closure_span(span, context.loc); let span = new_closure_span.map(|(args, _)| args).unwrap_or(span); - let old_closure_span = self.find_closure_span(issued_span, issued_borrow.location); + let old_closure_span = self.find_closure_span(issued_span, issued_borrow.reserve_location); let issued_span = old_closure_span .map(|(args, _)| args) .unwrap_or(issued_span); @@ -372,15 +372,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context: Context, borrow: &BorrowData<'tcx>, drop_span: Span, - borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>, + borrows: &Borrows<'cx, 'gcx, 'tcx> ) { let end_span = borrows.opt_region_end_span(&borrow.region); - let scope_tree = borrows.0.scope_tree(); + let scope_tree = borrows.scope_tree(); let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) .last() .unwrap(); - let borrow_span = self.mir.source_info(borrow.location).span; + let borrow_span = self.mir.source_info(borrow.reserve_location).span; let proper_span = match *root_place { Place::Local(local) => self.mir.local_decls[local].source_info.span, _ => drop_span, @@ -457,6 +457,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (RegionKind::ReLateBound(_, _), _) | (RegionKind::ReSkolemized(_, _), _) | (RegionKind::ReClosureBound(_), _) + | (RegionKind::ReCanonical(_), _) | (RegionKind::ReErased, _) => { span_bug!(drop_span, "region does not make sense in this context"); } @@ -788,7 +789,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } else { format!("{}", def.non_enum_variant().fields[field.index()].name) }, - ty::TyTuple(_, _) => format!("{}", field.index()), + ty::TyTuple(_) => format!("{}", field.index()), ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => { self.describe_field_from_ty(&tnm.ty, field) } @@ -817,7 +818,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Retrieve span of given borrow from the current MIR representation pub fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { - self.mir.source_info(borrow.location).span + self.mir.source_info(borrow.reserve_location).span } // Retrieve type of a place for the current MIR representation diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index ba966c9d4e31..ceff380c594e 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -17,13 +17,14 @@ use rustc::mir::{BasicBlock, Location}; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::{EverInitializedPlaces, MovingOutStatements}; -use dataflow::{ActiveBorrows, FlowAtLocation, FlowsAtLocation}; +use dataflow::{Borrows}; +use dataflow::{FlowAtLocation, FlowsAtLocation}; use dataflow::move_paths::HasMoveData; use std::fmt; // (forced to be `pub` due to its use as an associated type below.) pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { - pub borrows: FlowAtLocation>, + pub borrows: FlowAtLocation>, pub inits: FlowAtLocation>, pub uninits: FlowAtLocation>, pub move_outs: FlowAtLocation>, @@ -32,7 +33,7 @@ pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { pub fn new( - borrows: FlowAtLocation>, + borrows: FlowAtLocation>, inits: FlowAtLocation>, uninits: FlowAtLocation>, move_outs: FlowAtLocation>, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index dec32f5b2e53..5f54b7b4d9d5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -34,11 +34,10 @@ use syntax_pos::Span; use dataflow::{do_dataflow, DebugFormatted}; use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; -use dataflow::{DataflowAnalysis, DataflowResultsConsumer}; +use dataflow::{DataflowResultsConsumer}; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex}; -use dataflow::{ActiveBorrows, Reservations}; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; @@ -55,8 +54,6 @@ mod error_reporting; mod flows; mod prefixes; -use std::borrow::Cow; - pub(crate) mod nll; pub fn provide(providers: &mut Providers) { @@ -210,6 +207,18 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( }; let flow_inits = flow_inits; // remove mut + let flow_borrows = FlowAtLocation::new(do_dataflow( + tcx, + mir, + id, + &attributes, + &dead_unwinds, + Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id), + |rs, i| { + DebugFormatted::new(&(i.kind(), rs.location(i.borrow_index()))) + } + )); + let movable_generator = !match tcx.hir.get(id) { hir::map::Node::NodeExpr(&hir::Expr { node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)), @@ -231,44 +240,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( }, access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), - nonlexical_regioncx: opt_regioncx.clone(), + nonlexical_regioncx: opt_regioncx, nonlexical_cause_info: None, }; - let borrows = Borrows::new(tcx, mir, opt_regioncx, def_id, body_id); - let flow_reservations = do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - Reservations::new(borrows), - |rs, i| { - // In principle we could make the dataflow ensure that - // only reservation bits show up, and assert so here. - // - // In practice it is easier to be looser; in particular, - // it is okay for the kill-sets to hold activation bits. - DebugFormatted::new(&(i.kind(), rs.location(i))) - }, - ); - let flow_active_borrows = { - let reservations_on_entry = flow_reservations.0.sets.entry_set_state(); - let reservations = flow_reservations.0.operator; - let a = DataflowAnalysis::new_with_entry_sets( - mir, - &dead_unwinds, - Cow::Borrowed(reservations_on_entry), - ActiveBorrows::new(reservations), - ); - let results = a.run(tcx, id, &attributes, |ab, i| { - DebugFormatted::new(&(i.kind(), ab.location(i))) - }); - FlowAtLocation::new(results) - }; - let mut state = Flows::new( - flow_active_borrows, + flow_borrows, flow_inits, flow_uninits, flow_move_outs, @@ -416,11 +393,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // ignored when consuming results (update to // flow_state already handled). } - StatementKind::Nop | StatementKind::Validate(..) | StatementKind::StorageLive(..) => { - // `Nop`, `Validate`, and `StorageLive` are irrelevant + StatementKind::Nop | + StatementKind::UserAssertTy(..) | + StatementKind::Validate(..) | + StatementKind::StorageLive(..) => { + // `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant // to borrow check. } - StatementKind::StorageDead(local) => { self.access_place( ContextKind::StorageDead.new(location), @@ -554,7 +533,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // Look for any active borrows to locals let domain = flow_state.borrows.operator(); let data = domain.borrows(); - flow_state.borrows.with_elems_outgoing(|borrows| { + flow_state.borrows.with_iter_outgoing(|borrows| { for i in borrows { let borrow = &data[i.borrow_index()]; self.check_for_local_borrow(borrow, span); @@ -570,7 +549,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // so this "extra check" serves as a kind of backup. let domain = flow_state.borrows.operator(); let data = domain.borrows(); - flow_state.borrows.with_elems_outgoing(|borrows| { + flow_state.borrows.with_iter_outgoing(|borrows| { for i in borrows { let borrow = &data[i.borrow_index()]; let context = ContextKind::StorageDead.new(loc); @@ -756,7 +735,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { for (index, field) in def.all_fields().enumerate() { let gcx = self.tcx.global_tcx(); let field_ty = field.ty(gcx, substs); - let field_ty = gcx.normalize_associated_type_in_env(&field_ty, self.param_env); + let field_ty = gcx.normalize_erasing_regions(self.param_env, field_ty); let place = drop_place.clone().field(Field::new(index), field_ty); self.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span); @@ -1316,7 +1295,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place ); - for i in flow_state.ever_inits.elems_incoming() { + for i in flow_state.ever_inits.iter_incoming() { let init = self.move_data.inits[i]; let init_place = &self.move_data.move_paths[init.path].place; if self.places_conflict(&init_place, place, Deep) { @@ -2199,8 +2178,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. - let mut elems_incoming = flow_state.borrows.elems_incoming(); - while let Some(i) = elems_incoming.next() { + let mut iter_incoming = flow_state.borrows.iter_incoming(); + while let Some(i) = iter_incoming.next() { let borrowed = &data[i.borrow_index()]; if self.places_conflict(&borrowed.borrowed_place, place, access) { diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 3a39eb5c908d..afaedecdf0ab 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -12,10 +12,10 @@ use rustc::hir; use rustc::mir::{BasicBlock, BasicBlockData, Location, Place, Mir, Rvalue}; use rustc::mir::visit::Visitor; use rustc::mir::Place::Projection; -use rustc::mir::{PlaceProjection, ProjectionElem}; +use rustc::mir::{Local, PlaceProjection, ProjectionElem}; use rustc::mir::visit::TyContext; use rustc::infer::InferCtxt; -use rustc::ty::{self, ClosureSubsts}; +use rustc::ty::{self, CanonicalTy, ClosureSubsts}; use rustc::ty::subst::Substs; use rustc::ty::fold::TypeFoldable; @@ -106,6 +106,9 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx self.super_rvalue(rvalue, location); } + + fn visit_user_assert_ty(&mut self, _c_ty: &CanonicalTy<'tcx>, + _local: &Local, _location: Location) { } } impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs b/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs index d55b60182324..4fcd3118f910 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs @@ -18,9 +18,26 @@ use borrow_check::nll::region_infer::values::{RegionElementIndex, RegionValueEle use syntax::codemap::Span; use rustc::mir::{Location, Mir}; use rustc::ty::RegionVid; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::bitvec::BitVector; +use rustc_data_structures::indexed_vec::Idx; + +pub(super) struct DfsStorage { + stack: Vec, + visited: BitVector, +} impl<'tcx> RegionInferenceContext<'tcx> { + /// Creates dfs storage for use by dfs; this should be shared + /// across as many calls to dfs as possible to amortize allocation + /// costs. + pub(super) fn new_dfs_storage(&self) -> DfsStorage { + let num_elements = self.elements.num_elements(); + DfsStorage { + stack: vec![], + visited: BitVector::new(num_elements), + } + } + /// Function used to satisfy or test a `R1: R2 @ P` /// constraint. The core idea is that it performs a DFS starting /// from `P`. The precise actions *during* that DFS depend on the @@ -34,17 +51,21 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// - `Ok(false)` if the walk was completed with no changes; /// - `Err(early)` if the walk was existed early by `op`. `earlyelem` is the /// value that `op` returned. - pub(super) fn dfs(&self, mir: &Mir<'tcx>, mut op: C) -> Result + #[inline(never)] // ensure dfs is identifiable in profiles + pub(super) fn dfs( + &self, + mir: &Mir<'tcx>, + dfs: &mut DfsStorage, + mut op: C, + ) -> Result where C: DfsOp, { let mut changed = false; - let mut stack = vec![]; - let mut visited = FxHashSet(); - - stack.push(op.start_point()); - while let Some(p) = stack.pop() { + dfs.visited.clear(); + dfs.stack.push(op.start_point()); + while let Some(p) = dfs.stack.pop() { let point_index = self.elements.index(p); if !op.source_region_contains(point_index) { @@ -52,7 +73,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { continue; } - if !visited.insert(p) { + if !dfs.visited.insert(point_index.index()) { debug!(" already visited"); continue; } @@ -62,25 +83,27 @@ impl<'tcx> RegionInferenceContext<'tcx> { let block_data = &mir[p.block]; - let start_stack_len = stack.len(); + let start_stack_len = dfs.stack.len(); if p.statement_index < block_data.statements.len() { - stack.push(Location { + dfs.stack.push(Location { statement_index: p.statement_index + 1, ..p }); } else { - stack.extend(block_data.terminator().successors().iter().map( - |&basic_block| { - Location { + dfs.stack.extend( + block_data + .terminator() + .successors() + .iter() + .map(|&basic_block| Location { statement_index: 0, block: basic_block, - } - }, - )); + }), + ); } - if stack.len() == start_stack_len { + if dfs.stack.len() == start_stack_len { // If we reach the END point in the graph, then copy // over any skolemized end points in the `from_region` // and make sure they are included in the `to_region`. @@ -229,9 +252,8 @@ impl<'v, 'tcx> DfsOp for TestTargetOutlivesSource<'v, 'tcx> { // `X: ur_in_source`, OK. if self.inferred_values .universal_regions_outlived_by(self.target_region) - .any(|ur_in_target| { - self.universal_regions.outlives(ur_in_target, ur_in_source) - }) { + .any(|ur_in_target| self.universal_regions.outlives(ur_in_target, ur_in_source)) + { continue; } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs index 631b1d0f8941..b0346abee5a5 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs @@ -84,6 +84,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { sub, point, span, + next: _, } = constraint; with_msg(&format!( "{:?}: {:?} @ {:?} due to {:?}", diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs index db773240809c..6c4c02a36a0d 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs @@ -55,7 +55,7 @@ impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> { vids.into_cow() } fn edges(&'this self) -> dot::Edges<'this, Constraint> { - (&self.constraints[..]).into_cow() + (&self.constraints.raw[..]).into_cow() } // Render `a: b` as `a <- b`, indicating the flow diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 66776a94ff01..08391401cc69 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; - use super::universal_regions::UniversalRegions; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; @@ -23,9 +21,9 @@ use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegi Local, Location, Mir}; use rustc::traits::ObligationCause; use rustc::ty::{self, RegionVid, Ty, TypeFoldable}; -use rustc::util::common::ErrorReported; +use rustc::util::common::{self, ErrorReported}; use rustc_data_structures::bitvec::BitVector; -use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use std::fmt; use std::rc::Rc; use syntax::ast; @@ -61,8 +59,15 @@ pub struct RegionInferenceContext<'tcx> { /// until `solve` is invoked. inferred_values: Option, + /// For each variable, stores the index of the first constraint + /// where that variable appears on the RHS. This is the start of a + /// 'linked list' threaded by the `next` field in `Constraint`. + /// + /// This map is build when values are inferred. + dependency_map: Option>>, + /// The constraints we have accumulated and used during solving. - constraints: Vec, + constraints: IndexVec, /// Type constraints that we check after solving. type_tests: Vec>, @@ -143,10 +148,22 @@ pub struct Constraint { /// At this location. point: Location, + /// Later on, we thread the constraints onto a linked list + /// grouped by their `sub` field. So if you had: + /// + /// Index | Constraint | Next Field + /// ----- | ---------- | ---------- + /// 0 | `'a: 'b` | Some(2) + /// 1 | `'b: 'c` | None + /// 2 | `'c: 'b` | None + next: Option, + /// Where did this constraint arise? span: Span, } +newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" }); + /// A "type test" corresponds to an outlives constraint between a type /// and a lifetime, like `T: 'x` or `::Bar: 'x`. They are /// translated from the `Verify` region constraints in the ordinary @@ -259,7 +276,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { elements: elements.clone(), liveness_constraints: RegionValues::new(elements, num_region_variables), inferred_values: None, - constraints: Vec::new(), + dependency_map: None, + constraints: IndexVec::new(), type_tests: Vec::new(), universal_regions, }; @@ -387,6 +405,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { sup, sub, point, + next: None, }); } @@ -403,10 +422,25 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx: &InferCtxt<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, mir_def_id: DefId, + ) -> Option> { + common::time( + infcx.tcx.sess, + &format!("solve_nll_region_constraints({:?})", mir_def_id), + || self.solve_inner(infcx, mir, mir_def_id), + ) + } + + fn solve_inner<'gcx>( + &mut self, + infcx: &InferCtxt<'_, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + mir_def_id: DefId, ) -> Option> { assert!(self.inferred_values.is_none(), "values already inferred"); - self.propagate_constraints(mir); + let dfs_storage = &mut self.new_dfs_storage(); + + self.propagate_constraints(mir, dfs_storage); // If this is a closure, we can propagate unsatisfied // `outlives_requirements` to our creator, so create a vector @@ -419,7 +453,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { None }; - self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut()); + self.check_type_tests( + infcx, + mir, + dfs_storage, + mir_def_id, + outlives_requirements.as_mut(), + ); self.check_universal_regions(infcx, mir_def_id, outlives_requirements.as_mut()); @@ -439,7 +479,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Re-execute the region inference, this time tracking causal information. /// This is significantly slower, so it is done only when an error is being reported. pub(super) fn compute_causal_info(&self, mir: &Mir<'tcx>) -> RegionCausalInfo { - let inferred_values = self.compute_region_values(mir, TrackCauses(true)); + let dfs_storage = &mut self.new_dfs_storage(); + let inferred_values = self.compute_region_values(mir, dfs_storage, TrackCauses(true)); RegionCausalInfo { inferred_values } } @@ -447,12 +488,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be /// feasible, but we check this later. - fn propagate_constraints(&mut self, mir: &Mir<'tcx>) { - let inferred_values = self.compute_region_values(mir, TrackCauses(false)); + fn propagate_constraints(&mut self, mir: &Mir<'tcx>, dfs_storage: &mut dfs::DfsStorage) { + self.dependency_map = Some(self.build_dependency_map()); + let inferred_values = self.compute_region_values(mir, dfs_storage, TrackCauses(false)); self.inferred_values = Some(inferred_values); } - fn compute_region_values(&self, mir: &Mir<'tcx>, track_causes: TrackCauses) -> RegionValues { + #[inline(never)] // ensure dfs is identifiable in profiles + fn compute_region_values( + &self, + mir: &Mir<'tcx>, + dfs_storage: &mut dfs::DfsStorage, + track_causes: TrackCauses, + ) -> RegionValues { debug!("compute_region_values()"); debug!("compute_region_values: constraints={:#?}", { let mut constraints: Vec<_> = self.constraints.iter().collect(); @@ -464,17 +512,17 @@ impl<'tcx> RegionInferenceContext<'tcx> { // constraints we have accumulated. let mut inferred_values = self.liveness_constraints.duplicate(track_causes); - let dependency_map = self.build_dependency_map(); + let dependency_map = self.dependency_map.as_ref().unwrap(); // Constraints that may need to be repropagated (initially all): - let mut dirty_list: Vec<_> = (0..self.constraints.len()).collect(); + let mut dirty_list: Vec<_> = self.constraints.indices().collect(); // Set to 0 for each constraint that is on the dirty list: let mut clean_bit_vec = BitVector::new(dirty_list.len()); debug!("propagate_constraints: --------------------"); while let Some(constraint_idx) = dirty_list.pop() { - clean_bit_vec.insert(constraint_idx); + clean_bit_vec.insert(constraint_idx.index()); let constraint = &self.constraints[constraint_idx]; debug!("propagate_constraints: constraint={:?}", constraint); @@ -483,6 +531,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // outlives constraint. let Ok(made_changes) = self.dfs( mir, + dfs_storage, CopyFromSourceToTarget { source_region: constraint.sub, target_region: constraint.sup, @@ -496,10 +545,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("propagate_constraints: sub={:?}", constraint.sub); debug!("propagate_constraints: sup={:?}", constraint.sup); - for &dep_idx in dependency_map.get(&constraint.sup).unwrap_or(&vec![]) { - if clean_bit_vec.remove(dep_idx) { + let mut opt_dep_idx = dependency_map[constraint.sup]; + while let Some(dep_idx) = opt_dep_idx { + if clean_bit_vec.remove(dep_idx.index()) { dirty_list.push(dep_idx); } + opt_dep_idx = self.constraints[dep_idx].next; } } @@ -513,11 +564,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// indices of constraints that need to be re-evaluated when X changes. /// These are constraints like Y: X @ P -- so if X changed, we may /// need to grow Y. - fn build_dependency_map(&self) -> HashMap> { - let mut map = HashMap::new(); + #[inline(never)] // ensure dfs is identifiable in profiles + fn build_dependency_map(&mut self) -> IndexVec> { + let mut map = IndexVec::from_elem(None, &self.definitions); - for (idx, constraint) in self.constraints.iter().enumerate() { - map.entry(constraint.sub).or_insert(Vec::new()).push(idx); + for (idx, constraint) in self.constraints.iter_enumerated_mut().rev() { + let mut head = &mut map[constraint.sub]; + debug_assert!(constraint.next.is_none()); + constraint.next = *head; + *head = Some(idx); } map @@ -531,6 +586,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, infcx: &InferCtxt<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, + dfs_storage: &mut dfs::DfsStorage, mir_def_id: DefId, mut propagated_outlives_requirements: Option<&mut Vec>>, ) { @@ -539,7 +595,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { for type_test in &self.type_tests { debug!("check_type_test: {:?}", type_test); - if self.eval_region_test(mir, type_test.point, type_test.lower_bound, &type_test.test) { + if self.eval_region_test( + mir, + dfs_storage, + type_test.point, + type_test.lower_bound, + &type_test.test, + ) { continue; } @@ -796,6 +858,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn eval_region_test( &self, mir: &Mir<'tcx>, + dfs_storage: &mut dfs::DfsStorage, point: Location, lower_bound: RegionVid, test: &RegionTest, @@ -808,19 +871,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { match test { RegionTest::IsOutlivedByAllRegionsIn(regions) => regions .iter() - .all(|&r| self.eval_outlives(mir, r, lower_bound, point)), + .all(|&r| self.eval_outlives(mir, dfs_storage, r, lower_bound, point)), RegionTest::IsOutlivedByAnyRegionIn(regions) => regions .iter() - .any(|&r| self.eval_outlives(mir, r, lower_bound, point)), + .any(|&r| self.eval_outlives(mir, dfs_storage, r, lower_bound, point)), RegionTest::Any(tests) => tests .iter() - .any(|test| self.eval_region_test(mir, point, lower_bound, test)), + .any(|test| self.eval_region_test(mir, dfs_storage, point, lower_bound, test)), RegionTest::All(tests) => tests .iter() - .all(|test| self.eval_region_test(mir, point, lower_bound, test)), + .all(|test| self.eval_region_test(mir, dfs_storage, point, lower_bound, test)), } } @@ -828,6 +891,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn eval_outlives( &self, mir: &Mir<'tcx>, + dfs_storage: &mut dfs::DfsStorage, sup_region: RegionVid, sub_region: RegionVid, point: Location, @@ -843,6 +907,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // yield an `Err` result. match self.dfs( mir, + dfs_storage, TestTargetOutlivesSource { source_region: sub_region, target_region: sup_region, diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c54acda8a625..04c206b5c0c4 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -9,8 +9,8 @@ // except according to those terms. use rustc::ty::subst::Substs; -use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable}; -use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind}; +use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable}; +use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -118,6 +118,14 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_closure_substs: substs={:?}", substs); } + fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local, + _location: Location) { + // User-assert-ty statements represent types that the user added explicitly. + // We don't want to erase the regions from these types: rather, we want to + // add them as constraints at type-check time. + debug!("visit_user_assert_ty: skipping renumber"); + } + fn visit_statement( &mut self, block: BasicBlock, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index a50b99937475..d19fd2bb5969 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -14,13 +14,9 @@ use dataflow::MaybeInitializedPlaces; use dataflow::move_paths::{HasMoveData, MoveData}; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::mir::Local; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::traits; +use rustc::ty::{Ty, TyCtxt, TypeFoldable}; use rustc::infer::InferOk; -use rustc::util::common::ErrorReported; use borrow_check::nll::type_check::AtLocation; -use rustc_data_structures::fx::FxHashSet; -use syntax::codemap::DUMMY_SP; use util::liveness::LivenessResults; use super::TypeChecker; @@ -105,8 +101,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo for live_local in live_locals { debug!( "add_liveness_constraints: location={:?} live_local={:?}", - location, - live_local + location, live_local ); self.flow_inits.each_state_bit(|mpi_init| { @@ -157,8 +152,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo { debug!( "push_type_live_constraint(live_ty={:?}, location={:?})", - value, - location + value, location ); self.tcx.for_each_free_region(&value, |live_region| { @@ -182,9 +176,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo ) { debug!( "add_drop_live_constraint(dropped_local={:?}, dropped_ty={:?}, location={:?})", - dropped_local, - dropped_ty, - location + dropped_local, dropped_ty, location ); // If we end visiting the same type twice (usually due to a cycle involving @@ -197,73 +189,34 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo // // For this reason, we avoid calling TypeChecker.normalize, instead doing all normalization // ourselves in one large 'fully_perform_op' callback. - let (type_constraints, kind_constraints) = self.cx.fully_perform_op(location.at_self(), - |cx| { + let kind_constraints = self.cx + .fully_perform_op(location.at_self(), |cx| { + let span = cx.last_span; - let tcx = cx.infcx.tcx; - let mut selcx = traits::SelectionContext::new(cx.infcx); - let cause = cx.misc(cx.last_span); + let mut final_obligations = Vec::new(); + let mut kind_constraints = Vec::new(); - let mut types = vec![(dropped_ty, 0)]; - let mut final_obligations = Vec::new(); - let mut type_constraints = Vec::new(); - let mut kind_constraints = Vec::new(); - - let mut known = FxHashSet(); - - while let Some((ty, depth)) = types.pop() { - let span = DUMMY_SP; // FIXME - let result = match tcx.dtorck_constraint_for_ty(span, dropped_ty, depth, ty) { - Ok(result) => result, - Err(ErrorReported) => { - continue; - } - }; - - let ty::DtorckConstraint { - outlives, - dtorck_types, - } = result; - - // All things in the `outlives` array may be touched by - // the destructor and must be live at this point. - for outlive in outlives { + let InferOk { + value: kinds, + obligations, + } = cx.infcx + .at(&cx.misc(span), cx.param_env) + .dropck_outlives(dropped_ty); + for kind in kinds { + // All things in the `outlives` array may be touched by + // the destructor and must be live at this point. let cause = Cause::DropVar(dropped_local, location); - kind_constraints.push((outlive, location, cause)); + kind_constraints.push((kind, location, cause)); } - // However, there may also be some types that - // `dtorck_constraint_for_ty` could not resolve (e.g., - // associated types and parameters). We need to normalize - // associated types here and possibly recursively process. - for ty in dtorck_types { - let traits::Normalized { value: ty, obligations } = - traits::normalize(&mut selcx, cx.param_env, cause.clone(), &ty); + final_obligations.extend(obligations); - final_obligations.extend(obligations); - - let ty = cx.infcx.resolve_type_and_region_vars_if_possible(&ty); - match ty.sty { - ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => { - let cause = Cause::DropVar(dropped_local, location); - type_constraints.push((ty, location, cause)); - } - - _ => if known.insert(ty) { - types.push((ty, depth + 1)); - }, - } - } - } - - Ok(InferOk { - value: (type_constraints, kind_constraints), obligations: final_obligations + Ok(InferOk { + value: kind_constraints, + obligations: final_obligations, + }) }) - }).unwrap(); - - for (ty, location, cause) in type_constraints { - self.push_type_live_constraint(ty, location, cause); - } + .unwrap(); for (kind, location, cause) in kind_constraints { self.push_type_live_constraint(kind, location, cause); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 36e173dd5d64..544cb5eefc88 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -20,7 +20,8 @@ use dataflow::move_paths::MoveData; use rustc::hir::def_id::DefId; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; use rustc::infer::region_constraints::{GenericKind, RegionConstraintData}; -use rustc::traits::{self, FulfillmentContext}; +use rustc::traits::{self, Normalized, TraitEngine}; +use rustc::traits::query::NoSolution; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants}; @@ -243,8 +244,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { debug!( "sanitize_constant(constant={:?}, location={:?})", - constant, - location + constant, location ); let expected_ty = match constant.literal { @@ -542,7 +542,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }), }; } - ty::TyTuple(tys, _) => { + ty::TyTuple(tys) => { return match tys.get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { @@ -662,7 +662,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { where OP: FnOnce(&mut Self) -> InferResult<'tcx, R>, { - let mut fulfill_cx = FulfillmentContext::new(); + let mut fulfill_cx = TraitEngine::new(self.infcx.tcx); let InferOk { value, obligations } = self.infcx.commit_if_ok(|_| op(self))?; fulfill_cx.register_predicate_obligations(self.infcx, obligations); if let Err(e) = fulfill_cx.select_all_or_error(self.infcx) { @@ -678,8 +678,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let data = self.infcx.take_and_reset_region_constraints(); if !data.is_empty() { - debug!("fully_perform_op: constraints generated at {:?} are {:#?}", - locations, data); + debug!( + "fully_perform_op: constraints generated at {:?} are {:#?}", + locations, data + ); self.constraints .outlives_sets .push(OutlivesSet { locations, data }); @@ -759,6 +761,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); }; } + StatementKind::UserAssertTy(ref c_ty, ref local) => { + let local_ty = mir.local_decls()[*local].ty; + let (ty, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( + stmt.source_info.span, c_ty); + debug!("check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty); + if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) { + span_mirbug!( + self, + stmt, + "bad type assert ({:?} = {:?}): {:?}", + ty, + local_ty, + terr + ); + } + } StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::InlineAsm { .. } @@ -1137,12 +1155,16 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } TerminatorKind::FalseUnwind { real_target, - unwind + unwind, } => { self.assert_iscleanup(mir, block_data, real_target, is_cleanup); if let Some(unwind) = unwind { if is_cleanup { - span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind"); + span_mirbug!( + self, + block_data, + "cleanup in cleanup block via false unwind" + ); } self.assert_iscleanup(mir, block_data, unwind, true); } @@ -1435,8 +1457,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { debug!( "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})", - aggregate_kind, - location + aggregate_kind, location ); let instantiated_predicates = match aggregate_kind { @@ -1502,8 +1523,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn prove_predicates(&mut self, predicates: &[ty::Predicate<'tcx>], location: Location) { debug!( "prove_predicates(predicates={:?}, location={:?})", - predicates, - location + predicates, location ); self.fully_perform_op(location.at_self(), |this| { let cause = this.misc(this.last_span); @@ -1550,10 +1570,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { { debug!("normalize(value={:?}, location={:?})", value, location); self.fully_perform_op(location.at_self(), |this| { - let mut selcx = traits::SelectionContext::new(this.infcx); - let cause = this.misc(this.last_span); - let traits::Normalized { value, obligations } = - traits::normalize(&mut selcx, this.param_env, cause, value); + let Normalized { value, obligations } = this.infcx + .at(&this.misc(this.last_span), this.param_env) + .normalize(value) + .unwrap_or_else(|NoSolution| { + span_bug!( + this.last_span, + "normalization of `{:?}` failed at {:?}", + value, + location, + ); + }); Ok(InferOk { value, obligations }) }).unwrap() } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index 668172749fec..39dc29ba18b6 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -635,7 +635,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); let inputs = match tuplized_inputs[0].sty { - ty::TyTuple(inputs, _) => inputs, + ty::TyTuple(inputs) => inputs, _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), }; @@ -777,6 +777,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { where T: TypeFoldable<'tcx>, { + debug!( + "replace_bound_regions_with_nll_infer_vars(value={:?}, all_outlive_scope={:?})", + value, + all_outlive_scope, + ); let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| { let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: all_outlive_scope, @@ -784,6 +789,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { })); let region_vid = self.next_nll_region_var(origin); indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); + debug!("liberated_region={:?} => {:?}", liberated_region, region_vid); region_vid }); value diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index ef30b1e45223..94702927d260 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -102,6 +102,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { remainder_scope, init_scope, pattern, + ty, initializer, lint_level } => { @@ -117,14 +118,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { unpack!(block = this.in_opt_scope( - opt_destruction_scope.map(|de|(de, source_info)), block, move |this| { + opt_destruction_scope.map(|de|(de, source_info)), block, |this| { let scope = (init_scope, source_info); - this.in_scope(scope, lint_level, block, move |this| { - // FIXME #30046 ^~~~ - this.expr_into_pattern(block, pattern, init) + this.in_scope(scope, lint_level, block, |this| { + this.expr_into_pattern(block, ty, pattern, init) }) })); } else { + // FIXME(#47184): We currently only insert `UserAssertTy` statements for + // patterns that are bindings, this is as we do not want to deconstruct + // the type being assertion to match the pattern. + if let PatternKind::Binding { var, .. } = *pattern.kind { + if let Some(ty) = ty { + this.user_assert_ty(block, ty, var, span); + } + } + this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| { this.storage_live_binding(block, node, span); this.schedule_drop_for_binding(node, span); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 1a9064aab1b2..b7f402f61a9c 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -298,7 +298,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); let bool_ty = self.hir.bool_ty(); if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { - let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false); + let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]); let result_value = self.temp(result_tup, span); self.cfg.push_assign(block, source_info, diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 229e33dcd786..7eb52a3cdee9 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -145,8 +145,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { end_block.unit() } + pub fn user_assert_ty(&mut self, block: BasicBlock, hir_id: hir::HirId, + var: NodeId, span: Span) { + if self.hir.tcx().sess.opts.debugging_opts.disable_nll_user_type_assert { return; } + + let local_id = self.var_indices[&var]; + let source_info = self.source_info(span); + + debug!("user_assert_ty: local_id={:?}", hir_id.local_id); + if let Some(c_ty) = self.hir.tables.user_provided_tys().get(hir_id) { + debug!("user_assert_ty: c_ty={:?}", c_ty); + self.cfg.push(block, Statement { + source_info, + kind: StatementKind::UserAssertTy(*c_ty, local_id), + }); + } + } + pub fn expr_into_pattern(&mut self, mut block: BasicBlock, + ty: Option, irrefutable_pat: Pattern<'tcx>, initializer: ExprRef<'tcx>) -> BlockAnd<()> { @@ -156,6 +174,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { var, subpattern: None, .. } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span); + + if let Some(ty) = ty { + self.user_assert_ty(block, ty, var, irrefutable_pat.span); + } + unpack!(block = self.into(&place, block, initializer)); self.schedule_drop_for_binding(var, irrefutable_pat.span); block.unit() diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index abea55835466..4e95ee6444dc 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || { - self.hir.tcx().features().never_type && + self.hir.tcx().features().exhaustive_patterns && self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs) } }); diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 09579eaecb2d..c50d84c10d86 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -196,15 +196,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut values = Vec::with_capacity(used_variants); let tcx = self.hir.tcx(); for (idx, discr) in adt_def.discriminants(tcx).enumerate() { - target_blocks.place_back() <- if variants.contains(idx) { + target_blocks.push(if variants.contains(idx) { values.push(discr.val); - *(targets.place_back() <- self.cfg.start_new_block()) + targets.push(self.cfg.start_new_block()); + *targets.last().unwrap() } else { if otherwise_block.is_none() { otherwise_block = Some(self.cfg.start_new_block()); } otherwise_block.unwrap() - }; + }); } if let Some(otherwise_block) = otherwise_block { targets.push(otherwise_block); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 23c5499bb639..6f5fcc9e421c 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -317,7 +317,7 @@ newtype_index!(ScopeId); /// macro (and methods below) makes working with `BlockAnd` much more /// convenient. -#[must_use] // if you don't use one of these results, you're leaving a dangling edge +#[must_use = "if you don't use one of these results, you're leaving a dangling edge"] struct BlockAnd(BasicBlock, T); trait BlockAndExtension { @@ -422,7 +422,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, builder.args_and_body(block, &arguments, arg_scope, &body.value) })); // Attribute epilogue to function's closing brace - let fn_end = span.with_lo(span.hi()); + let fn_end = span.shrink_to_hi(); let source_info = builder.source_info(fn_end); let return_block = builder.return_block(); builder.cfg.terminate(block, source_info, diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index b1f73bfbe228..0fbb54e8e0a0 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -12,7 +12,7 @@ //! locations. use rustc::mir::{BasicBlock, Location}; -use rustc_data_structures::indexed_set::{self, IdxSetBuf}; +use rustc_data_structures::indexed_set::{IdxSetBuf, Iter}; use rustc_data_structures::indexed_vec::Idx; use dataflow::{BitDenotation, BlockSets, DataflowResults}; @@ -81,8 +81,7 @@ where where F: FnMut(BD::Idx), { - self.curr_state - .each_bit(self.base_results.operator().bits_per_block(), f) + self.curr_state.iter().for_each(f) } /// Iterate over each `gen` bit in the current effect (invoke @@ -92,8 +91,7 @@ where where F: FnMut(BD::Idx), { - self.stmt_gen - .each_bit(self.base_results.operator().bits_per_block(), f) + self.stmt_gen.iter().for_each(f) } pub fn new(results: DataflowResults) -> Self { @@ -119,23 +117,21 @@ where } /// Returns an iterator over the elements present in the current state. - pub fn elems_incoming(&self) -> iter::Peekable> { - let univ = self.base_results.sets().bits_per_block(); - self.curr_state.elems(univ).peekable() + pub fn iter_incoming(&self) -> iter::Peekable> { + self.curr_state.iter().peekable() } /// Creates a clone of the current state and applies the local /// effects to the clone (leaving the state of self intact). /// Invokes `f` with an iterator over the resulting state. - pub fn with_elems_outgoing(&self, f: F) + pub fn with_iter_outgoing(&self, f: F) where - F: FnOnce(indexed_set::Elems), + F: FnOnce(Iter), { let mut curr_state = self.curr_state.clone(); curr_state.union(&self.stmt_gen); curr_state.subtract(&self.stmt_kill); - let univ = self.base_results.sets().bits_per_block(); - f(curr_state.elems(univ)); + f(curr_state.iter()); } } @@ -147,8 +143,8 @@ impl FlowsAtLocation for FlowAtLocation } fn reconstruct_statement_effect(&mut self, loc: Location) { - self.stmt_gen.reset_to_empty(); - self.stmt_kill.reset_to_empty(); + self.stmt_gen.clear(); + self.stmt_kill.clear(); { let mut sets = BlockSets { on_entry: &mut self.curr_state, @@ -172,8 +168,8 @@ impl FlowsAtLocation for FlowAtLocation } fn reconstruct_terminator_effect(&mut self, loc: Location) { - self.stmt_gen.reset_to_empty(); - self.stmt_kill.reset_to_empty(); + self.stmt_gen.clear(); + self.stmt_kill.clear(); { let mut sets = BlockSets { on_entry: &mut self.curr_state, diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index fb3cb1518cbb..07585c08f6a2 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -20,12 +20,9 @@ use dot::IntoCow; use std::fs; use std::io; -use std::io::prelude::*; use std::marker::PhantomData; use std::path::Path; -use util; - use super::{BitDenotation, DataflowState}; use super::DataflowBuilder; use super::DebugFormatted; @@ -98,158 +95,162 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> } fn node_label(&self, n: &Node) -> dot::LabelText { - // A standard MIR label, as generated by write_node_label, is - // presented in a single column in a table. - // - // The code below does a bunch of formatting work to format a - // node (i.e. MIR basic-block) label with extra - // dataflow-enriched information. In particular, the goal is - // to add extra columns that present the three dataflow - // bitvectors, and the data those bitvectors represent. - // - // It presents it in the following format (where I am - // presenting the table rendering via ASCII art, one line per - // row of the table, and a chunk size of 3 rather than 5): - // - // ------ ----------------------- ------------ -------------------- - // [e1, e3, e4] - // [e8, e9] "= ENTRY:" - // ------ ----------------------- ------------ -------------------- - // Left - // Most - // Column - // Is - // Just - // Normal - // Series - // Of - // MIR - // Stmts - // ------ ----------------------- ------------ -------------------- - // [g1, g4, g5] "= GEN:" - // ------ ----------------------- ------------ -------------------- - // "KILL:" "=" [k1, k3, k8] - // [k9] - // ------ ----------------------- ------------ -------------------- - // - // (In addition, the added dataflow is rendered with a colored - // background just so it will stand out compared to the - // statements.) + // Node label is something like this: + // +---------+----------------------------------+------------------+------------------+ + // | ENTRY | MIR | GEN | KILL | + // +---------+----------------------------------+------------------+------------------+ + // | | 0: StorageLive(_7) | bb3[2]: reserved | bb2[0]: reserved | + // | | 1: StorageLive(_8) | bb3[2]: active | bb2[0]: active | + // | | 2: _8 = &mut _1 | | bb4[2]: reserved | + // | | | | bb4[2]: active | + // | | | | bb9[0]: reserved | + // | | | | bb9[0]: active | + // | | | | bb10[0]: reserved| + // | | | | bb10[0]: active | + // | | | | bb11[0]: reserved| + // | | | | bb11[0]: active | + // +---------+----------------------------------+------------------+------------------+ + // | [00-00] | _7 = const Foo::twiddle(move _8) | [0c-00] | [f3-0f] | + // +---------+----------------------------------+------------------+------------------+ let mut v = Vec::new(); - let i = n.index(); - let chunk_size = 5; - const BG_FLOWCONTENT: &'static str = r#"bgcolor="pink""#; - const ALIGN_RIGHT: &'static str = r#"align="right""#; - const FACE_MONOSPACE: &'static str = r#"FACE="Courier""#; - fn chunked_present_left(w: &mut W, - interpreted: &[DebugFormatted], - chunk_size: usize) - -> io::Result<()> - { - // This function may emit a sequence of 's, but it - // always finishes with an (unfinished) - // - // - // Thus, after being called, one should finish both the - // pending as well as the itself. - let mut seen_one = false; - for c in interpreted.chunks(chunk_size) { - if seen_one { - // if not the first row, finish off the previous row - write!(w, "")?; - } - write!(w, "{objs:?}", - bg = BG_FLOWCONTENT, - align = ALIGN_RIGHT, - objs = c)?; - seen_one = true; - } - if !seen_one { - write!(w, "[]", - bg = BG_FLOWCONTENT, - align = ALIGN_RIGHT)?; - } - Ok(()) - } - util::write_graphviz_node_label( - *n, self.mbcx.mir(), &mut v, 4, - |w| { - let flow = self.mbcx.flow_state(); - let entry_interp = flow.interpret_set(&flow.operator, - flow.sets.on_entry_set_for(i), - &self.render_idx); - chunked_present_left(w, &entry_interp[..], chunk_size)?; - let bits_per_block = flow.sets.bits_per_block(); - let entry = flow.sets.on_entry_set_for(i); - debug!("entry set for i={i} bits_per_block: {bpb} entry: {e:?} interp: {ei:?}", - i=i, e=entry, bpb=bits_per_block, ei=entry_interp); - write!(w, "= ENTRY:{entrybits:?}\ - ", - bg = BG_FLOWCONTENT, - face = FACE_MONOSPACE, - entrybits=bits_to_string(entry.words(), bits_per_block)) - }, - |w| { - let flow = self.mbcx.flow_state(); - let gen_interp = - flow.interpret_set(&flow.operator, flow.sets.gen_set_for(i), &self.render_idx); - let kill_interp = - flow.interpret_set(&flow.operator, flow.sets.kill_set_for(i), &self.render_idx); - chunked_present_left(w, &gen_interp[..], chunk_size)?; - let bits_per_block = flow.sets.bits_per_block(); - { - let gen = flow.sets.gen_set_for(i); - debug!("gen set for i={i} bits_per_block: {bpb} gen: {g:?} interp: {gi:?}", - i=i, g=gen, bpb=bits_per_block, gi=gen_interp); - write!(w, " = GEN:{genbits:?}\ - ", - bg = BG_FLOWCONTENT, - face = FACE_MONOSPACE, - genbits=bits_to_string(gen.words(), bits_per_block))?; - } - - { - let kill = flow.sets.kill_set_for(i); - debug!("kill set for i={i} bits_per_block: {bpb} kill: {k:?} interp: {ki:?}", - i=i, k=kill, bpb=bits_per_block, ki=kill_interp); - write!(w, "KILL:\ - {killbits:?}", - bg = BG_FLOWCONTENT, - align = ALIGN_RIGHT, - face = FACE_MONOSPACE, - killbits=bits_to_string(kill.words(), bits_per_block))?; - } - - // (chunked_present_right) - let mut seen_one = false; - for k in kill_interp.chunks(chunk_size) { - if !seen_one { - // continuation of row; this is fourth - write!(w, "= {kill:?}", - bg = BG_FLOWCONTENT, - kill=k)?; - } else { - // new row, with indent of three 's - write!(w, "{kill:?}", - bg = BG_FLOWCONTENT, - kill=k)?; - } - seen_one = true; - } - if !seen_one { - write!(w, "= []", - bg = BG_FLOWCONTENT)?; - } - - Ok(()) - }) - .unwrap(); + self.node_label_internal(n, &mut v, *n, self.mbcx.mir()).unwrap(); dot::LabelText::html(String::from_utf8(v).unwrap()) } + fn node_shape(&self, _n: &Node) -> Option { Some(dot::LabelText::label("none")) } + + fn edge_label(&'a self, e: &Edge) -> dot::LabelText<'a> { + let term = self.mbcx.mir()[e.source].terminator(); + let label = &term.kind.fmt_successor_labels()[e.index]; + dot::LabelText::label(label.clone()) + } +} + +impl<'a, 'tcx, MWF, P> Graph<'a, 'tcx, MWF, P> +where MWF: MirWithFlowState<'tcx>, + P: Fn(&MWF::BD, ::Idx) -> DebugFormatted, +{ + /// Generate the node label + fn node_label_internal(&self, + n: &Node, + w: &mut W, + block: BasicBlock, + mir: &Mir) -> io::Result<()> { + // Header rows + const HDRS: [&'static str; 4] = ["ENTRY", "MIR", "BLOCK GENS", "BLOCK KILLS"]; + const HDR_FMT: &'static str = "bgcolor=\"grey\""; + write!(w, "")?; + for hdr in &HDRS { + write!(w, "", HDR_FMT, hdr)?; + } + write!(w, "")?; + + // Data row + self.node_label_verbose_row(n, w, block, mir)?; + self.node_label_final_row(n, w, block, mir)?; + write!(w, "
", HDRS.len())?; + write!(w, "{:?}", block.index())?; + write!(w, "
{}
")?; + + Ok(()) + } + + /// Build the verbose row: full MIR data, and detailed gen/kill/entry sets + fn node_label_verbose_row(&self, + n: &Node, + w: &mut W, + block: BasicBlock, + mir: &Mir) + -> io::Result<()> { + let i = n.index(); + + macro_rules! dump_set_for { + ($set:ident) => { + write!(w, "")?; + + let flow = self.mbcx.flow_state(); + let entry_interp = flow.interpret_set(&flow.operator, + flow.sets.$set(i), + &self.render_idx); + for e in &entry_interp { + write!(w, "{:?}
", e)?; + } + write!(w, "")?; + } + } + + write!(w, "")?; + // Entry + dump_set_for!(on_entry_set_for); + + // MIR statements + write!(w, "")?; + { + let data = &mir[block]; + for (i, statement) in data.statements.iter().enumerate() { + write!(w, "{}
", + dot::escape_html(&format!("{:3}: {:?}", i, statement)))?; + } + } + write!(w, "")?; + + // Gen + dump_set_for!(gen_set_for); + + // Kill + dump_set_for!(kill_set_for); + + write!(w, "")?; + + Ok(()) + } + + /// Build the summary row: terminator, gen/kill/entry bit sets + fn node_label_final_row(&self, + n: &Node, + w: &mut W, + block: BasicBlock, + mir: &Mir) + -> io::Result<()> { + let i = n.index(); + + macro_rules! dump_set_for { + ($set:ident) => { + let flow = self.mbcx.flow_state(); + let bits_per_block = flow.sets.bits_per_block(); + let set = flow.sets.$set(i); + write!(w, "{:?}", + dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?; + } + } + + write!(w, "")?; + // Entry + dump_set_for!(on_entry_set_for); + + // Terminator + write!(w, "")?; + { + let data = &mir[block]; + let mut terminator_head = String::new(); + data.terminator().kind.fmt_head(&mut terminator_head).unwrap(); + write!(w, "{}", dot::escape_html(&terminator_head))?; + } + write!(w, "")?; + + // Gen + dump_set_for!(gen_set_for); + + // Kill + dump_set_for!(kill_set_for); + + write!(w, "")?; + + Ok(()) + } } impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P> diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index a150335a1ae4..fb3042014df6 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -63,58 +63,43 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { /// to its borrow-indexes. assigned_map: FxHashMap, FxHashSet>, + /// Locations which activate borrows. + /// NOTE: A given location may activate more than one borrow in the future + /// when more general two-phase borrow support is introduced, but for now we + /// only need to store one borrow index + activation_map: FxHashMap, + /// Every borrow has a region; this maps each such regions back to /// its borrow-indexes. region_map: FxHashMap, FxHashSet>, + + /// Map from local to all the borrows on that local local_map: FxHashMap>, + + /// Maps regions to their corresponding source spans + /// Only contains ReScope()s as keys region_span_map: FxHashMap, + + /// NLL region inference context with which NLL queries should be resolved nonlexical_regioncx: Option>>, } -// Two-phase borrows actually requires two flow analyses; they need -// to be separate because the final results of the first are used to -// construct the gen+kill sets for the second. (The dataflow system -// is not designed to allow the gen/kill sets to change during the -// fixed-point iteration.) - -/// The `Reservations` analysis is the first of the two flow analyses -/// tracking (phased) borrows. It computes where a borrow is reserved; -/// i.e. where it can reach in the control flow starting from its -/// initial `assigned = &'rgn borrowed` statement, and ending -/// wherever `'rgn` itself ends. -pub(crate) struct Reservations<'a, 'gcx: 'tcx, 'tcx: 'a>(pub(crate) Borrows<'a, 'gcx, 'tcx>); - -/// The `ActiveBorrows` analysis is the second of the two flow -/// analyses tracking (phased) borrows. It computes where any given -/// borrow `&assigned = &'rgn borrowed` is *active*, which starts at -/// the first use of `assigned` after the reservation has started, and -/// ends wherever `'rgn` itself ends. -pub(crate) struct ActiveBorrows<'a, 'gcx: 'tcx, 'tcx: 'a>(pub(crate) Borrows<'a, 'gcx, 'tcx>); - -impl<'a, 'gcx, 'tcx> Reservations<'a, 'gcx, 'tcx> { - pub(crate) fn new(b: Borrows<'a, 'gcx, 'tcx>) -> Self { Reservations(b) } - pub(crate) fn location(&self, idx: ReserveOrActivateIndex) -> &Location { - self.0.location(idx.borrow_index()) - } -} - -impl<'a, 'gcx, 'tcx> ActiveBorrows<'a, 'gcx, 'tcx> { - pub(crate) fn new(r: Reservations<'a, 'gcx, 'tcx>) -> Self { ActiveBorrows(r.0) } - pub(crate) fn location(&self, idx: ReserveOrActivateIndex) -> &Location { - self.0.location(idx.borrow_index()) - } -} - // temporarily allow some dead fields: `kind` and `region` will be // needed by borrowck; `borrowed_place` will probably be a MovePathIndex when // that is extended to include borrowed data paths. #[allow(dead_code)] #[derive(Debug)] pub struct BorrowData<'tcx> { - pub(crate) location: Location, + /// Location where the borrow reservation starts. + /// In many cases, this will be equal to the activation location but not always. + pub(crate) reserve_location: Location, + /// What kind of borrow this is pub(crate) kind: mir::BorrowKind, + /// The region for which this borrow is live pub(crate) region: Region<'tcx>, + /// Place from which we are borrowing pub(crate) borrowed_place: mir::Place<'tcx>, + /// Place to which the borrow was stored pub(crate) assigned_place: mir::Place<'tcx>, } @@ -163,9 +148,11 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { idx_vec: IndexVec::new(), location_map: FxHashMap(), assigned_map: FxHashMap(), + activation_map: FxHashMap(), region_map: FxHashMap(), local_map: FxHashMap(), - region_span_map: FxHashMap() + region_span_map: FxHashMap(), + nonlexical_regioncx: nonlexical_regioncx.clone() }; visitor.visit_mir(mir); return Borrows { tcx: tcx, @@ -175,6 +162,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { root_scope, location_map: visitor.location_map, assigned_map: visitor.assigned_map, + activation_map: visitor.activation_map, region_map: visitor.region_map, local_map: visitor.local_map, region_span_map: visitor.region_span_map, @@ -186,9 +174,11 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { idx_vec: IndexVec>, location_map: FxHashMap, assigned_map: FxHashMap, FxHashSet>, + activation_map: FxHashMap, region_map: FxHashMap, FxHashSet>, local_map: FxHashMap>, region_span_map: FxHashMap, + nonlexical_regioncx: Option>>, } impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { @@ -208,14 +198,25 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue { if is_unsafe_place(self.tcx, self.mir, borrowed_place) { return; } + let activate_location = self.compute_activation_location(location, + &assigned_place, + region, + kind); let borrow = BorrowData { - location, kind, region, + kind, region, + reserve_location: location, borrowed_place: borrowed_place.clone(), assigned_place: assigned_place.clone(), }; let idx = self.idx_vec.push(borrow); self.location_map.insert(location, idx); + // This assert is a good sanity check until more general 2-phase borrow + // support is introduced. See NOTE on the activation_map field for more + assert!(!self.activation_map.contains_key(&activate_location), + "More than one activation introduced at the same location."); + self.activation_map.insert(activate_location, idx); + insert(&mut self.assigned_map, assigned_place, idx); insert(&mut self.region_map, ®ion, idx); if let Some(local) = root_local(borrowed_place) { @@ -245,7 +246,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { let mut found_it = false; for idx in &self.region_map[region] { let bd = &self.idx_vec[*idx]; - if bd.location == location && + if bd.reserve_location == location && bd.kind == kind && bd.region == region && bd.borrowed_place == *place @@ -270,6 +271,231 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { return self.super_statement(block, statement, location); } } + + /// A MIR visitor that determines if a specific place is used in a two-phase activating + /// manner in a given chunk of MIR. + struct ContainsUseOfPlace<'b, 'tcx: 'b> { + target: &'b Place<'tcx>, + use_found: bool, + } + + impl<'b, 'tcx: 'b> ContainsUseOfPlace<'b, 'tcx> { + fn new(place: &'b Place<'tcx>) -> Self { + Self { target: place, use_found: false } + } + + /// return whether `context` should be considered a "use" of a + /// place found in that context. "Uses" activate associated + /// borrows (at least when such uses occur while the borrow also + /// has a reservation at the time). + fn is_potential_use(context: PlaceContext) -> bool { + match context { + // storage effects on a place do not activate it + PlaceContext::StorageLive | PlaceContext::StorageDead => false, + + // validation effects do not activate a place + // + // FIXME: Should they? Is it just another read? Or can we + // guarantee it won't dereference the stored address? How + // "deep" does validation go? + PlaceContext::Validate => false, + + // FIXME: This is here to not change behaviour from before + // AsmOutput existed, but it's not necessarily a pure overwrite. + // so it's possible this should activate the place. + PlaceContext::AsmOutput | + // pure overwrites of a place do not activate it. (note + // PlaceContext::Call is solely about dest place) + PlaceContext::Store | PlaceContext::Call => false, + + // reads of a place *do* activate it + PlaceContext::Move | + PlaceContext::Copy | + PlaceContext::Drop | + PlaceContext::Inspect | + PlaceContext::Borrow { .. } | + PlaceContext::Projection(..) => true, + } + } + } + + impl<'b, 'tcx: 'b> Visitor<'tcx> for ContainsUseOfPlace<'b, 'tcx> { + fn visit_place(&mut self, + place: &mir::Place<'tcx>, + context: PlaceContext<'tcx>, + location: Location) { + if Self::is_potential_use(context) && place == self.target { + self.use_found = true; + return; + // There is no need to keep checking the statement, we already found a use + } + + self.super_place(place, context, location); + } + } + + impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> { + /// Returns true if the borrow represented by `kind` is + /// allowed to be split into separate Reservation and + /// Activation phases. + fn allow_two_phase_borrow(&self, kind: mir::BorrowKind) -> bool { + self.tcx.two_phase_borrows() && + (kind.allows_two_phase_borrow() || + self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref) + } + + /// Returns true if the given location contains an NLL-activating use of the given place + fn location_contains_use(&self, location: Location, place: &Place) -> bool { + let mut use_checker = ContainsUseOfPlace::new(place); + let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { + panic!("could not find block at location {:?}", location); + }); + if location.statement_index != block.statements.len() { + // This is a statement + let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| { + panic!("could not find statement at location {:?}"); + }); + use_checker.visit_statement(location.block, stmt, location); + } else { + // This is a terminator + match block.terminator { + Some(ref term) => { + use_checker.visit_terminator(location.block, term, location); + } + None => { + // There is no way for Place to be used by the terminator if there is no + // terminator + } + } + } + + use_checker.use_found + } + + /// Determines if the provided region is terminated after the provided location. + /// EndRegion statements terminate their enclosed region::Scope. + /// We also consult with the NLL region inference engine, should one be available + fn region_terminated_after(&self, region: Region<'tcx>, location: Location) -> bool { + let block_data = &self.mir[location.block]; + if location.statement_index != block_data.statements.len() { + let stmt = &block_data.statements[location.statement_index]; + if let mir::StatementKind::EndRegion(region_scope) = stmt.kind { + if &ReScope(region_scope) == region { + // We encountered an EndRegion statement that terminates the provided + // region + return true; + } + } + } + if let Some(ref regioncx) = self.nonlexical_regioncx { + if !regioncx.region_contains_point(region, location) { + // NLL says the region has ended already + return true; + } + } + + false + } + + /// Computes the activation location of a borrow. + /// The general idea is to start at the beginning of the region and perform a DFS + /// until we exit the region, either via an explicit EndRegion or because NLL tells + /// us so. If we find more than one valid activation point, we currently panic the + /// compiler since two-phase borrows are only currently supported for compiler- + /// generated code. More precisely, we only allow two-phase borrows for: + /// - Function calls (fn some_func(&mut self, ....)) + /// - *Assign operators (a += b -> fn add_assign(&mut self, other: Self)) + /// See + /// - https://github.com/rust-lang/rust/issues/48431 + /// for detailed design notes. + /// See the FIXME in the body of the function for notes on extending support to more + /// general two-phased borrows. + fn compute_activation_location(&self, + start_location: Location, + assigned_place: &mir::Place<'tcx>, + region: Region<'tcx>, + kind: mir::BorrowKind) -> Location { + debug!("Borrows::compute_activation_location({:?}, {:?}, {:?})", + start_location, + assigned_place, + region); + if !self.allow_two_phase_borrow(kind) { + debug!(" -> {:?}", start_location); + return start_location; + } + + // Perform the DFS. + // `stack` is the stack of locations still under consideration + // `visited` is the set of points we have already visited + // `found_use` is an Option that becomes Some when we find a use + let mut stack = vec![start_location]; + let mut visited = FxHashSet(); + let mut found_use = None; + while let Some(curr_loc) = stack.pop() { + let block_data = &self.mir.basic_blocks() + .get(curr_loc.block) + .unwrap_or_else(|| { + panic!("could not find block at location {:?}", curr_loc); + }); + + if self.region_terminated_after(region, curr_loc) { + // No need to process this statement. + // It's either an EndRegion (and thus couldn't use assigned_place) or not + // contained in the NLL region and thus a use would be invalid + continue; + } + + if !visited.insert(curr_loc) { + debug!(" Already visited {:?}", curr_loc); + continue; + } + + if self.location_contains_use(curr_loc, assigned_place) { + // FIXME: Handle this case a little more gracefully. Perhaps collect + // all uses in a vector, and find the point in the CFG that dominates + // all of them? + // Right now this is sufficient though since there should only be exactly + // one borrow-activating use of the borrow. + assert!(found_use.is_none(), "Found secondary use of place"); + found_use = Some(curr_loc); + } + + // Push the points we should consider next. + if curr_loc.statement_index < block_data.statements.len() { + stack.push(curr_loc.successor_within_block()); + } else { + stack.extend(block_data.terminator().successors().iter().map( + |&basic_block| { + Location { + statement_index: 0, + block: basic_block + } + } + )) + } + } + + let found_use = found_use.expect("Did not find use of two-phase place"); + debug!(" -> {:?}", found_use); + found_use + } + } + } + + /// Returns the span for the "end point" given region. This will + /// return `None` if NLL is enabled, since that concept has no + /// meaning there. Otherwise, return region span if it exists and + /// span for end of the function if it doesn't exist. + pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option { + match self.nonlexical_regioncx { + Some(_) => None, + None => { + match self.region_span_map.get(region) { + Some(span) => Some(self.tcx.sess.codemap().end_point(*span)), + None => Some(self.tcx.sess.codemap().end_point(self.mir.span)) + } + } + } } pub fn borrows(&self) -> &IndexVec> { &self.borrows } @@ -277,22 +503,15 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { pub fn scope_tree(&self) -> &Lrc { &self.scope_tree } pub fn location(&self, idx: BorrowIndex) -> &Location { - &self.borrows[idx].location + &self.borrows[idx].reserve_location } /// Add all borrows to the kill set, if those borrows are out of scope at `location`. - /// - /// `is_activations` tracks whether we are in the Reservations or - /// the ActiveBorrows flow analysis, and does not set the - /// activation kill bits in the former case. (Technically, we - /// could set those kill bits without such a guard, since they are - /// never gen'ed by Reservations in the first place. But it makes - /// the instrumentation and graph renderings nicer to leave - /// activations out when of the Reservations kill sets.) + /// That means either they went out of either a nonlexical scope, if we care about those + /// at the moment, or the location represents a lexical EndRegion fn kill_loans_out_of_scope_at_location(&self, sets: &mut BlockSets, - location: Location, - is_activations: bool) { + location: Location) { if let Some(ref regioncx) = self.nonlexical_regioncx { // NOTE: The state associated with a given `location` // reflects the dataflow on entry to the statement. If it @@ -309,21 +528,62 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { let borrow_region = borrow_data.region.to_region_vid(); if !regioncx.region_contains_point(borrow_region, location) { sets.kill(&ReserveOrActivateIndex::reserved(borrow_index)); - if is_activations { - sets.kill(&ReserveOrActivateIndex::active(borrow_index)); - } + sets.kill(&ReserveOrActivateIndex::active(borrow_index)); } } } } - /// Models statement effect in Reservations and ActiveBorrows flow - /// analyses; `is activations` tells us if we are in the latter - /// case. - fn statement_effect_on_borrows(&self, - sets: &mut BlockSets, - location: Location, - is_activations: bool) { + fn kill_borrows_on_local(&self, + sets: &mut BlockSets, + local: &rustc::mir::Local) + { + if let Some(borrow_indexes) = self.local_map.get(local) { + sets.kill_all(borrow_indexes.iter() + .map(|b| ReserveOrActivateIndex::reserved(*b))); + sets.kill_all(borrow_indexes.iter() + .map(|b| ReserveOrActivateIndex::active(*b))); + } + } + + /// Performs the activations for a given location + fn perform_activations_at_location(&self, + sets: &mut BlockSets, + location: Location) { + // Handle activations + match self.activation_map.get(&location) { + Some(&activated) => { + debug!("activating borrow {:?}", activated); + sets.gen(&ReserveOrActivateIndex::active(activated)) + } + None => {} + } + } +} + +impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { + type Idx = ReserveOrActivateIndex; + fn name() -> &'static str { "borrows" } + fn bits_per_block(&self) -> usize { + self.borrows.len() * 2 + } + + fn start_block_effect(&self, _entry_set: &mut IdxSet) { + // no borrows of code region_scopes have been taken prior to + // function execution, so this method has no effect on + // `_sets`. + } + + fn before_statement_effect(&self, + sets: &mut BlockSets, + location: Location) { + debug!("Borrows::before_statement_effect sets: {:?} location: {:?}", sets, location); + self.kill_loans_out_of_scope_at_location(sets, location); + } + + fn statement_effect(&self, sets: &mut BlockSets, location: Location) { + debug!("Borrows::statement_effect sets: {:?} location: {:?}", sets, location); + let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { panic!("could not find block at location {:?}", location); }); @@ -331,21 +591,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { panic!("could not find statement at location {:?}"); }); - // Do kills introduced by NLL before setting up any potential - // gens. (See NOTE in kill_loans_out_of_scope_at_location.) - self.kill_loans_out_of_scope_at_location(sets, location, is_activations); - - if is_activations { - // INVARIANT: `sets.on_entry` accurately captures - // reservations on entry to statement (b/c - // accumulates_intrablock_state is overridden for - // ActiveBorrows). - // - // Now compute the activations generated by uses within - // the statement based on that reservation state. - let mut find = FindPlaceUses { sets, assigned_map: &self.assigned_map }; - find.visit_statement(location.block, stmt, location); - } + self.perform_activations_at_location(sets, location); + self.kill_loans_out_of_scope_at_location(sets, location); match stmt.kind { // EndRegion kills any borrows (reservations and active borrows both) @@ -354,9 +601,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { assert!(self.nonlexical_regioncx.is_none()); for idx in borrow_indexes { sets.kill(&ReserveOrActivateIndex::reserved(*idx)); - if is_activations { - sets.kill(&ReserveOrActivateIndex::active(*idx)); - } + sets.kill(&ReserveOrActivateIndex::active(*idx)); } } else { // (if there is no entry, then there are no borrows to be tracked) @@ -369,7 +614,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { if let Place::Local(ref local) = *lhs { // FIXME: Handle the case in which we're assigning over // a projection (`foo.bar`). - self.kill_borrows_on_local(sets, local, is_activations); + self.kill_borrows_on_local(sets, local); } // NOTE: if/when the Assign case is revised to inspect @@ -379,32 +624,32 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { if let mir::Rvalue::Ref(region, _, ref place) = *rhs { if is_unsafe_place(self.tcx, self.mir, place) { return; } - if let RegionKind::ReEmpty = region { - // If the borrowed value is dead, the region for it - // can be empty. Don't track the borrow in that case. - return - } - let index = self.location_map.get(&location).unwrap_or_else(|| { panic!("could not find BorrowIndex for location {:?}", location); }); + + if let RegionKind::ReEmpty = region { + // If the borrowed value dies before the borrow is used, the region for + // the borrow can be empty. Don't track the borrow in that case. + sets.kill(&ReserveOrActivateIndex::active(*index)); + return + } + assert!(self.region_map.get(region).unwrap_or_else(|| { panic!("could not find BorrowIndexs for region {:?}", region); }).contains(&index)); sets.gen(&ReserveOrActivateIndex::reserved(*index)); - if is_activations { - // Issue #46746: Two-phase borrows handles - // stmts of form `Tmp = &mut Borrow` ... - match lhs { - Place::Local(..) | Place::Static(..) => {} // okay - Place::Projection(..) => { - // ... can assign into projections, - // e.g. `box (&mut _)`. Current - // conservative solution: force - // immediate activation here. - sets.gen(&ReserveOrActivateIndex::active(*index)); - } + // Issue #46746: Two-phase borrows handles + // stmts of form `Tmp = &mut Borrow` ... + match lhs { + Place::Local(..) | Place::Static(..) => {} // okay + Place::Projection(..) => { + // ... can assign into projections, + // e.g. `box (&mut _)`. Current + // conservative solution: force + // immediate activation here. + sets.gen(&ReserveOrActivateIndex::active(*index)); } } } @@ -413,7 +658,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::StorageDead(local) => { // Make sure there are no remaining borrows for locals that // are gone out of scope. - self.kill_borrows_on_local(sets, &local, is_activations) + self.kill_borrows_on_local(sets, &local) } mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => { @@ -424,7 +669,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { if let Place::Local(ref local) = *output { // FIXME: Handle the case in which we're assigning over // a projection (`foo.bar`). - self.kill_borrows_on_local(sets, local, is_activations); + self.kill_borrows_on_local(sets, local); } } } @@ -433,53 +678,30 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) | mir::StatementKind::Validate(..) | + mir::StatementKind::UserAssertTy(..) | mir::StatementKind::Nop => {} } } - fn kill_borrows_on_local(&self, - sets: &mut BlockSets, - local: &rustc::mir::Local, - is_activations: bool) - { - if let Some(borrow_indexes) = self.local_map.get(local) { - sets.kill_all(borrow_indexes.iter() - .map(|b| ReserveOrActivateIndex::reserved(*b))); - if is_activations { - sets.kill_all(borrow_indexes.iter() - .map(|b| ReserveOrActivateIndex::active(*b))); - } - } + fn before_terminator_effect(&self, + sets: &mut BlockSets, + location: Location) { + debug!("Borrows::before_terminator_effect sets: {:?} location: {:?}", sets, location); + self.kill_loans_out_of_scope_at_location(sets, location); } - /// Models terminator effect in Reservations and ActiveBorrows - /// flow analyses; `is activations` tells us if we are in the - /// latter case. - fn terminator_effect_on_borrows(&self, - sets: &mut BlockSets, - location: Location, - is_activations: bool) { + fn terminator_effect(&self, sets: &mut BlockSets, location: Location) { + debug!("Borrows::terminator_effect sets: {:?} location: {:?}", sets, location); + let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { panic!("could not find block at location {:?}", location); }); - // Do kills introduced by NLL before setting up any potential - // gens. (See NOTE in kill_loans_out_of_scope_at_location.) - self.kill_loans_out_of_scope_at_location(sets, location, is_activations); - let term = block.terminator(); - if is_activations { - // INVARIANT: `sets.on_entry` accurately captures - // reservations on entry to terminator (b/c - // accumulates_intrablock_state is overridden for - // ActiveBorrows). - // - // Now compute effect of the terminator on the activations - // themselves in the ActiveBorrows state. - let mut find = FindPlaceUses { sets, assigned_map: &self.assigned_map }; - find.visit_terminator(location.block, term, location); - } + self.perform_activations_at_location(sets, location); + self.kill_loans_out_of_scope_at_location(sets, location); + match term.kind { mir::TerminatorKind::Resume | @@ -501,9 +723,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { self.scope_tree.is_subscope_of(*scope, root_scope) { sets.kill(&ReserveOrActivateIndex::reserved(borrow_index)); - if is_activations { - sets.kill(&ReserveOrActivateIndex::active(borrow_index)); - } + sets.kill(&ReserveOrActivateIndex::active(borrow_index)); } } } @@ -522,161 +742,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { mir::TerminatorKind::Unreachable => {} } } -} - -impl<'a, 'gcx, 'tcx> ActiveBorrows<'a, 'gcx, 'tcx> { - pub(crate) fn borrows(&self) -> &IndexVec> { - self.0.borrows() - } - - /// Returns the span for the "end point" given region. This will - /// return `None` if NLL is enabled, since that concept has no - /// meaning there. Otherwise, return region span if it exists and - /// span for end of the function if it doesn't exist. - pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option { - match self.0.nonlexical_regioncx { - Some(_) => None, - None => { - match self.0.region_span_map.get(region) { - Some(span) => Some(self.0.tcx.sess.codemap().end_point(*span)), - None => Some(self.0.tcx.sess.codemap().end_point(self.0.mir.span)) - } - } - } - } -} - -/// `FindPlaceUses` is a MIR visitor that updates `self.sets` for all -/// of the borrows activated by a given statement or terminator. -/// -/// ---- -/// -/// The `ActiveBorrows` flow analysis, when inspecting any given -/// statement or terminator, needs to "generate" (i.e. set to 1) all -/// of the bits for the borrows that are activated by that -/// statement/terminator. -/// -/// This struct will seek out all places that are assignment-targets -/// for borrows (gathered in `self.assigned_map`; see also the -/// `assigned_map` in `struct Borrows`), and set the corresponding -/// gen-bits for activations of those borrows in `self.sets` -struct FindPlaceUses<'a, 'b: 'a, 'tcx: 'a> { - assigned_map: &'a FxHashMap, FxHashSet>, - sets: &'a mut BlockSets<'b, ReserveOrActivateIndex>, -} - -impl<'a, 'b, 'tcx> FindPlaceUses<'a, 'b, 'tcx> { - fn has_been_reserved(&self, b: &BorrowIndex) -> bool { - self.sets.on_entry.contains(&ReserveOrActivateIndex::reserved(*b)) - } - - /// return whether `context` should be considered a "use" of a - /// place found in that context. "Uses" activate associated - /// borrows (at least when such uses occur while the borrow also - /// has a reservation at the time). - fn is_potential_use(context: PlaceContext) -> bool { - match context { - // storage effects on a place do not activate it - PlaceContext::StorageLive | PlaceContext::StorageDead => false, - - // validation effects do not activate a place - // - // FIXME: Should they? Is it just another read? Or can we - // guarantee it won't dereference the stored address? How - // "deep" does validation go? - PlaceContext::Validate => false, - - // FIXME: This is here to not change behaviour from before - // AsmOutput existed, but it's not necessarily a pure overwrite. - // so it's possible this should activate the place. - PlaceContext::AsmOutput | - // pure overwrites of a place do not activate it. (note - // PlaceContext::Call is solely about dest place) - PlaceContext::Store | PlaceContext::Call => false, - - // reads of a place *do* activate it - PlaceContext::Move | - PlaceContext::Copy | - PlaceContext::Drop | - PlaceContext::Inspect | - PlaceContext::Borrow { .. } | - PlaceContext::Projection(..) => true, - } - } -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for FindPlaceUses<'a, 'b, 'tcx> { - fn visit_place(&mut self, - place: &mir::Place<'tcx>, - context: PlaceContext<'tcx>, - location: Location) { - debug!("FindPlaceUses place: {:?} assigned from borrows: {:?} \ - used in context: {:?} at location: {:?}", - place, self.assigned_map.get(place), context, location); - if Self::is_potential_use(context) { - if let Some(borrows) = self.assigned_map.get(place) { - for borrow_idx in borrows { - debug!("checking if index {:?} for {:?} is reserved ({}) \ - and thus needs active gen-bit set in sets {:?}", - borrow_idx, place, self.has_been_reserved(&borrow_idx), self.sets); - if self.has_been_reserved(&borrow_idx) { - self.sets.gen(&ReserveOrActivateIndex::active(*borrow_idx)); - } else { - // (This can certainly happen in valid code. I - // just want to know about it in the short - // term.) - debug!("encountered use of Place {:?} of borrow_idx {:?} \ - at location {:?} outside of reservation", - place, borrow_idx, location); - } - } - } - } - - self.super_place(place, context, location); - } -} - - -impl<'a, 'gcx, 'tcx> BitDenotation for Reservations<'a, 'gcx, 'tcx> { - type Idx = ReserveOrActivateIndex; - fn name() -> &'static str { "reservations" } - fn bits_per_block(&self) -> usize { - self.0.borrows.len() * 2 - } - fn start_block_effect(&self, _entry_set: &mut IdxSet) { - // no borrows of code region_scopes have been taken prior to - // function execution, so this method has no effect on - // `_sets`. - } - - fn before_statement_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("Reservations::before_statement_effect sets: {:?} location: {:?}", sets, location); - self.0.kill_loans_out_of_scope_at_location(sets, location, false); - } - - fn statement_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("Reservations::statement_effect sets: {:?} location: {:?}", sets, location); - self.0.statement_effect_on_borrows(sets, location, false); - } - - fn before_terminator_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("Reservations::before_terminator_effect sets: {:?} location: {:?}", sets, location); - self.0.kill_loans_out_of_scope_at_location(sets, location, false); - } - - fn terminator_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("Reservations::terminator_effect sets: {:?} location: {:?}", sets, location); - self.0.terminator_effect_on_borrows(sets, location, false); - } fn propagate_call_return(&self, _in_out: &mut IdxSet, @@ -691,85 +756,17 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Reservations<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> BitDenotation for ActiveBorrows<'a, 'gcx, 'tcx> { - type Idx = ReserveOrActivateIndex; - fn name() -> &'static str { "active_borrows" } - - /// Overriding this method; `ActiveBorrows` uses the intrablock - /// state in `on_entry` to track the current reservations (which - /// then affect the construction of the gen/kill sets for - /// activations). - fn accumulates_intrablock_state() -> bool { true } - - fn bits_per_block(&self) -> usize { - self.0.borrows.len() * 2 - } - - fn start_block_effect(&self, _entry_sets: &mut IdxSet) { - // no borrows of code region_scopes have been taken prior to - // function execution, so this method has no effect on - // `_sets`. - } - - fn before_statement_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("ActiveBorrows::before_statement_effect sets: {:?} location: {:?}", sets, location); - self.0.kill_loans_out_of_scope_at_location(sets, location, true); - } - - fn statement_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("ActiveBorrows::statement_effect sets: {:?} location: {:?}", sets, location); - self.0.statement_effect_on_borrows(sets, location, true); - } - - fn before_terminator_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("ActiveBorrows::before_terminator_effect sets: {:?} location: {:?}", sets, location); - self.0.kill_loans_out_of_scope_at_location(sets, location, true); - } - - fn terminator_effect(&self, - sets: &mut BlockSets, - location: Location) { - debug!("ActiveBorrows::terminator_effect sets: {:?} location: {:?}", sets, location); - self.0.terminator_effect_on_borrows(sets, location, true); - } - - fn propagate_call_return(&self, - _in_out: &mut IdxSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place) { - // there are no effects on borrows from method call return... - // - // ... but If overwriting a place can affect flow state, then - // latter is not true; see NOTE on Assign case in - // statement_effect_on_borrows. - } -} - -impl<'a, 'gcx, 'tcx> BitwiseOperator for Reservations<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { pred1 | pred2 // union effects of preds when computing reservations } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for ActiveBorrows<'a, 'gcx, 'tcx> { - #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { - pred1 | pred2 // union effects of preds when computing activations - } -} - -impl<'a, 'gcx, 'tcx> InitialFlow for Reservations<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> InitialFlow for Borrows<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { - false // bottom = no Rvalue::Refs are reserved by default + false // bottom = nothing is reserved or activated yet } } diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index c5f5492cd2c2..287640439c0e 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> // sets on_entry bits for Arg places fn start_block_effect(&self, entry_set: &mut IdxSet) { // set all bits to 1 (uninit) before gathering counterevidence - for e in entry_set.words_mut() { *e = !0; } + entry_set.set_up_to(self.bits_per_block()); drop_flag_effects_for_function_entry( self.tcx, self.mir, self.mdpe, @@ -443,7 +443,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc // sets on_entry bits for Arg places fn start_block_effect(&self, entry_set: &mut IdxSet) { - for e in entry_set.words_mut() { *e = 0; } + entry_set.clear(); drop_flag_effects_for_function_entry( self.tcx, self.mir, self.mdpe, diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index aa7bb6f97786..74e41ef9c93e 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -18,7 +18,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; use rustc::session::Session; -use std::borrow::{Borrow, Cow}; +use std::borrow::Borrow; use std::fmt; use std::io; use std::mem; @@ -31,7 +31,7 @@ pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; pub use self::impls::EverInitializedPlaces; pub use self::impls::borrows::{Borrows, BorrowData}; pub use self::impls::HaveBeenBorrowedLocals; -pub(crate) use self::impls::borrows::{ActiveBorrows, Reservations, ReserveOrActivateIndex}; +pub(crate) use self::impls::borrows::{ReserveOrActivateIndex}; pub use self::at_location::{FlowAtLocation, FlowsAtLocation}; pub(crate) use self::drop_flag_effects::*; @@ -444,8 +444,7 @@ pub struct DataflowState impl DataflowState { pub fn each_bit(&self, words: &IdxSet, f: F) where F: FnMut(O::Idx) { - let bits_per_block = self.operator.bits_per_block(); - words.each_bit(bits_per_block, f) + words.iter().for_each(f) } pub(crate) fn interpret_set<'c, P>(&self, @@ -584,9 +583,6 @@ impl AllSets { pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet { self.lookup_set_for(&self.on_entry_sets, block_idx) } - pub(crate) fn entry_set_state(&self) -> &Bits { - &self.on_entry_sets - } } /// Parameterization for the precise form of data flow that is used. @@ -739,27 +735,17 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation dead_unwinds: &'a IdxSet, denotation: D) -> Self where D: InitialFlow { let bits_per_block = denotation.bits_per_block(); + let usize_bits = mem::size_of::() * 8; + let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; let num_overall = Self::num_bits_overall(mir, bits_per_block); + + let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall)); let on_entry = Bits::new(if D::bottom_value() { IdxSetBuf::new_filled(num_overall) } else { IdxSetBuf::new_empty(num_overall) }); - Self::new_with_entry_sets(mir, dead_unwinds, Cow::Owned(on_entry), denotation) - } - - pub(crate) fn new_with_entry_sets(mir: &'a Mir<'tcx>, - dead_unwinds: &'a IdxSet, - on_entry: Cow>, - denotation: D) - -> Self { - let bits_per_block = denotation.bits_per_block(); - let usize_bits = mem::size_of::() * 8; - let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; - let num_overall = Self::num_bits_overall(mir, bits_per_block); - assert_eq!(num_overall, on_entry.bits.words().len() * usize_bits); - let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall)); DataflowAnalysis { mir, dead_unwinds, @@ -769,13 +755,27 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation words_per_block, gen_sets: zeroes.clone(), kill_sets: zeroes, - on_entry_sets: on_entry.into_owned(), + on_entry_sets: on_entry, }, operator: denotation, } } } + pub fn new_from_sets(mir: &'a Mir<'tcx>, + dead_unwinds: &'a IdxSet, + sets: AllSets, + denotation: D) -> Self { + DataflowAnalysis { + mir, + dead_unwinds, + flow_state: DataflowState { + sets: sets, + operator: denotation, + } + } + } + fn num_bits_overall(mir: &Mir, bits_per_block: usize) -> usize { let usize_bits = mem::size_of::() * 8; let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index d6f419f6cfb4..cbf4c822769c 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -298,6 +298,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { } StatementKind::EndRegion(_) | StatementKind::Validate(..) | + StatementKind::UserAssertTy(..) | StatementKind::Nop => {} } } diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 7b6ebc6fba87..9f6cf8c036e1 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -29,17 +29,17 @@ mod abs_domain; // (which is likely to yield a subtle off-by-one error). pub(crate) mod indexes { use std::fmt; - use core::nonzero::NonZero; + use std::num::NonZeroUsize; use rustc_data_structures::indexed_vec::Idx; macro_rules! new_index { ($Index:ident, $debug_name:expr) => { #[derive(Copy, Clone, PartialEq, Eq, Hash)] - pub struct $Index(NonZero); + pub struct $Index(NonZeroUsize); impl Idx for $Index { fn new(idx: usize) -> Self { - $Index(NonZero::new(idx + 1).unwrap()) + $Index(NonZeroUsize::new(idx + 1).unwrap()) } fn index(self) -> usize { self.0.get() - 1 diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 2000ebea25d7..4f36c3888b96 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -2247,7 +2247,7 @@ let mut b = || { yield (); // ...is still in scope here, when the yield occurs. println!("{}", a); }; -b.resume(); +unsafe { b.resume() }; ``` At present, it is not permitted to have a yield that occurs while a @@ -2265,7 +2265,7 @@ let mut b = || { yield (); println!("{}", a); }; -b.resume(); +unsafe { b.resume() }; ``` This is a very simple case, of course. In more complex cases, we may @@ -2283,7 +2283,7 @@ let mut b = || { yield x; // ...when this yield occurs. } }; -b.resume(); +unsafe { b.resume() }; ``` Such cases can sometimes be resolved by iterating "by value" (or using @@ -2298,7 +2298,7 @@ let mut b = || { yield x; // <-- Now yield is OK. } }; -b.resume(); +unsafe { b.resume() }; ``` If taking ownership is not an option, using indices can work too: @@ -2314,7 +2314,7 @@ let mut b = || { yield x; // <-- Now yield is OK. } }; -b.resume(); +unsafe { b.resume() }; // (*) -- Unfortunately, these temporaries are currently required. // See . diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 6f6258f52f79..14aa307f0ae1 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -76,12 +76,14 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, first_statement_index: region::FirstStatementIndex::new(index), }); + let ty = local.ty.clone().map(|ty| ty.hir_id); let pattern = cx.pattern_from_hir(&local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { remainder_scope: remainder_scope, init_scope: region::Scope::Node(hir_id.local_id), pattern, + ty, initializer: local.init.to_ref(), lint_level: cx.lint_level_of(local.id), }, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index da25969bf117..5b3739084801 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -227,7 +227,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e)); let tupled_args = Expr { - ty: cx.tcx.mk_tup(arg_tys, false), + ty: cx.tcx.mk_tup(arg_tys), temp_lifetime, span: expr.span, kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() }, @@ -662,9 +662,13 @@ trait ToBorrowKind { fn to_borrow_kind(&self) -> BorrowKind; } impl ToBorrowKind for AutoBorrowMutability { fn to_borrow_kind(&self) -> BorrowKind { + use rustc::ty::adjustment::AllowTwoPhase; match *self { AutoBorrowMutability::Mutable { allow_two_phase_borrow } => - BorrowKind::Mut { allow_two_phase_borrow }, + BorrowKind::Mut { allow_two_phase_borrow: match allow_two_phase_borrow { + AllowTwoPhase::Yes => true, + AllowTwoPhase::No => false + }}, AutoBorrowMutability::Immutable => BorrowKind::Shared, } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 5f60a134fb13..fe82b8158f76 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -93,10 +93,13 @@ pub enum StmtKind<'tcx> { /// lifetime of temporaries init_scope: region::Scope, - /// let = ... + /// let : ty = ... pattern: Pattern<'tcx>, - /// let pat = ... + /// let pat: = init ... + ty: Option, + + /// let pat: ty = ... initializer: Option>, /// the lint level for this let-statement diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index a3295aac8015..6f8b1f8e7994 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -219,7 +219,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { - if self.tcx.features().never_type { + if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(self.module, ty) } else { false @@ -245,7 +245,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { substs: &'tcx ty::subst::Substs<'tcx>) -> bool { - if self.tcx.features().never_type { + if self.tcx.features().exhaustive_patterns { self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs) } else { false @@ -694,7 +694,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, // test for details. // // FIXME: currently the only way I know of something can - // be a privately-empty enum is when the never_type + // be a privately-empty enum is when the exhaustive_patterns // feature flag is not present, so this is only // needed for that case. @@ -877,7 +877,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt, fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 { debug!("constructor_arity({:#?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs, _) => fs.len() as u64, + ty::TyTuple(ref fs) => fs.len() as u64, ty::TySlice(..) | ty::TyArray(..) => match *ctor { Slice(length) => length, ConstantValue(_) => 0, @@ -901,7 +901,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, { debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(), + ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(), ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor { Slice(length) => (0..length).map(|_| ty).collect(), ConstantValue(_) => vec![], diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 69ed4e6064fc..d924baaf0052 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -222,7 +222,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let pat_ty = self.tables.node_id_to_type(scrut.hir_id); let module = self.tcx.hir.get_module_parent(scrut.id); if inlined_arms.is_empty() { - let scrutinee_is_uninhabited = if self.tcx.features().never_type { + let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { self.conservative_is_uninhabited(pat_ty) diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 1774c95af0f0..798d63531818 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -449,7 +449,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::Tuple(ref subpatterns, ddpos) => { let ty = self.tables.node_id_to_type(pat.hir_id); match ty.sty { - ty::TyTuple(ref tys, _) => { + ty::TyTuple(ref tys) => { let subpatterns = subpatterns.iter() .enumerate_and_adjust(tys.len(), ddpos) @@ -851,13 +851,38 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::TyAdt(adt_def, substs) if adt_def.is_enum() => { match cv.val { ConstVal::Value(val) => { - let discr = const_discr( + let discr_val = const_discr( self.tcx, self.param_env, instance, val, cv.ty - ).unwrap(); - let variant_index = adt_def - .discriminants(self.tcx) - .position(|var| var.val == discr) - .unwrap(); + ).expect("const_discr failed"); + let layout = self + .tcx + .layout_of(self.param_env.and(cv.ty)) + .expect("layout of enum not available"); + let variant_index = match layout.variants { + ty::layout::Variants::Single { index } => index, + ty::layout::Variants::Tagged { ref discr, .. } => { + // raw discriminants for enums are isize or bigger during + // their computation, but later shrunk to the smallest possible + // representation + let size = discr.value.size(self.tcx).bits(); + let amt = 128 - size; + adt_def + .discriminants(self.tcx) + .position(|var| ((var.val << amt) >> amt) == discr_val) + .unwrap_or_else(|| { + bug!("discriminant {} not found in {:#?}", + discr_val, + adt_def + .discriminants(self.tcx) + .collect::>(), + ); + }) + } + ty::layout::Variants::NicheFilling { .. } => { + assert_eq!(discr_val as usize as u128, discr_val); + discr_val as usize + }, + }; let subpatterns = adt_subpatterns( adt_def.variants[variant_index].fields.len(), Some(variant_index), @@ -879,7 +904,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { subpatterns: adt_subpatterns(struct_var.fields.len(), None), } } - ty::TyTuple(fields, _) => { + ty::TyTuple(fields) => { PatternKind::Leaf { subpatterns: adt_subpatterns(fields.len(), None), } diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index ee5874be9d70..57977b6201a6 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -5,6 +5,7 @@ use rustc::mir; use rustc::ty::{self, TyCtxt, Ty, Instance}; use rustc::ty::layout::{self, LayoutOf}; use rustc::ty::subst::Subst; +use rustc::util::nodemap::FxHashSet; use syntax::ast::Mutability; use syntax::codemap::Span; @@ -14,7 +15,7 @@ use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory}; use std::fmt; use std::error::Error; -use std::rc::Rc; +use rustc_data_structures::sync::Lrc; pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -110,6 +111,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>( span = mir.span; let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; let alloc = tcx.interpret_interner.get_cached(cid.instance.def_id()); + let is_static = tcx.is_static(cid.instance.def_id()).is_some(); let alloc = match alloc { Some(alloc) => { assert!(cid.promoted.is_none()); @@ -123,7 +125,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>( layout.align, None, )?; - if tcx.is_static(cid.instance.def_id()).is_some() { + if is_static { tcx.interpret_interner.cache(cid.instance.def_id(), ptr.alloc_id); } let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span); @@ -151,8 +153,11 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>( } }; let ptr = MemoryPointer::new(alloc, 0).into(); + // always try to read the value and report errors let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? { - Some(val) => val, + // if it's a constant (so it needs no address, directly compute its value) + Some(val) if !is_static => val, + // point at the allocation _ => Value::ByRef(ptr, layout.align), }; Ok((value, ptr, layout.ty)) @@ -335,6 +340,14 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator { ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, cid: GlobalId<'tcx>, ) -> EvalResult<'tcx, AllocId> { + let alloc = ecx + .tcx + .interpret_interner + .get_cached(cid.instance.def_id()); + // Don't evaluate when already cached to prevent cycles + if let Some(alloc) = alloc { + return Ok(alloc) + } // ensure the static is computed ecx.const_eval(cid)?; Ok(ecx @@ -473,7 +486,7 @@ pub fn const_eval_provider<'a, 'tcx>( // Do match-check before building MIR if tcx.check_match(def_id).is_err() { return Err(ConstEvalErr { - kind: Rc::new(CheckMatchError), + kind: Lrc::new(CheckMatchError), span, }); } @@ -485,14 +498,20 @@ pub fn const_eval_provider<'a, 'tcx>( // Do not continue into miri if typeck errors occurred; it will fail horribly if tables.tainted_by_errors { return Err(ConstEvalErr { - kind: Rc::new(TypeckError), + kind: Lrc::new(TypeckError), span, }); } }; let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env); - res.map(|(miri_value, _, miri_ty)| { + res.map(|(miri_value, ptr, miri_ty)| { + if tcx.is_static(def_id).is_some() { + if let Ok(ptr) = ptr.primval.to_ptr() { + let mut seen = FxHashSet::default(); + create_depgraph_edges(tcx, ptr.alloc_id, &mut seen); + } + } tcx.mk_const(ty::Const { val: ConstVal::Value(miri_value), ty: miri_ty, @@ -509,3 +528,35 @@ pub fn const_eval_provider<'a, 'tcx>( } }) } + +// This function creates dep graph edges from statics to all referred to statics. +// This is necessary, because the `const_eval` query cannot directly call itself +// for other statics, because we cannot prevent recursion in queries. +// +// see test/incremental/static_refering_to_other_static2/issue.rs for an example +// where not creating those edges would cause static A, which refers to static B +// to point to the old allocation of static B, even though B has changed. +// +// In the future we will want to remove this funcion in favour of a system that +// makes sure that statics don't need to have edges to other statics as long as +// they are only referring by reference and not inspecting the other static's body. +fn create_depgraph_edges<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + alloc_id: AllocId, + seen: &mut FxHashSet, +) { + trace!("create_depgraph_edges: {:?}, {:?}", alloc_id, seen); + if seen.insert(alloc_id) { + trace!("seen: {:?}, {:?}", alloc_id, seen); + if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) { + trace!("get_alloc: {:?}, {:?}, {:?}", alloc_id, seen, alloc); + for (_, &reloc) in &alloc.relocations { + if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(reloc) { + trace!("get_corresponding: {:?}, {:?}, {:?}, {:?}, {:?}", alloc_id, seen, alloc, did, reloc); + let _ = tcx.maybe_optimized_mir(did); + } + create_depgraph_edges(tcx, reloc, seen); + } + } + } +} diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 13090ca53302..cf3241fe9be6 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1,7 +1,7 @@ -use std::collections::HashSet; use std::fmt::Write; use rustc::hir::def_id::DefId; +use rustc::hir::def::Def; use rustc::hir::map::definitions::DefPathData; use rustc::middle::const_val::{ConstVal, ErrKind}; use rustc::mir; @@ -9,7 +9,7 @@ use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::TyCtxtAt; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::middle::const_val::FrameInfo; use syntax::codemap::{self, Span}; use syntax::ast::Mutability; @@ -17,6 +17,7 @@ use rustc::mir::interpret::{ GlobalId, Value, Pointer, PrimVal, PrimValKind, EvalError, EvalResult, EvalErrorKind, MemoryPointer, }; +use std::mem; use super::{Place, PlaceExtra, Memory, HasMemory, MemoryKind, @@ -71,12 +72,12 @@ pub struct Frame<'mir, 'tcx: 'mir> { pub return_place: Place, /// The list of locals for this stack frame, stored in order as - /// `[arguments..., variables..., temporaries...]`. The locals are stored as `Option`s. + /// `[return_ptr, arguments..., variables..., temporaries...]`. The locals are stored as `Option`s. /// `None` represents a local that is currently dead, while a live local /// can either directly contain `PrimVal` or refer to some part of an `Allocation`. /// /// Before being initialized, arguments are `Value::ByVal(PrimVal::Undef)` and other locals are `None`. - pub locals: Vec>, + pub locals: IndexVec>, //////////////////////////////////////////////////////////////////////////////// // Current position within the function @@ -249,7 +250,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M trace!("resolve: {:?}, {:#?}", def_id, substs); trace!("substs: {:#?}", self.substs()); trace!("param_env: {:#?}", self.param_env); - let substs = self.tcx.trans_apply_param_substs_env(self.substs(), self.param_env, &substs); + let substs = self.tcx.subst_and_normalize_erasing_regions( + self.substs(), + self.param_env, + &substs, + ); ty::Instance::resolve( *self.tcx, self.param_env, @@ -285,10 +290,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub fn monomorphize(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { // miri doesn't care about lifetimes, and will choke on some crazy ones // let's simply get rid of them - let without_lifetimes = self.tcx.erase_regions(&ty); - let substituted = without_lifetimes.subst(*self.tcx, substs); - let substituted = self.tcx.fully_normalize_monormophic_ty(&substituted); - substituted + let substituted = ty.subst(*self.tcx, substs); + self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted) } /// Return the size and aligment of the value at the given type. @@ -381,39 +384,29 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M ) -> EvalResult<'tcx> { ::log_settings::settings().indentation += 1; - /// Return the set of locals that have a storage annotation anywhere - fn collect_storage_annotations<'mir, 'tcx>(mir: &'mir mir::Mir<'tcx>) -> HashSet { - use rustc::mir::StatementKind::*; - - let mut set = HashSet::new(); - for block in mir.basic_blocks() { - for stmt in block.statements.iter() { - match stmt.kind { - StorageLive(local) | - StorageDead(local) => { - set.insert(local); + let locals = if mir.local_decls.len() > 1 { + let mut locals = IndexVec::from_elem(Some(Value::ByVal(PrimVal::Undef)), &mir.local_decls); + match self.tcx.describe_def(instance.def_id()) { + // statics and constants don't have `Storage*` statements, no need to look for them + Some(Def::Static(..)) | Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}, + _ => { + trace!("push_stack_frame: {:?}: num_bbs: {}", span, mir.basic_blocks().len()); + for block in mir.basic_blocks() { + for stmt in block.statements.iter() { + use rustc::mir::StatementKind::{StorageDead, StorageLive}; + match stmt.kind { + StorageLive(local) | + StorageDead(local) => locals[local] = None, + _ => {} + } } - _ => {} } - } - } - set - } - - // Subtract 1 because `local_decls` includes the ReturnMemoryPointer, but we don't store a local - // `Value` for that. - let num_locals = mir.local_decls.len() - 1; - - let locals = { - let annotated_locals = collect_storage_annotations(mir); - let mut locals = vec![None; num_locals]; - for i in 0..num_locals { - let local = mir::Local::new(i + 1); - if !annotated_locals.contains(&local) { - locals[i] = Some(Value::ByVal(PrimVal::Undef)); - } + }, } locals + } else { + // don't allocate at all for trivial constants + IndexVec::new() }; self.stack.push(Frame { @@ -724,7 +717,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M ClosureFnPointer => { match self.eval_operand(operand)?.ty.sty { ty::TyClosure(def_id, substs) => { - let substs = self.tcx.trans_apply_param_substs(self.substs(), &substs); + let substs = self.tcx.subst_and_normalize_erasing_regions( + self.substs(), + ty::ParamEnv::reveal_all(), + &substs, + ); let instance = ty::Instance::resolve_closure( *self.tcx, def_id, @@ -746,20 +743,29 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M Discriminant(ref place) => { let ty = self.place_ty(place); + let layout = self.layout_of(ty)?; let place = self.eval_place(place)?; let discr_val = self.read_discriminant_value(place, ty)?; - if let ty::TyAdt(adt_def, _) = ty.sty { - trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::>()); - if adt_def.discriminants(*self.tcx).all(|v| { - discr_val != v.val - }) - { - return err!(InvalidDiscriminant); + match layout.variants { + layout::Variants::Single { index } => { + assert_eq!(discr_val, index as u128); + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => { + if let ty::TyAdt(adt_def, _) = ty.sty { + trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::>()); + if adt_def.discriminants(*self.tcx).all(|v| { + discr_val != v.val + }) + { + return err!(InvalidDiscriminant); + } + } else { + bug!("rustc only generates Rvalue::Discriminant for enums"); + } } - self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; - } else { - bug!("rustc only generates Rvalue::Discriminant for enums"); } + self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } } @@ -949,8 +955,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { let param_env = if self.tcx.is_static(gid.instance.def_id()).is_some() { - use rustc::traits; - ty::ParamEnv::empty(traits::Reveal::All) + ty::ParamEnv::reveal_all() } else { self.param_env }; @@ -968,8 +973,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> { let new_place = match place { Place::Local { frame, local } => { - // -1 since we don't store the return value - match self.stack[frame].locals[local.index() - 1] { + match self.stack[frame].locals[local] { None => return err!(DeadLocal), Some(Value::ByRef(ptr, align)) => { Place::Ptr { @@ -983,7 +987,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M let ty = self.monomorphize(ty, self.stack[frame].instance.substs); let layout = self.layout_of(ty)?; let ptr = self.alloc_ptr(ty)?; - self.stack[frame].locals[local.index() - 1] = + self.stack[frame].locals[local] = Some(Value::ByRef(ptr.into(), layout.align)); // it stays live let place = Place::from_ptr(ptr, layout.align); self.write_value(ValTy { value: val, ty }, place)?; @@ -1697,13 +1701,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M impl<'mir, 'tcx> Frame<'mir, 'tcx> { pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> { - // Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0. - self.locals[local.index() - 1].ok_or(EvalErrorKind::DeadLocal.into()) + self.locals[local].ok_or(EvalErrorKind::DeadLocal.into()) } fn set_local(&mut self, local: mir::Local, value: Value) -> EvalResult<'tcx> { - // Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0. - match self.locals[local.index() - 1] { + match self.locals[local] { None => err!(DeadLocal), Some(ref mut local) => { *local = value; @@ -1712,20 +1714,17 @@ impl<'mir, 'tcx> Frame<'mir, 'tcx> { } } - pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, Option> { + pub fn storage_live(&mut self, local: mir::Local) -> Option { trace!("{:?} is now live", local); - let old = self.locals[local.index() - 1]; - self.locals[local.index() - 1] = Some(Value::ByVal(PrimVal::Undef)); // StorageLive *always* kills the value that's currently stored - return Ok(old); + // StorageLive *always* kills the value that's currently stored + mem::replace(&mut self.locals[local], Some(Value::ByVal(PrimVal::Undef))) } /// Returns the old value of the local - pub fn storage_dead(&mut self, local: mir::Local) -> EvalResult<'tcx, Option> { + pub fn storage_dead(&mut self, local: mir::Local) -> Option { trace!("{:?} is now dead", local); - let old = self.locals[local.index() - 1]; - self.locals[local.index() - 1] = None; - return Ok(old); + self.locals[local].take() } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index b369f80e849b..dcf97f61545d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1,5 +1,5 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian}; -use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque}; +use std::collections::{btree_map, BTreeMap, VecDeque}; use std::{ptr, io}; use rustc::ty::Instance; @@ -7,6 +7,7 @@ use rustc::ty::maps::TyCtxtAt; use rustc::ty::layout::{self, Align, TargetDataLayout}; use syntax::ast::Mutability; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, Value, Pointer, EvalResult, PrimVal, EvalErrorKind}; @@ -33,15 +34,15 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { pub data: M::MemoryData, /// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate` - alloc_kind: HashMap>, + alloc_kind: FxHashMap>, /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). - alloc_map: HashMap, + alloc_map: FxHashMap, /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). /// /// Stores statics while they are being processed, before they are interned and thus frozen - uninitialized_statics: HashMap, + uninitialized_statics: FxHashMap, /// The current stack frame. Used to check accesses against locks. pub cur_frame: usize, @@ -53,9 +54,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self { Memory { data, - alloc_kind: HashMap::new(), - alloc_map: HashMap::new(), - uninitialized_statics: HashMap::new(), + alloc_kind: FxHashMap::default(), + alloc_map: FxHashMap::default(), + uninitialized_statics: FxHashMap::default(), tcx, cur_frame: usize::max_value(), } @@ -327,6 +328,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { .ok_or(EvalErrorKind::ExecuteMemory.into()) } + pub fn get_alloc_kind(&self, id: AllocId) -> Option> { + self.alloc_kind.get(&id).cloned() + } + /// For debugging, print an allocation and all allocations it points to, recursively. pub fn dump_alloc(&self, id: AllocId) { self.dump_allocs(vec![id]); @@ -338,7 +343,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { allocs.sort(); allocs.dedup(); let mut allocs_to_print = VecDeque::from(allocs); - let mut allocs_seen = HashSet::new(); + let mut allocs_seen = FxHashSet::default(); while let Some(id) = allocs_to_print.pop_front() { let mut msg = format!("Alloc {:<5} ", format!("{}:", id)); diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index d27de3ef6bfc..456f5fd75db0 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -197,29 +197,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { }, Static(ref static_) => { - let alloc = self - .tcx - .interpret_interner - .get_cached(static_.def_id); let layout = self.layout_of(self.place_ty(mir_place))?; - if let Some(alloc) = alloc { - Place::Ptr { - ptr: MemoryPointer::new(alloc, 0).into(), - align: layout.align, - extra: PlaceExtra::None, - } - } else { - let instance = ty::Instance::mono(*self.tcx, static_.def_id); - let cid = GlobalId { - instance, - promoted: None - }; - let alloc = Machine::init_static(self, cid)?; - Place::Ptr { - ptr: MemoryPointer::new(alloc, 0).into(), - align: layout.align, - extra: PlaceExtra::None, - } + let instance = ty::Instance::mono(*self.tcx, static_.def_id); + let cid = GlobalId { + instance, + promoted: None + }; + let alloc = Machine::init_static(self, cid)?; + Place::Ptr { + ptr: MemoryPointer::new(alloc, 0).into(), + align: layout.align, + extra: PlaceExtra::None, } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 4e1750caf26b..a22572ec687c 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -69,13 +69,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { // Mark locals as alive StorageLive(local) => { - let old_val = self.frame_mut().storage_live(local)?; + let old_val = self.frame_mut().storage_live(local); self.deallocate_local(old_val)?; } // Mark locals as dead StorageDead(local) => { - let old_val = self.frame_mut().storage_dead(local)?; + let old_val = self.frame_mut().storage_dead(local); self.deallocate_local(old_val)?; } @@ -89,6 +89,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { M::end_region(self, Some(ce))?; } + UserAssertTy(..) => {} + // Defined to do nothing. These are added by optimization passes, to avoid changing the // size of MIR constantly. Nop => {} diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index babc78470147..851fac532e36 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -75,8 +75,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { match instance_ty.sty { ty::TyFnDef(..) => { let real_sig = instance_ty.fn_sig(*self.tcx); - let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig); - let real_sig = self.tcx.erase_late_bound_regions_and_normalize(&real_sig); + let sig = self.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); + let real_sig = self.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &real_sig, + ); if !self.check_sig_compat(sig, real_sig)? { return err!(FunctionPointerTyMismatch(real_sig, sig)); } @@ -95,7 +101,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } }; let args = self.operands_to_args(args)?; - let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = self.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); self.eval_fn_call( fn_def, destination, @@ -113,7 +122,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { // FIXME(CTFE): forbid drop in const eval let place = self.eval_place(location)?; let ty = self.place_ty(location); - let ty = self.tcx.trans_apply_param_substs(self.substs(), &ty); + let ty = self.tcx.subst_and_normalize_erasing_regions( + self.substs(), + ty::ParamEnv::reveal_all(), + &ty, + ); trace!("TerminatorKind::drop: {:?}, type {}", location, ty); let instance = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); @@ -221,7 +234,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { // Second argument must be a tuple matching the argument list of sig let snd_ty = real_sig.inputs_and_output[1]; match snd_ty.sty { - ty::TyTuple(tys, _) if sig.inputs().len() == tys.len() => + ty::TyTuple(tys) if sig.inputs().len() == tys.len() => if sig.inputs().iter().zip(tys).all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) { return Ok(true) }, diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index e21fa63ccc27..682250391b67 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -21,24 +21,23 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_patterns)] #![feature(box_syntax)] #![feature(catch_expr)] -#![feature(conservative_impl_trait)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(decl_macro)] #![feature(dyn_trait)] #![feature(fs_read_write)] -#![feature(i128_type)] -#![feature(inclusive_range_syntax)] -#![feature(inclusive_range)] +#![cfg_attr(stage0, feature(i128_type))] +#![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(macro_vis_matcher)] -#![feature(match_default_bindings)] -#![feature(never_type)] +#![cfg_attr(stage0, feature(match_default_bindings))] +#![feature(exhaustive_patterns)] #![feature(range_contains)] #![feature(rustc_diagnostic_macros)] -#![feature(placement_in_syntax)] -#![feature(collection_placement)] #![feature(nonzero)] -#![feature(underscore_lifetimes)] +#![cfg_attr(stage0, feature(underscore_lifetimes))] +#![cfg_attr(stage0, feature(never_type))] +#![feature(inclusive_range_fields)] #![feature(crate_visibility_modifier)] extern crate arena; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f6b47efca31c..446ef6bd3287 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -196,7 +196,6 @@ use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; use rustc::mir::interpret::{Value, PrimVal, AllocId, Pointer}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; -use rustc::traits; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt}; use rustc::ty::adjustment::CustomCoerceUnsized; @@ -342,6 +341,8 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; tcx.hir.krate().visit_all_item_likes(&mut visitor); + + visitor.push_extra_entry_roots(); } // We can only translate items that are instantiable - items all of @@ -383,7 +384,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance, promoted: None, }; - let param_env = ty::ParamEnv::empty(traits::Reveal::All); + let param_env = ty::ParamEnv::reveal_all(); match tcx.const_eval(param_env.and(cid)) { Ok(val) => collect_const(tcx, val, instance.substs, &mut neighbors), @@ -524,11 +525,17 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { // have to instantiate all methods of the trait being cast to, so we // can build the appropriate vtable. mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, target_ty) => { - let target_ty = self.tcx.trans_apply_param_substs(self.param_substs, - &target_ty); + let target_ty = self.tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + &target_ty, + ); let source_ty = operand.ty(self.mir, self.tcx); - let source_ty = self.tcx.trans_apply_param_substs(self.param_substs, - &source_ty); + let source_ty = self.tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + &source_ty, + ); let (source_ty, target_ty) = find_vtable_types_for_unsizing(self.tcx, source_ty, target_ty); @@ -544,14 +551,20 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { } mir::Rvalue::Cast(mir::CastKind::ReifyFnPointer, ref operand, _) => { let fn_ty = operand.ty(self.mir, self.tcx); - let fn_ty = self.tcx.trans_apply_param_substs(self.param_substs, - &fn_ty); + let fn_ty = self.tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + &fn_ty, + ); visit_fn_use(self.tcx, fn_ty, false, &mut self.output); } mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => { let source_ty = operand.ty(self.mir, self.tcx); - let source_ty = self.tcx.trans_apply_param_substs(self.param_substs, - &source_ty); + let source_ty = self.tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + &source_ty, + ); match source_ty.sty { ty::TyClosure(def_id, substs) => { let instance = monomorphize::resolve_closure( @@ -596,14 +609,22 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match *kind { mir::TerminatorKind::Call { ref func, .. } => { let callee_ty = func.ty(self.mir, tcx); - let callee_ty = tcx.trans_apply_param_substs(self.param_substs, &callee_ty); + let callee_ty = tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + &callee_ty, + ); visit_fn_use(self.tcx, callee_ty, true, &mut self.output); } mir::TerminatorKind::Drop { ref location, .. } | mir::TerminatorKind::DropAndReplace { ref location, .. } => { let ty = location.ty(self.mir, self.tcx) .to_ty(self.tcx); - let ty = tcx.trans_apply_param_substs(self.param_substs, &ty); + let ty = tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + &ty, + ); visit_drop_use(self.tcx, ty, true, self.output); } mir::TerminatorKind::Goto { .. } | @@ -654,7 +675,7 @@ fn visit_fn_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { if let ty::TyFnDef(def_id, substs) = ty.sty { let instance = ty::Instance::resolve(tcx, - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), def_id, substs).unwrap(); visit_instance_use(tcx, instance, is_direct_call, output); @@ -776,7 +797,7 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let type_has_metadata = |ty: Ty<'tcx>| -> bool { use syntax_pos::DUMMY_SP; - if ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::empty(traits::Reveal::All)) { + if ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) { return false; } let tail = tcx.struct_tail(ty); @@ -859,7 +880,7 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let methods = methods.iter().cloned().filter_map(|method| method) .map(|(def_id, substs)| ty::Instance::resolve( tcx, - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), def_id, substs).unwrap()) .filter(|&instance| should_monomorphize_locally(tcx, &instance)) @@ -979,8 +1000,6 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { let instance = Instance::mono(self.tcx, def_id); self.output.push(create_fn_mono_item(instance)); - - self.push_extra_entry_roots(def_id); } } @@ -989,20 +1008,22 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { /// monomorphized copy of the start lang item based on /// the return type of `main`. This is not needed when /// the user writes their own `start` manually. - fn push_extra_entry_roots(&mut self, def_id: DefId) { - if self.entry_fn != Some(def_id) { - return; + fn push_extra_entry_roots(&mut self) { + if self.tcx.sess.entry_type.get() != Some(config::EntryMain) { + return } - if self.tcx.sess.entry_type.get() != Some(config::EntryMain) { - return; - } + let main_def_id = if let Some(def_id) = self.entry_fn { + def_id + } else { + return + }; let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) { Ok(s) => s, Err(err) => self.tcx.sess.fatal(&err), }; - let main_ret_ty = self.tcx.fn_sig(def_id).output(); + let main_ret_ty = self.tcx.fn_sig(main_def_id).output(); // Given that `main()` has no arguments, // then its return type cannot have @@ -1013,7 +1034,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { let start_instance = Instance::resolve( self.tcx, - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), start_def_id, self.tcx.mk_substs(iter::once(Kind::from(main_ret_ty))) ).unwrap(); @@ -1047,7 +1068,6 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id_to_string(tcx, impl_def_id)); if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { - let callee_substs = tcx.erase_regions(&trait_ref.substs); let overridden_methods: FxHashSet<_> = impl_item_refs.iter() .map(|iiref| iiref.name) @@ -1061,10 +1081,15 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, continue; } + let substs = Substs::for_item(tcx, + method.def_id, + |_, _| tcx.types.re_erased, + |def, _| trait_ref.substs.type_for_def(def)); + let instance = ty::Instance::resolve(tcx, - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), method.def_id, - callee_substs).unwrap(); + substs).unwrap(); let mono_item = create_fn_mono_item(instance); if mono_item.is_instantiable(tcx) @@ -1120,7 +1145,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output, param_substs: instance.substs, }.visit_mir(&mir); - let param_env = ty::ParamEnv::empty(traits::Reveal::All); + let param_env = ty::ParamEnv::reveal_all(); for (i, promoted) in mir.promoted.iter().enumerate() { use rustc_data_structures::indexed_vec::Idx; let cid = GlobalId { @@ -1155,9 +1180,12 @@ fn collect_const<'a, 'tcx>( let val = match constant.val { ConstVal::Unevaluated(def_id, substs) => { - let param_env = ty::ParamEnv::empty(traits::Reveal::All); - let substs = tcx.trans_apply_param_substs(param_substs, - &substs); + let param_env = ty::ParamEnv::reveal_all(); + let substs = tcx.subst_and_normalize_erasing_regions( + param_substs, + param_env, + &substs, + ); let instance = ty::Instance::resolve(tcx, param_env, def_id, diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 1f7f1237ba78..c2f4359c0082 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -281,7 +281,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_def_path(adt_def.did, output); self.push_type_params(substs, iter::empty(), output); }, - ty::TyTuple(component_types, _) => { + ty::TyTuple(component_types) => { output.push('('); for &component_type in component_types { self.push_type_name(component_type, output); @@ -347,7 +347,10 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push_str("fn("); - let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = self.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 2ca6c76a8009..5c38735d9203 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -88,7 +88,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( closure_did, substs); let sig = substs.closure_sig(closure_did, tcx); - let sig = tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); assert_eq!(sig.inputs().len(), 1); let substs = tcx.mk_substs([ Kind::from(self_ty), @@ -154,7 +154,7 @@ pub fn resolve_drop_in_place<'a, 'tcx>( { let def_id = tcx.require_lang_item(DropInPlaceFnLangItem); let substs = tcx.intern_substs(&[ty.into()]); - Instance::resolve(tcx, ty::ParamEnv::empty(traits::Reveal::All), def_id, substs).unwrap() + Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap() } pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -168,7 +168,7 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, substs: tcx.mk_substs_trait(source_ty, &[target_ty]) }); - match tcx.trans_fulfill_obligation( (ty::ParamEnv::empty(traits::Reveal::All), trait_ref)) { + match tcx.trans_fulfill_obligation( (ty::ParamEnv::reveal_all(), trait_ref)) { traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => { tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap() } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index d65c1e03298a..3789342b3891 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -645,7 +645,11 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(impl_def_id) = tcx.impl_of_method(def_id) { // This is a method within an inherent impl, find out what the // self-type is: - let impl_self_ty = tcx.trans_impl_self_ty(impl_def_id, instance.substs); + let impl_self_ty = tcx.subst_and_normalize_erasing_regions( + instance.substs, + ty::ParamEnv::reveal_all(), + &tcx.type_of(impl_def_id), + ); if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { return Some(def_id); } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 9aff7fa2a2c7..6a0f42c6dbb6 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -312,7 +312,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, substs.upvar_tys(def_id, tcx) ) } - ty::TyTuple(tys, _) => builder.tuple_like_shim(dest, src, tys.iter().cloned()), + ty::TyTuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()), _ => { bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty) } @@ -832,14 +832,11 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let tcx = infcx.tcx; let gcx = tcx.global_tcx(); let def_id = tcx.hir.local_def_id(ctor_id); - let sig = gcx.fn_sig(def_id).no_late_bound_regions() - .expect("LBR in ADT constructor signature"); - let sig = gcx.erase_regions(&sig); let param_env = gcx.param_env(def_id); - // Normalize the sig now that we have liberated the late-bound - // regions. - let sig = gcx.normalize_associated_type_in_env(&sig, param_env); + // Normalize the sig. + let sig = gcx.fn_sig(def_id).no_late_bound_regions().expect("LBR in ADT constructor signature"); + let sig = gcx.normalize_erasing_regions(param_env, sig); let (adt_def, substs) = match sig.output().sty { ty::TyAdt(adt_def, substs) => (adt_def, substs), diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 86d08dec2b9c..31af7c218579 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -105,6 +105,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { StatementKind::StorageDead(..) | StatementKind::EndRegion(..) | StatementKind::Validate(..) | + StatementKind::UserAssertTy(..) | StatementKind::Nop => { // safe (at least as emitted during MIR construction) } @@ -125,21 +126,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { &AggregateKind::Array(..) | &AggregateKind::Tuple | &AggregateKind::Adt(..) => {} - &AggregateKind::Closure(def_id, _) => { + &AggregateKind::Closure(def_id, _) | + &AggregateKind::Generator(def_id, _, _) => { let UnsafetyCheckResult { violations, unsafe_blocks } = self.tcx.unsafety_check_result(def_id); self.register_violations(&violations, &unsafe_blocks); } - &AggregateKind::Generator(def_id, _, interior) => { - let UnsafetyCheckResult { - violations, unsafe_blocks - } = self.tcx.unsafety_check_result(def_id); - self.register_violations(&violations, &unsafe_blocks); - if !interior.movable { - self.require_unsafe("construction of immovable generator") - } - } } } self.super_rvalue(rvalue, location); diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs similarity index 65% rename from src/librustc_mir/transform/clean_end_regions.rs rename to src/librustc_mir/transform/cleanup_post_borrowck.rs index 6e8985d99d28..256b1fd66e9a 100644 --- a/src/librustc_mir/transform/clean_end_regions.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -8,16 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module provides one pass, `CleanEndRegions`, that reduces the -//! set of `EndRegion` statements in the MIR. +//! This module provides two passes: //! -//! The "pass" is actually implemented as two traversals (aka visits) -//! of the input MIR. The first traversal, `GatherBorrowedRegions`, -//! finds all of the regions in the MIR that are involved in a borrow. +//! - `CleanEndRegions`, that reduces the set of `EndRegion` statements +//! in the MIR. +//! - `CleanUserAssertTy`, that replaces all `UserAssertTy` statements +//! with `Nop`. +//! +//! The `CleanEndRegions` "pass" is actually implemented as two +//! traversals (aka visits) of the input MIR. The first traversal, +//! `GatherBorrowedRegions`, finds all of the regions in the MIR +//! that are involved in a borrow. //! //! The second traversal, `DeleteTrivialEndRegions`, walks over the //! MIR and removes any `EndRegion` that is applied to a region that //! was not seen in the previous pass. +//! +//! The `CleanUserAssertTy` pass runs at a distinct time from the +//! `CleanEndRegions` pass. It is important that the `CleanUserAssertTy` +//! pass runs after the MIR borrowck so that the NLL type checker can +//! perform the type assertion when it encounters the `UserAssertTy` +//! statements. use rustc_data_structures::fx::FxHashSet; @@ -93,7 +104,33 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { } if delete_it { - statement.kind = StatementKind::Nop; + statement.make_nop(); + } + self.super_statement(block, statement, location); + } +} + +pub struct CleanUserAssertTy; + +pub struct DeleteUserAssertTy; + +impl MirPass for CleanUserAssertTy { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _source: MirSource, + mir: &mut Mir<'tcx>) { + let mut delete = DeleteUserAssertTy; + delete.visit_mir(mir); + } +} + +impl<'tcx> MutVisitor<'tcx> for DeleteUserAssertTy { + fn visit_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>, + location: Location) { + if let StatementKind::UserAssertTy(..) = statement.kind { + statement.make_nop(); } self.super_statement(block, statement, location); } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index b8a0e0f89073..2dd805ccf9b5 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -19,7 +19,7 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::*; use rustc::mir::visit::*; -use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc::ty::subst::{Subst,Substs}; use std::collections::VecDeque; @@ -129,8 +129,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let callee_mir = match ty::queries::optimized_mir::try_get(self.tcx, callsite.location.span, callsite.callee) { - Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => { - subst_and_normalize(callee_mir, self.tcx, &callsite.substs, param_env) + Ok(callee_mir) if self.should_inline(callsite, callee_mir) => { + self.tcx.subst_and_normalize_erasing_regions( + &callsite.substs, + param_env, + callee_mir, + ) } Ok(_) => continue, @@ -595,7 +599,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { assert!(args.next().is_none()); let tuple = Place::Local(tuple); - let tuple_tys = if let ty::TyTuple(s, _) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty { + let tuple_tys = if let ty::TyTuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty { s } else { bug!("Closure arguments are not passed as a tuple"); @@ -664,30 +668,6 @@ fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes()) } -fn subst_and_normalize<'a, 'tcx: 'a>( - mir: &Mir<'tcx>, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - substs: &'tcx ty::subst::Substs<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> Mir<'tcx> { - struct Folder<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - substs: &'tcx ty::subst::Substs<'tcx>, - } - impl<'a, 'tcx: 'a> ty::fold::TypeFolder<'tcx, 'tcx> for Folder<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { - self.tcx - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - self.tcx.trans_apply_param_substs_env(&self.substs, self.param_env, &t) - } - } - let mut f = Folder { tcx, param_env, substs }; - mir.fold_with(&mut f) -} - /** * Integrator. * diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 81b740c917b5..63ca35aa0e7b 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -25,7 +25,7 @@ use syntax_pos::Span; pub mod add_validation; pub mod add_moves_for_packed_drops; -pub mod clean_end_regions; +pub mod cleanup_post_borrowck; pub mod check_unsafety; pub mod simplify_branches; pub mod simplify; @@ -193,7 +193,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea let mut mir = tcx.mir_built(def_id).steal(); run_passes![tcx, mir, def_id, 0; // Remove all `EndRegion` statements that are not involved in borrows. - clean_end_regions::CleanEndRegions, + cleanup_post_borrowck::CleanEndRegions, // What we need to do constant evaluation. simplify::SimplifyCfg::new("initial"), @@ -234,6 +234,8 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx simplify_branches::SimplifyBranches::new("initial"), remove_noop_landing_pads::RemoveNoopLandingPads, simplify::SimplifyCfg::new("early-opt"), + // Remove all `UserAssertTy` statements. + cleanup_post_borrowck::CleanUserAssertTy, // These next passes must be executed together add_call_guards::CriticalCallEdges, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 88618122e4f1..aeefd5ab1d5a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -21,7 +21,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; -use rustc::traits::{self, Reveal}; +use rustc::traits::{self, TraitEngine}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; use rustc::ty::maps::Providers; @@ -1099,6 +1099,7 @@ This does not pose a problem by itself because they can't be accessed directly." StatementKind::InlineAsm {..} | StatementKind::EndRegion(_) | StatementKind::Validate(..) | + StatementKind::UserAssertTy(..) | StatementKind::Nop => {} } }); @@ -1237,7 +1238,7 @@ impl MirPass for QualifyAndPromoteConstants { } let ty = mir.return_ty(); tcx.infer_ctxt().enter(|infcx| { - let param_env = ty::ParamEnv::empty(Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, @@ -1246,7 +1247,7 @@ impl MirPass for QualifyAndPromoteConstants { tcx.require_lang_item(lang_items::SyncTraitLangItem), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&err, None); + infcx.report_fulfillment_errors(&err, None, false); } }); } diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index cd80d25c410f..6d365012525f 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -50,6 +50,7 @@ impl RemoveNoopLandingPads { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::EndRegion(_) | + StatementKind::UserAssertTy(..) | StatementKind::Nop => { // These are all nops in a landing pad (there's some // borrowck interaction between EndRegion and storage diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 76283edac728..45e7a0d3f4c5 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -163,6 +163,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::InlineAsm { .. } | mir::StatementKind::EndRegion(_) | mir::StatementKind::Validate(..) | + mir::StatementKind::UserAssertTy(..) | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 5da6d135f5f2..1078013a3e22 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -52,30 +52,30 @@ impl Origin { } } -pub trait BorrowckErrors { - fn struct_span_err_with_code<'a, S: Into>(&'a self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'a>; +pub trait BorrowckErrors<'cx>: Sized + Copy { + fn struct_span_err_with_code>(self, + sp: S, + msg: &str, + code: DiagnosticId) + -> DiagnosticBuilder<'cx>; - fn struct_span_err<'a, S: Into>(&'a self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a>; + fn struct_span_err>(self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'cx>; /// Cancels the given error if we shouldn't emit errors for a given /// origin in the current mode. /// /// Always make sure that the error gets passed through this function /// before you return it. - fn cancel_if_wrong_origin<'a>(&'a self, - diag: DiagnosticBuilder<'a>, - o: Origin) - -> DiagnosticBuilder<'a>; + fn cancel_if_wrong_origin(self, + diag: DiagnosticBuilder<'cx>, + o: Origin) + -> DiagnosticBuilder<'cx>; - fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'_> + fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0505, "cannot move out of `{}` because it is borrowed{OGN}", @@ -83,13 +83,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_use_when_mutably_borrowed(&self, + fn cannot_use_when_mutably_borrowed(self, span: Span, desc: &str, borrow_span: Span, borrow_desc: &str, o: Origin) - -> DiagnosticBuilder<'_> + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, span, E0503, "cannot use `{}` because it was mutably borrowed{OGN}", @@ -101,12 +101,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_uninitialized_variable(&self, + fn cannot_act_on_uninitialized_variable(self, span: Span, verb: &str, desc: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0381, "{} of possibly uninitialized variable: `{}`{OGN}", @@ -114,7 +114,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_mutably_borrow_multiply(&self, + fn cannot_mutably_borrow_multiply(self, new_loan_span: Span, desc: &str, opt_via: &str, @@ -122,7 +122,7 @@ pub trait BorrowckErrors { old_opt_via: &str, old_load_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, new_loan_span, E0499, "cannot borrow `{}`{} as mutable more than once at a time{OGN}", @@ -148,13 +148,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_uniquely_borrow_by_two_closures(&self, + fn cannot_uniquely_borrow_by_two_closures(self, new_loan_span: Span, desc: &str, old_loan_span: Span, old_load_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, new_loan_span, E0524, "two closures require unique access to `{}` at the same time{OGN}", @@ -173,7 +173,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_uniquely_borrow_by_one_closure(&self, + fn cannot_uniquely_borrow_by_one_closure(self, new_loan_span: Span, desc_new: &str, opt_via: &str, @@ -182,7 +182,7 @@ pub trait BorrowckErrors { old_opt_via: &str, previous_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, new_loan_span, E0500, "closure requires unique access to `{}` but {} is already borrowed{}{OGN}", @@ -197,7 +197,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_reborrow_already_uniquely_borrowed(&self, + fn cannot_reborrow_already_uniquely_borrowed(self, new_loan_span: Span, desc_new: &str, opt_via: &str, @@ -206,7 +206,7 @@ pub trait BorrowckErrors { old_opt_via: &str, previous_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, new_loan_span, E0501, "cannot borrow `{}`{} as {} because previous closure \ @@ -222,7 +222,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_reborrow_already_borrowed(&self, + fn cannot_reborrow_already_borrowed(self, span: Span, desc_new: &str, msg_new: &str, @@ -233,7 +233,7 @@ pub trait BorrowckErrors { msg_old: &str, old_load_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, span, E0502, "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}", @@ -246,8 +246,8 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, span, E0506, "cannot assign to `{}` because it is borrowed{OGN}", @@ -259,8 +259,8 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0504, "cannot move `{}` into closure because it is borrowed{OGN}", @@ -269,8 +269,8 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin) - -> DiagnosticBuilder + fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin) + -> DiagnosticBuilder<'cx> { let msg = if is_arg { "to immutable argument" @@ -284,8 +284,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } +<<<<<<< HEAD fn cannot_assign(&self, span: Span, desc: &str, o: Origin, is_reference:bool) -> DiagnosticBuilder +======= + fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> +>>>>>>> 56714acc5eb0687ed9a7566fdebe5528657fc5b3 { let msg = if is_reference { "through" @@ -299,14 +303,14 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_assign_static(self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> { self.cannot_assign(span, &format!("immutable static item `{}`", desc), o, false) } - fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, move_from_span, E0507, "cannot move out of {}{OGN}", @@ -318,12 +322,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_move_out_of_interior_noncopy(&self, + fn cannot_move_out_of_interior_noncopy(self, move_from_span: Span, ty: ty::Ty, is_index: bool, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let type_name = match (&ty.sty, is_index) { (&ty::TyArray(_, _), true) => "array", @@ -339,11 +343,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_move_out_of_interior_of_drop(&self, + fn cannot_move_out_of_interior_of_drop(self, move_from_span: Span, container_ty: ty::Ty, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, move_from_span, E0509, "cannot move out of type `{}`, \ @@ -354,13 +358,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_moved_value(&self, + fn cannot_act_on_moved_value(self, use_span: Span, verb: &str, optional_adverb_for_moved: &str, moved_path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, use_span, E0382, "{} of {}moved value: `{}`{OGN}", @@ -369,11 +373,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_partially_reinit_an_uninit_struct(&self, + fn cannot_partially_reinit_an_uninit_struct(self, span: Span, uninit_path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, @@ -384,11 +388,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn closure_cannot_assign_to_borrowed(&self, + fn closure_cannot_assign_to_borrowed(self, span: Span, descr: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}", descr, OGN=o); @@ -396,11 +400,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_borrow_path_as_mutable(&self, + fn cannot_borrow_path_as_mutable(self, span: Span, path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}", path, OGN=o); @@ -408,11 +412,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_borrow_across_generator_yield(&self, + fn cannot_borrow_across_generator_yield(self, span: Span, yield_span: Span, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, span, @@ -424,11 +428,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn path_does_not_live_long_enough(&self, + fn path_does_not_live_long_enough(self, span: Span, path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}", path, OGN=o); @@ -436,11 +440,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn lifetime_too_short_for_reborrow(&self, + fn lifetime_too_short_for_reborrow(self, span: Span, path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let err = struct_span_err!(self, span, E0598, "lifetime of {} is too short to guarantee \ @@ -450,12 +454,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_capture_in_sharable_fn(&self, + fn cannot_act_on_capture_in_sharable_fn(self, span: Span, bad_thing: &str, help: (Span, &str), o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let (help_span, help_msg) = help; let mut err = struct_span_err!(self, span, E0387, @@ -466,11 +470,11 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_into_immutable_reference(&self, + fn cannot_assign_into_immutable_reference(self, span: Span, bad_thing: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}", bad_thing, OGN=o); @@ -479,12 +483,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_capture_in_long_lived_closure(&self, + fn cannot_capture_in_long_lived_closure(self, closure_span: Span, borrowed_path: &str, capture_span: Span, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!(self, closure_span, E0373, "closure may outlive the current function, \ @@ -498,28 +502,28 @@ pub trait BorrowckErrors { } } -impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> { - fn struct_span_err_with_code<'a, S: Into>(&'a self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'a> +impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { + fn struct_span_err_with_code>(self, + sp: S, + msg: &str, + code: DiagnosticId) + -> DiagnosticBuilder<'cx> { self.sess.struct_span_err_with_code(sp, msg, code) } - fn struct_span_err<'a, S: Into>(&'a self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a> + fn struct_span_err>(self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'cx> { self.sess.struct_span_err(sp, msg) } - fn cancel_if_wrong_origin<'a>(&'a self, - mut diag: DiagnosticBuilder<'a>, - o: Origin) - -> DiagnosticBuilder<'a> + fn cancel_if_wrong_origin(self, + mut diag: DiagnosticBuilder<'cx>, + o: Origin) + -> DiagnosticBuilder<'cx> { if !o.should_emit_errors(self.borrowck_mode()) { self.sess.diagnostic().cancel(&mut diag); diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 458dd488409e..19f33ef5d45a 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -177,7 +177,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> }); } DropStyle::Conditional => { - let unwind = self.unwind; // FIXME(#6393) + let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; let drop_bb = self.complete_drop(Some(DropFlagMode::Deep), succ, unwind); self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto { @@ -206,11 +206,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let field = Field::new(i); let subpath = self.elaborator.field_subpath(variant_path, field); - let field_ty = - self.tcx().normalize_associated_type_in_env( - &f.ty(self.tcx(), substs), - self.elaborator.param_env() - ); + let field_ty = self.tcx().normalize_erasing_regions( + self.elaborator.param_env(), + f.ty(self.tcx(), substs), + ); (base_place.clone().field(field, field_ty), subpath) }).collect() } @@ -269,7 +268,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> // Clear the "master" drop flag at the end. This is needed // because the "master" drop protects the ADT's discriminant, // which is invalidated after the ADT is dropped. - let (succ, unwind) = (self.succ, self.unwind); // FIXME(#6393) + let (succ, unwind) = (self.succ, self.unwind); // FIXME(#43234) ( self.drop_flag_reset_block(DropFlagMode::Shallow, succ, unwind), unwind.map(|unwind| { @@ -345,7 +344,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let interior = self.place.clone().deref(); let interior_path = self.elaborator.deref_subpath(self.path); - let succ = self.succ; // FIXME(#6393) + let succ = self.succ; // FIXME(#43234) let unwind = self.unwind; let succ = self.box_free_block(ty, succ, unwind); let unwind_succ = self.unwind.map(|unwind| { @@ -718,7 +717,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ptr_based) }); - let succ = self.succ; // FIXME(#6393) + let succ = self.succ; // FIXME(#43234) let loop_block = self.drop_loop( succ, cur, @@ -789,7 +788,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } - ty::TyTuple(tys, _) => { + ty::TyTuple(tys) => { self.open_drop_for_tuple(tys) } ty::TyAdt(def, _) if def.is_box() => { @@ -799,7 +798,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.open_drop_for_adt(def, substs) } ty::TyDynamic(..) => { - let unwind = self.unwind; // FIXME(#6393) + let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; self.complete_drop(Some(DropFlagMode::Deep), succ, unwind) } @@ -850,7 +849,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> fn elaborated_drop_block<'a>(&mut self) -> BasicBlock { debug!("elaborated_drop_block({:?})", self); - let unwind = self.unwind; // FIXME(#6393) + let unwind = self.unwind; // FIXME(#43234) let succ = self.succ; let blk = self.drop_block(succ, unwind); self.elaborate_drop(blk); @@ -883,7 +882,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> args: vec![Operand::Move(self.place.clone())], destination: Some((unit_temp, target)), cleanup: None - }; // FIXME(#6393) + }; // FIXME(#43234) let free_block = self.new_block(unwind, call); let block_start = Location { block: free_block, statement_index: 0 }; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 55d00f92e4da..37274d1fc447 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -37,15 +37,17 @@ impl<'a> AstValidator<'a> { } fn check_lifetime(&self, lifetime: &Lifetime) { - let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()]; + let valid_names = [keywords::UnderscoreLifetime.name(), + keywords::StaticLifetime.name(), + keywords::Invalid.name()]; if !valid_names.contains(&lifetime.ident.name) && - token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() { + token::is_reserved_ident(lifetime.ident.without_first_quote()) { self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names"); } } fn check_label(&self, label: Ident, span: Span) { - if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" { + if token::is_reserved_ident(label.without_first_quote()) { self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name)); } } @@ -65,7 +67,7 @@ impl<'a> AstValidator<'a> { E0449, "unnecessary visibility qualifier"); if vis.node == VisibilityKind::Public { - err.span_label(vis.span, "`pub` not needed here"); + err.span_label(vis.span, "`pub` not permitted here because it's implied"); } if let Some(note) = note { err.note(note); diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 4a4ce63cc1d4..a4e056c6b589 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -90,6 +90,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", + StatementKind::UserAssertTy(..) => "StatementKind::UserAssertTy", StatementKind::Nop => "StatementKind::Nop", }, &statement.kind); self.super_statement(block, statement, location); diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 16278c37a0cc..76cbc6709698 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -34,7 +34,6 @@ use rustc::middle::mem_categorization::Categorization; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::ty::subst::Substs; -use rustc::traits::Reveal; use rustc::util::nodemap::{ItemLocalSet, NodeSet}; use rustc::hir; use rustc_data_structures::sync::Lrc; @@ -87,7 +86,7 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_static: false, promotable: false, mut_rvalue_borrows: NodeSet(), - param_env: ty::ParamEnv::empty(Reveal::UserFacing), + param_env: ty::ParamEnv::empty(), identity_substs: Substs::empty(), result: ItemLocalSet(), }; @@ -374,10 +373,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - let def_id = v.tables.type_dependent_defs()[e.hir_id].def_id(); - match v.tcx.associated_item(def_id).container { - ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty), - ty::TraitContainer(_) => v.promotable = false + if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) { + let def_id = def.def_id(); + match v.tcx.associated_item(def_id).container { + ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty), + ty::TraitContainer(_) => v.promotable = false + } + } else { + v.tcx.sess.delay_span_bug(e.span, "no type-dependent def for method call"); } } hir::ExprStruct(..) => { diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 3f74093241d2..ebfd8785a0a0 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -106,14 +106,16 @@ impl<'a> Registry<'a> { expander, def_info: _, allow_internal_unstable, - allow_internal_unsafe + allow_internal_unsafe, + unstable_feature } => { let nid = ast::CRATE_NODE_ID; NormalTT { expander, def_info: Some((nid, self.krate_span)), allow_internal_unstable, - allow_internal_unsafe + allow_internal_unsafe, + unstable_feature } } IdentTT(ext, _, allow_internal_unstable) => { @@ -149,6 +151,7 @@ impl<'a> Registry<'a> { def_info: None, allow_internal_unstable: false, allow_internal_unsafe: false, + unstable_feature: None, }); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index bf7b81c4d0e4..c192f349c201 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -119,7 +119,8 @@ impl<'a> Resolver<'a> { .collect(); match use_tree.kind { - ast::UseTreeKind::Simple(mut ident) => { + ast::UseTreeKind::Simple(rename) => { + let mut ident = use_tree.ident(); let mut source = module_path.pop().unwrap().node; let mut type_ns_only = false; @@ -142,7 +143,7 @@ impl<'a> Resolver<'a> { // Replace `use foo::self;` with `use foo;` let _ = module_path.pop(); source = last_segment.node; - if ident.name == keywords::SelfValue.name() { + if rename.is_none() { ident = last_segment.node; } } @@ -162,7 +163,7 @@ impl<'a> Resolver<'a> { ModuleKind::Block(..) => unreachable!(), }; source.name = crate_name; - if ident.name == keywords::DollarCrate.name() { + if rename.is_none() { ident.name = crate_name; } @@ -206,8 +207,8 @@ impl<'a> Resolver<'a> { // Ensure there is at most one `self` in the list let self_spans = items.iter().filter_map(|&(ref use_tree, _)| { - if let ast::UseTreeKind::Simple(ident) = use_tree.kind { - if ident.name == keywords::SelfValue.name() { + if let ast::UseTreeKind::Simple(..) = use_tree.kind { + if use_tree.ident().name == keywords::SelfValue.name() { return Some(use_tree.span); } } @@ -244,9 +245,9 @@ impl<'a> Resolver<'a> { match item.node { ItemKind::Use(ref use_tree) => { - // Just an empty prefix to start out + // Imports are resolved as global by default, add starting root segment. let prefix = ast::Path { - segments: vec![], + segments: use_tree.prefix.make_root().into_iter().collect(), span: use_tree.span, }; @@ -255,7 +256,7 @@ impl<'a> Resolver<'a> { ); } - ItemKind::ExternCrate(as_name) => { + ItemKind::ExternCrate(orig_name) => { self.crate_loader.process_item(item, &self.definitions); // n.b. we don't need to look at the path option here, because cstore already did @@ -274,7 +275,7 @@ impl<'a> Resolver<'a> { id: item.id, parent, imported_module: Cell::new(Some(module)), - subclass: ImportDirectiveSubclass::ExternCrate(as_name), + subclass: ImportDirectiveSubclass::ExternCrate(orig_name), span: item.span, module_path: Vec::new(), vis: Cell::new(vis), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a6b776125ae9..3a97d2767444 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -41,7 +41,7 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; -use syntax::codemap::{dummy_spanned, respan, CodeMap}; +use syntax::codemap::{dummy_spanned, respan, BytePos, CodeMap}; use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; @@ -57,7 +57,7 @@ use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics}; use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; -use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue}; +use syntax::feature_gate::{feature_err, GateIssue}; use syntax::parse::token; use syntax::ptr::P; @@ -162,6 +162,10 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, } +/// Combines an error with provided span and emits it +/// +/// This takes the error provided, combines it with the span and any additional spans inside the +/// error and emits it. fn resolve_error<'sess, 'a>(resolver: &'sess Resolver, span: Span, resolution_error: ResolutionError<'a>) { @@ -179,11 +183,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, E0401, "can't use type parameters from outer function"); err.span_label(span, "use of type variable from outer function"); + + let cm = resolver.session.codemap(); match outer_def { Def::SelfTy(_, maybe_impl_defid) => { if let Some(impl_span) = maybe_impl_defid.map_or(None, |def_id| resolver.definitions.opt_span(def_id)) { - let cm = resolver.session.codemap(); err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span), "`Self` type implicitely declared here, on the `impl`"); } @@ -206,12 +211,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, // Try to retrieve the span of the function signature and generate a new message with // a local type parameter let sugg_msg = "try using a local type parameter instead"; - if let Some((sugg_span, new_snippet)) = generate_local_type_param_snippet( - resolver.session.codemap(), span) { + if let Some((sugg_span, new_snippet)) = generate_local_type_param_snippet(cm, span) { // Suggest the modification to the user err.span_suggestion(sugg_span, sugg_msg, new_snippet); + } else if let Some(sp) = generate_fn_name_span(cm, span) { + err.span_label(sp, "try adding a local type parameter in this method instead"); } else { err.help("try using a local type parameter instead"); } @@ -407,19 +413,28 @@ fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span { impl_span } +fn generate_fn_name_span(cm: &CodeMap, span: Span) -> Option { + let prev_span = cm.span_extend_to_prev_str(span, "fn", true); + cm.span_to_snippet(prev_span).map(|snippet| { + let len = snippet.find(|c: char| !c.is_alphanumeric() && c != '_') + .expect("no label after fn"); + prev_span.with_hi(BytePos(prev_span.lo().0 + len as u32)) + }).ok() +} + /// Take the span of a type parameter in a function signature and try to generate a span for the /// function name (with generics) and a new snippet for this span with the pointed type parameter as /// a new local type parameter. /// /// For instance: -/// ``` +/// ```rust,ignore (pseudo-Rust) /// // Given span /// fn my_function(param: T) -/// ^ Original span +/// // ^ Original span /// /// // Result /// fn my_function(param: T) -/// ^^^^^^^^^^^ Generated span with snippet `my_function` +/// // ^^^^^^^^^^^ Generated span with snippet `my_function` /// ``` /// /// Attention: The method used is very fragile since it essentially duplicates the work of the @@ -428,17 +443,12 @@ fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span { fn generate_local_type_param_snippet(cm: &CodeMap, span: Span) -> Option<(Span, String)> { // Try to extend the span to the previous "fn" keyword to retrieve the function // signature - let sugg_span = cm.span_extend_to_prev_str(span, "fn"); + let sugg_span = cm.span_extend_to_prev_str(span, "fn", false); if sugg_span != span { if let Ok(snippet) = cm.span_to_snippet(sugg_span) { - use syntax::codemap::BytePos; - // Consume the function name - let mut offset = 0; - for c in snippet.chars().take_while(|c| c.is_ascii_alphanumeric() || - *c == '_') { - offset += c.len_utf8(); - } + let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_') + .expect("no label after fn"); // Consume the generics part of the function signature let mut bracket_counter = 0; @@ -480,7 +490,7 @@ struct BindingInfo { binding_mode: BindingMode, } -// Map from the name in a pattern to its binding mode. +/// Map from the name in a pattern to its binding mode. type BindingMap = FxHashMap; #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -675,6 +685,9 @@ impl<'a> PathSource<'a> { } } +/// Different kinds of symbols don't influence each other. +/// +/// Therefore, they have a separate universe (namespace). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum Namespace { TypeNS, @@ -682,6 +695,7 @@ pub enum Namespace { MacroNS, } +/// Just a helper ‒ separate structure for each namespace. #[derive(Clone, Default, Debug)] pub struct PerNS { value_ns: T, @@ -750,7 +764,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { // don't suggest placing a use before the prelude // import or other generated ones if item.span.ctxt().outer().expn_info().is_none() { - self.span = Some(item.span.with_hi(item.span.lo())); + self.span = Some(item.span.shrink_to_lo()); self.found_use = true; return; } @@ -762,12 +776,12 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { if item.span.ctxt().outer().expn_info().is_none() { // don't insert between attributes and an item if item.attrs.is_empty() { - self.span = Some(item.span.with_hi(item.span.lo())); + self.span = Some(item.span.shrink_to_lo()); } else { // find the first attribute on the item for attr in &item.attrs { if self.span.map_or(true, |span| attr.span < span) { - self.span = Some(attr.span.with_hi(attr.span.lo())); + self.span = Some(attr.span.shrink_to_lo()); } } } @@ -778,6 +792,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } } +/// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes. impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { fn visit_item(&mut self, item: &'tcx Item) { self.resolve_item(item); @@ -904,7 +919,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { fn visit_generics(&mut self, generics: &'tcx Generics) { // For type parameter defaults, we have to ban access // to following type parameters, as the Substs can only - // provide previous type parameters as they're built. + // provide previous type parameters as they're built. We + // put all the parameters on the ban list and then remove + // them one by one as they are processed and become available. let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); default_ban_rib.bindings.extend(generics.params.iter() .filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None }) @@ -980,6 +997,17 @@ enum RibKind<'a> { } /// One local scope. +/// +/// A rib represents a scope names can live in. Note that these appear in many places, not just +/// around braces. At any place where the list of accessible names (of the given namespace) +/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a +/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro, +/// etc. +/// +/// Different [rib kinds](enum.RibKind) are transparent for different names. +/// +/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When +/// resolving, the name is looked up from inside out. #[derive(Debug)] struct Rib<'a> { bindings: FxHashMap, @@ -995,6 +1023,11 @@ impl<'a> Rib<'a> { } } +/// An intermediate resolution result. +/// +/// This refers to the thing referred by a name. The difference between `Def` and `Item` is that +/// items are visible in their whole block, while defs only from the place they are defined +/// forward. enum LexicalScopeBinding<'a> { Item(&'a NameBinding<'a>), Def(Def), @@ -1025,7 +1058,26 @@ enum PathResult<'a> { } enum ModuleKind { + /// An anonymous module, eg. just a block. + /// + /// ``` + /// fn main() { + /// fn f() {} // (1) + /// { // This is an anonymous module + /// f(); // This resolves to (2) as we are inside the block. + /// fn f() {} // (2) + /// } + /// f(); // Resolves to (1) + /// } + /// ``` Block(NodeId), + /// Any module with a name. + /// + /// This could be: + /// + /// * A normal module ‒ either `mod from_file;` or `mod from_block { }`. + /// * A trait or an enum (it implicitly contains associated types, methods and variant + /// constructors). Def(Def, Name), } @@ -1310,6 +1362,9 @@ impl<'a> NameBinding<'a> { } /// Interns the names of the primitive types. +/// +/// All other types are defined somewhere and possibly imported, but the primitive ones need +/// special handling, since they have no place of origin. struct PrimitiveTypeTable { primitive_types: FxHashMap, } @@ -1344,6 +1399,8 @@ impl PrimitiveTypeTable { } /// The main resolver class. +/// +/// This is the visitor that walks the whole crate. pub struct Resolver<'a> { session: &'a Session, cstore: &'a CrateStore, @@ -1475,6 +1532,7 @@ pub struct Resolver<'a> { injected_crate: Option>, } +/// Nothing really interesting here, it just provides memory for the rest of the crate. pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, @@ -1520,10 +1578,12 @@ impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, _ => self.cstore.def_key(id).parent, - }.map(|index| DefId { index: index, ..id }) + }.map(|index| DefId { index, ..id }) } } +/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that +/// the resolver is no longer needed as all the relevant information is inline. impl<'a> hir::lowering::Resolver for Resolver<'a> { fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { self.resolve_hir_path_cb(path, is_value, @@ -1746,6 +1806,7 @@ impl<'a> Resolver<'a> { } } + /// Runs the function on each namespace. fn per_ns T>(&mut self, mut f: F) -> PerNS { PerNS { type_ns: f(self, TypeNS), @@ -2158,8 +2219,9 @@ impl<'a> Resolver<'a> { } ItemKind::Use(ref use_tree) => { + // Imports are resolved as global by default, add starting root segment. let path = Path { - segments: vec![], + segments: use_tree.prefix.make_root().into_iter().collect(), span: use_tree.span, }; self.resolve_use_tree(item.id, use_tree, &path); @@ -2294,7 +2356,6 @@ impl<'a> Resolver<'a> { None, &path, trait_ref.path.span, - trait_ref.path.segments.last().unwrap().span, PathSource::Trait(AliasPossibility::No) ).base_def(); if def != Def::Err { @@ -2725,8 +2786,7 @@ impl<'a> Resolver<'a> { let segments = &path.segments.iter() .map(|seg| respan(seg.span, seg.identifier)) .collect::>(); - let ident_span = path.segments.last().map_or(path.span, |seg| seg.span); - self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source) + self.smart_resolve_path_fragment(id, qself, segments, path.span, source) } fn smart_resolve_path_fragment(&mut self, @@ -2734,9 +2794,9 @@ impl<'a> Resolver<'a> { qself: Option<&QSelf>, path: &[SpannedIdent], span: Span, - ident_span: Span, source: PathSource) -> PathResolution { + let ident_span = path.last().map_or(span, |ident| ident.span); let ns = source.namespace(); let is_expected = &|def| source.is_expected(def); let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; @@ -3084,7 +3144,7 @@ impl<'a> Resolver<'a> { // Make sure `A::B` in `::B::C` is a trait item. let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], - span, span, PathSource::TraitItem(ns)); + span, PathSource::TraitItem(ns)); return Some(PathResolution::with_unresolved_segments( res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 )); @@ -3112,17 +3172,6 @@ impl<'a> Resolver<'a> { self.primitive_type_table.primitive_types .contains_key(&path[0].node.name) => { let prim = self.primitive_type_table.primitive_types[&path[0].node.name]; - match prim { - TyUint(UintTy::U128) | TyInt(IntTy::I128) => { - if !self.session.features_untracked().i128_type { - emit_feature_err(&self.session.parse_sess, - "i128_type", span, GateIssue::Language, - "128-bit type is unstable"); - - } - } - _ => {} - } PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), @@ -3201,7 +3250,7 @@ impl<'a> Resolver<'a> { // `$crate::a::b` module = Some(self.resolve_crate_root(ident.node.ctxt, true)); continue - } else if i == 1 && !token::Ident(ident.node).is_path_segment_keyword() { + } else if i == 1 && !token::is_path_segment_keyword(ident.node) { let prev_name = path[0].node.name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && @@ -3935,8 +3984,12 @@ impl<'a> Resolver<'a> { ty::Visibility::Restricted(self.current_module.normal_ancestor_id) } ast::VisibilityKind::Restricted { ref path, id, .. } => { - let def = self.smart_resolve_path(id, None, path, - PathSource::Visibility).base_def(); + // Visibilities are resolved as global by default, add starting root segment. + let segments = path.make_root().iter().chain(path.segments.iter()) + .map(|seg| respan(seg.span, seg.identifier)) + .collect::>(); + let def = self.smart_resolve_path_fragment(id, None, &segments, path.span, + PathSource::Visibility).base_def(); if def == Def::Err { ty::Visibility::Public } else { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 95fa0f3b52fe..0692a1e0d7f8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -268,7 +268,7 @@ impl<'a> base::Resolver for Resolver<'a> { if k > 0 { tokens.push(TokenTree::Token(path.span, Token::ModSep).into()); } - let tok = Token::Ident(segment.identifier); + let tok = Token::from_ast_ident(segment.identifier); tokens.push(TokenTree::Token(path.span, tok).into()); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 01c1ded94578..7036bdd0e2b0 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -625,7 +625,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } else { Some(self.resolve_crate_root(source.ctxt.modern(), false)) } - } else if is_extern && !token::Ident(source).is_path_segment_keyword() { + } else if is_extern && !token::is_path_segment_keyword(source) { let crate_id = self.crate_loader.resolve_crate_from_path(source.name, directive.span); let crate_root = @@ -667,11 +667,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } PathResult::Failed(span, msg, true) => { let (mut self_path, mut self_result) = (module_path.clone(), None); - if !self_path.is_empty() && - !token::Ident(self_path[0].node).is_path_segment_keyword() && - !(self_path.len() > 1 && - token::Ident(self_path[1].node).is_path_segment_keyword()) - { + let is_special = |ident| token::is_path_segment_keyword(ident) && + ident.name != keywords::CrateRoot.name(); + if !self_path.is_empty() && !is_special(self_path[0].node) && + !(self_path.len() > 1 && is_special(self_path[1].node)) { self_path[0].node.name = keywords::SelfValue.name(); self_result = Some(self.resolve_path(&self_path, None, false, span)); } @@ -1026,28 +1025,9 @@ fn import_path_to_string(names: &[SpannedIdent], if names.is_empty() { import_directive_subclass_to_string(subclass) } else { - // FIXME: Remove this entire logic after #48116 is fixed. - // - // Note that this code looks a little wonky, it's currently here to - // hopefully help debug #48116, but otherwise isn't intended to - // cause any problems. - let x = format!( - "{}::{}", - names_to_string(names), - import_directive_subclass_to_string(subclass), - ); - if names.is_empty() || x.starts_with("::") { - span_bug!( - span, - "invalid name `{}` at {:?}; global = {}, names = {:?}, subclass = {:?}", - x, - span, - global, - names, - subclass - ); - } - return x + format!("{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass)) } } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index d92025a6787d..3d4d8571c6e4 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1209,7 +1209,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) { self.process_macro_use(trait_item.span); - let vis_span = trait_item.span.empty(); + let vis_span = trait_item.span.shrink_to_lo(); match trait_item.node { ast::TraitItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( @@ -1342,7 +1342,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .map(::id_from_def_id); match use_tree.kind { - ast::UseTreeKind::Simple(ident) => { + ast::UseTreeKind::Simple(..) => { + let ident = use_tree.ident(); let path = ast::Path { segments: prefix.segments .iter() diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 490dc4e5ac4a..953747756517 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -13,6 +13,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] #![feature(custom_attribute)] +#![feature(macro_lifetime_matcher)] #![allow(unused_attributes)] #[macro_use] diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml new file mode 100644 index 000000000000..dc2a21cdab25 --- /dev/null +++ b/src/librustc_traits/Cargo.toml @@ -0,0 +1,18 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_traits" +version = "0.0.0" + +[lib] +name = "rustc_traits" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +bitflags = "1.0" +graphviz = { path = "../libgraphviz" } +log = { version = "0.4" } +rustc = { path = "../librustc" } +rustc_data_structures = { path = "../librustc_data_structures" } +syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs new file mode 100644 index 000000000000..1fe2f87128ab --- /dev/null +++ b/src/librustc_traits/dropck_outlives.rs @@ -0,0 +1,285 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::infer::canonical::{Canonical, QueryResult}; +use rustc::hir::def_id::DefId; +use rustc::traits::{FulfillmentContext, Normalized, ObligationCause}; +use rustc::traits::query::{CanonicalTyGoal, NoSolution}; +use rustc::traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; +use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use rustc::ty::subst::Subst; +use rustc::util::nodemap::FxHashSet; +use rustc_data_structures::sync::Lrc; +use syntax::codemap::{Span, DUMMY_SP}; +use util; + +crate fn dropck_outlives<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + goal: CanonicalTyGoal<'tcx>, +) -> Result>>>, NoSolution> { + debug!("dropck_outlives(goal={:#?})", goal); + + tcx.infer_ctxt().enter(|ref infcx| { + let tcx = infcx.tcx; + let ( + ParamEnvAnd { + param_env, + value: for_ty, + }, + canonical_inference_vars, + ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal); + + let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] }; + + // A stack of types left to process. Each round, we pop + // something from the stack and invoke + // `dtorck_constraint_for_ty`. This may produce new types that + // have to be pushed on the stack. This continues until we have explored + // all the reachable types from the type `for_ty`. + // + // Example: Imagine that we have the following code: + // + // ```rust + // struct A { + // value: B, + // children: Vec
, + // } + // + // struct B { + // value: u32 + // } + // + // fn f() { + // let a: A = ...; + // .. + // } // here, `a` is dropped + // ``` + // + // at the point where `a` is dropped, we need to figure out + // which types inside of `a` contain region data that may be + // accessed by any destructors in `a`. We begin by pushing `A` + // onto the stack, as that is the type of `a`. We will then + // invoke `dtorck_constraint_for_ty` which will expand `A` + // into the types of its fields `(B, Vec)`. These will get + // pushed onto the stack. Eventually, expanding `Vec` will + // lead to us trying to push `A` a second time -- to prevent + // infinite recusion, we notice that `A` was already pushed + // once and stop. + let mut ty_stack = vec![(for_ty, 0)]; + + // Set used to detect infinite recursion. + let mut ty_set = FxHashSet(); + + let fulfill_cx = &mut FulfillmentContext::new(); + + let cause = ObligationCause::dummy(); + while let Some((ty, depth)) = ty_stack.pop() { + let DtorckConstraint { + dtorck_types, + outlives, + overflows, + } = dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty)?; + + // "outlives" represent types/regions that may be touched + // by a destructor. + result.kinds.extend(outlives); + result.overflows.extend(overflows); + + // dtorck types are "types that will get dropped but which + // do not themselves define a destructor", more or less. We have + // to push them onto the stack to be expanded. + for ty in dtorck_types { + match infcx.at(&cause, param_env).normalize(&ty) { + Ok(Normalized { + value: ty, + obligations, + }) => { + fulfill_cx.register_predicate_obligations(infcx, obligations); + + debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + + match ty.sty { + // All parameters live for the duration of the + // function. + ty::TyParam(..) => {} + + // A projection that we couldn't resolve - it + // might have a destructor. + ty::TyProjection(..) | ty::TyAnon(..) => { + result.kinds.push(ty.into()); + } + + _ => { + if ty_set.insert(ty) { + ty_stack.push((ty, depth + 1)); + } + } + } + } + + // We don't actually expect to fail to normalize. + // That implies a WF error somewhere else. + Err(NoSolution) => { + return Err(NoSolution); + } + } + } + } + + debug!("dropck_outlives: result = {:#?}", result); + + util::make_query_response(infcx, canonical_inference_vars, result, fulfill_cx) + }) +} + +/// Return a set of constraints that needs to be satisfied in +/// order for `ty` to be valid for destruction. +fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + span: Span, + for_ty: Ty<'tcx>, + depth: usize, + ty: Ty<'tcx>, +) -> Result, NoSolution> { + debug!( + "dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", + span, for_ty, depth, ty + ); + + if depth >= tcx.sess.recursion_limit.get() { + return Ok(DtorckConstraint { + outlives: vec![], + dtorck_types: vec![], + overflows: vec![ty], + }); + } + + let result = match ty.sty { + ty::TyBool + | ty::TyChar + | ty::TyInt(_) + | ty::TyUint(_) + | ty::TyFloat(_) + | ty::TyStr + | ty::TyNever + | ty::TyForeign(..) + | ty::TyRawPtr(..) + | ty::TyRef(..) + | ty::TyFnDef(..) + | ty::TyFnPtr(_) + | ty::TyGeneratorWitness(..) => { + // these types never have a destructor + Ok(DtorckConstraint::empty()) + } + + ty::TyArray(ety, _) | ty::TySlice(ety) => { + // single-element containers, behave like their element + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety) + } + + ty::TyTuple(tys) => tys.iter() + .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) + .collect(), + + ty::TyClosure(def_id, substs) => substs + .upvar_tys(def_id, tcx) + .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) + .collect(), + + ty::TyGenerator(def_id, substs, _) => { + // Note that the interior types are ignored here. + // Any type reachable inside the interior must also be reachable + // through the upvars. + substs + .upvar_tys(def_id, tcx) + .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) + .collect() + } + + ty::TyAdt(def, substs) => { + let DtorckConstraint { + dtorck_types, + outlives, + overflows, + } = tcx.at(span).adt_dtorck_constraint(def.did)?; + Ok(DtorckConstraint { + // FIXME: we can try to recursively `dtorck_constraint_on_ty` + // there, but that needs some way to handle cycles. + dtorck_types: dtorck_types.subst(tcx, substs), + outlives: outlives.subst(tcx, substs), + overflows: overflows.subst(tcx, substs), + }) + } + + // Objects must be alive in order for their destructor + // to be called. + ty::TyDynamic(..) => Ok(DtorckConstraint { + outlives: vec![ty.into()], + dtorck_types: vec![], + overflows: vec![], + }), + + // Types that can't be resolved. Pass them forward. + ty::TyProjection(..) | ty::TyAnon(..) | ty::TyParam(..) => Ok(DtorckConstraint { + outlives: vec![], + dtorck_types: vec![ty], + overflows: vec![], + }), + + ty::TyInfer(..) | ty::TyError => { + // By the time this code runs, all type variables ought to + // be fully resolved. + Err(NoSolution) + } + }; + + debug!("dtorck_constraint_for_ty({:?}) = {:?}", ty, result); + result +} + +/// Calculates the dtorck constraint for a type. +crate fn adt_dtorck_constraint<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, +) -> Result, NoSolution> { + let def = tcx.adt_def(def_id); + let span = tcx.def_span(def_id); + debug!("dtorck_constraint: {:?}", def); + + if def.is_phantom_data() { + let result = DtorckConstraint { + outlives: vec![], + dtorck_types: vec![tcx.mk_param_from_def(&tcx.generics_of(def_id).types[0])], + overflows: vec![], + }; + debug!("dtorck_constraint: {:?} => {:?}", def, result); + return Ok(result); + } + + let mut result = def.all_fields() + .map(|field| tcx.type_of(field.did)) + .map(|fty| dtorck_constraint_for_ty(tcx, span, fty, 0, fty)) + .collect::>()?; + result.outlives.extend(tcx.destructor_constraints(def)); + dedup_dtorck_constraint(&mut result); + + debug!("dtorck_constraint: {:?} => {:?}", def, result); + + Ok(result) +} + +fn dedup_dtorck_constraint<'tcx>(c: &mut DtorckConstraint<'tcx>) { + let mut outlives = FxHashSet(); + let mut dtorck_types = FxHashSet(); + + c.outlives.retain(|&val| outlives.replace(val).is_none()); + c.dtorck_types + .retain(|&val| dtorck_types.replace(val).is_none()); +} diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs new file mode 100644 index 000000000000..90f368edeeca --- /dev/null +++ b/src/librustc_traits/lib.rs @@ -0,0 +1,46 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! New recursive solver modeled on Chalk's recursive solver. Most of +//! the guts are broken up into modules; see the comments in those modules. + +#![deny(warnings)] + +#![feature(crate_visibility_modifier)] +#![cfg_attr(stage0, feature(match_default_bindings))] +#![cfg_attr(stage0, feature(underscore_lifetimes))] + +#[macro_use] +extern crate log; +#[macro_use] +extern crate rustc; +extern crate rustc_data_structures; +extern crate syntax; +extern crate syntax_pos; + +mod dropck_outlives; +mod normalize_projection_ty; +mod normalize_erasing_regions; +mod util; +pub mod lowering; + +use rustc::ty::maps::Providers; + +pub fn provide(p: &mut Providers) { + *p = Providers { + dropck_outlives: dropck_outlives::dropck_outlives, + adt_dtorck_constraint: dropck_outlives::adt_dtorck_constraint, + normalize_projection_ty: normalize_projection_ty::normalize_projection_ty, + normalize_ty_after_erasing_regions: + normalize_erasing_regions::normalize_ty_after_erasing_regions, + program_clauses_for: lowering::program_clauses_for, + ..*p + }; +} diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs new file mode 100644 index 000000000000..1092e826a35f --- /dev/null +++ b/src/librustc_traits/lowering.rs @@ -0,0 +1,225 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::hir::{self, ImplPolarity}; +use rustc::hir::def_id::DefId; +use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc::ty::{self, TyCtxt}; +use rustc::ty::subst::Substs; +use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom}; +use syntax::ast; +use rustc_data_structures::sync::Lrc; + +trait Lower { + /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type. + fn lower(&self) -> T; +} + +impl Lower> for Vec where T: Lower { + fn lower(&self) -> Vec { + self.iter().map(|item| item.lower()).collect() + } +} + +impl<'tcx> Lower> for ty::TraitPredicate<'tcx> { + fn lower(&self) -> WhereClauseAtom<'tcx> { + WhereClauseAtom::Implemented(*self) + } +} + +impl<'tcx> Lower> for ty::ProjectionPredicate<'tcx> { + fn lower(&self) -> WhereClauseAtom<'tcx> { + WhereClauseAtom::ProjectionEq(*self) + } +} + +impl<'tcx, T> Lower> for T where T: Lower> { + fn lower(&self) -> DomainGoal<'tcx> { + DomainGoal::Holds(self.lower()) + } +} + +impl<'tcx> Lower> for ty::RegionOutlivesPredicate<'tcx> { + fn lower(&self) -> DomainGoal<'tcx> { + DomainGoal::RegionOutlives(*self) + } +} + +impl<'tcx> Lower> for ty::TypeOutlivesPredicate<'tcx> { + fn lower(&self) -> DomainGoal<'tcx> { + DomainGoal::TypeOutlives(*self) + } +} + +/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic +/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things +/// in that leaf-form (i.e. `Holds(Implemented(Binder))` in the previous +/// example), we model them with quantified goals, e.g. as for the previous example: +/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like +/// `Binder`. +/// +/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we +/// can directly lower to a leaf goal instead of a quantified goal. +impl<'tcx, T> Lower> for ty::Binder + where T: Lower> + ty::fold::TypeFoldable<'tcx> + Copy +{ + fn lower(&self) -> Goal<'tcx> { + match self.no_late_bound_regions() { + Some(p) => p.lower().into(), + None => Goal::Quantified( + QuantifierKind::Universal, + Box::new(self.map_bound(|p| p.lower().into())) + ), + } + } +} + +impl<'tcx> Lower> for ty::Predicate<'tcx> { + fn lower(&self) -> Goal<'tcx> { + use rustc::ty::Predicate::*; + + match self { + Trait(predicate) => predicate.lower(), + RegionOutlives(predicate) => predicate.lower(), + TypeOutlives(predicate) => predicate.lower(), + Projection(predicate) => predicate.lower(), + WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(), + ObjectSafe(..) | + ClosureKind(..) | + Subtype(..) | + ConstEvaluatable(..) => unimplemented!(), + } + } +} + +crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> Lrc>> +{ + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item = tcx.hir.expect_item(node_id); + match item.node { + hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id), + hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id), + + // FIXME: other constructions e.g. traits, associated types... + _ => Lrc::new(vec![]), + } +} + +fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> Lrc>> +{ + // Rule Implemented-From-Env (see rustc guide) + // + // `trait Trait where WC { .. } // P0 == Self` + // + // ``` + // forall { + // Implemented(Self: Trait) :- FromEnv(Self: Trait) + // } + // ``` + + // `Self: Trait` + let trait_pred = ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id, + substs: Substs::identity_for_item(tcx, def_id) + } + }; + // `FromEnv(Self: Trait)` + let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower())); + // `Implemented(Self: Trait)` + let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred)); + + // `Implemented(Self: Trait) :- FromEnv(Self: Trait)` + let clause = Clause::Implies(vec![from_env], impl_trait); + Lrc::new(vec![clause]) +} + +fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> Lrc>> +{ + if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { + return Lrc::new(vec![]); + } + + // Rule Implemented-From-Impl (see rustc guide) + // + // `impl Trait for A0 where WC { .. }` + // + // ``` + // forall { + // Implemented(A0: Trait) :- WC + // } + // ``` + + let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); + // `Implemented(A0: Trait)` + let trait_pred = ty::TraitPredicate { trait_ref }.lower(); + // `WC` + let where_clauses = tcx.predicates_of(def_id).predicates.lower(); + + // `Implemented(A0: Trait) :- WC` + let clause = Clause::Implies(where_clauses, trait_pred); + Lrc::new(vec![clause]) +} + +pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + if !tcx.features().rustc_attrs { + return; + } + + let mut visitor = ClauseDumper { tcx }; + tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); +} + +struct ClauseDumper<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, +} + +impl <'a, 'tcx> ClauseDumper<'a, 'tcx > { + fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { + let def_id = self.tcx.hir.local_def_id(node_id); + for attr in attrs { + if attr.check_name("rustc_dump_program_clauses") { + let clauses = self.tcx.program_clauses_for(def_id); + for clause in &*clauses { + self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit(); + } + } + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.tcx.hir) + } + + fn visit_item(&mut self, item: &'tcx hir::Item) { + self.process_attrs(item.id, &item.attrs); + intravisit::walk_item(self, item); + } + + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.process_attrs(trait_item.id, &trait_item.attrs); + intravisit::walk_trait_item(self, trait_item); + } + + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { + self.process_attrs(impl_item.id, &impl_item.attrs); + intravisit::walk_impl_item(self, impl_item); + } + + fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { + self.process_attrs(s.id, &s.attrs); + intravisit::walk_struct_field(self, s); + } +} diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs new file mode 100644 index 000000000000..14f8694dbf72 --- /dev/null +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -0,0 +1,62 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::traits::{Normalized, ObligationCause}; +use rustc::traits::query::NoSolution; +use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use rustc::util::common::CellUsizeExt; + +crate fn normalize_ty_after_erasing_regions<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + goal: ParamEnvAnd<'tcx, Ty<'tcx>>, +) -> Ty<'tcx> { + let ParamEnvAnd { param_env, value } = goal; + tcx.sess + .perf_stats + .normalize_ty_after_erasing_regions + .increment(); + tcx.infer_ctxt().enter(|infcx| { + let cause = ObligationCause::dummy(); + match infcx.at(&cause, param_env).normalize(&value) { + Ok(Normalized { + value: normalized_value, + obligations: normalized_obligations, + }) => { + // We don't care about the `obligations`; they are + // always only region relations, and we are about to + // erase those anyway: + debug_assert_eq!( + normalized_obligations + .iter() + .find(|p| not_outlives_predicate(&p.predicate)), + None, + ); + + let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value); + let normalized_value = infcx.tcx.erase_regions(&normalized_value); + tcx.lift_to_global(&normalized_value).unwrap() + } + Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), + } + }) +} + +fn not_outlives_predicate(p: &ty::Predicate<'_>) -> bool { + match p { + ty::Predicate::RegionOutlives(..) | ty::Predicate::TypeOutlives(..) => false, + ty::Predicate::Trait(..) + | ty::Predicate::Projection(..) + | ty::Predicate::WellFormed(..) + | ty::Predicate::ObjectSafe(..) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::Subtype(..) + | ty::Predicate::ConstEvaluatable(..) => true, + } +} diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs new file mode 100644 index 000000000000..62d5ef11551c --- /dev/null +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -0,0 +1,55 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::infer::canonical::{Canonical, QueryResult}; +use rustc::traits::{self, FulfillmentContext, Normalized, ObligationCause, + SelectionContext}; +use rustc::traits::query::{CanonicalProjectionGoal, NoSolution, normalize::NormalizationResult}; +use rustc::ty::{ParamEnvAnd, TyCtxt}; +use rustc::util::common::CellUsizeExt; +use rustc_data_structures::sync::Lrc; +use syntax::ast::DUMMY_NODE_ID; +use syntax_pos::DUMMY_SP; +use util; + +crate fn normalize_projection_ty<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + goal: CanonicalProjectionGoal<'tcx>, +) -> Result>>>, NoSolution> { + debug!("normalize_provider(goal={:#?})", goal); + + tcx.sess.perf_stats.normalize_projection_ty.increment(); + tcx.infer_ctxt().enter(|ref infcx| { + let ( + ParamEnvAnd { + param_env, + value: goal, + }, + canonical_inference_vars, + ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal); + let fulfill_cx = &mut FulfillmentContext::new(); + let selcx = &mut SelectionContext::new(infcx); + let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID); + let Normalized { + value: answer, + obligations, + } = traits::normalize_projection_type(selcx, param_env, goal, cause, 0); + fulfill_cx.register_predicate_obligations(infcx, obligations); + + // Now that we have fulfilled as much as we can, create a solution + // from what we've learned. + util::make_query_response( + infcx, + canonical_inference_vars, + NormalizationResult { normalized_ty: answer }, + fulfill_cx, + ) + }) +} diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs new file mode 100644 index 000000000000..bff070ab73de --- /dev/null +++ b/src/librustc_traits/util.rs @@ -0,0 +1,117 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::infer::InferCtxt; +use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints, + QueryResult}; +use rustc::infer::region_constraints::{Constraint, RegionConstraintData}; +use rustc::traits::{FulfillmentContext, TraitEngine}; +use rustc::traits::query::NoSolution; +use rustc::ty; +use std::fmt::Debug; + +/// The canonicalization form of `QueryResult<'tcx, T>`. +type CanonicalizedQueryResult<'gcx, 'tcx, T> = + as Canonicalize<'gcx, 'tcx>>::Canonicalized; + +crate fn make_query_response<'gcx, 'tcx, T>( + infcx: &InferCtxt<'_, 'gcx, 'tcx>, + inference_vars: CanonicalVarValues<'tcx>, + answer: T, + fulfill_cx: &mut FulfillmentContext<'tcx>, +) -> Result, NoSolution> +where + T: Debug, + QueryResult<'tcx, T>: Canonicalize<'gcx, 'tcx>, +{ + let tcx = infcx.tcx; + + debug!( + "make_query_response(\ + inference_vars={:?}, \ + answer={:?})", + inference_vars, answer, + ); + + // Select everything, returning errors. + let true_errors = match fulfill_cx.select_where_possible(infcx) { + Ok(()) => vec![], + Err(errors) => errors, + }; + debug!("true_errors = {:#?}", true_errors); + + if !true_errors.is_empty() { + // FIXME -- we don't indicate *why* we failed to solve + debug!("make_query_response: true_errors={:#?}", true_errors); + return Err(NoSolution); + } + + // Anything left unselected *now* must be an ambiguity. + let ambig_errors = match fulfill_cx.select_all_or_error(infcx) { + Ok(()) => vec![], + Err(errors) => errors, + }; + debug!("ambig_errors = {:#?}", ambig_errors); + + let region_obligations = infcx.take_registered_region_obligations(); + + let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| { + let RegionConstraintData { + constraints, + verifys, + givens, + } = region_constraints; + + assert!(verifys.is_empty()); + assert!(givens.is_empty()); + + let region_outlives: Vec<_> = constraints + .into_iter() + .map(|(k, _)| match *k { + Constraint::VarSubVar(v1, v2) => { + (tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2))) + } + Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2), + Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))), + Constraint::RegSubReg(r1, r2) => (r1, r2), + }) + .collect(); + + let ty_outlives: Vec<_> = region_obligations + .into_iter() + .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)) + .collect(); + + (region_outlives, ty_outlives) + }); + + let certainty = if ambig_errors.is_empty() { + Certainty::Proven + } else { + Certainty::Ambiguous + }; + + let (canonical_result, _) = infcx.canonicalize_response(&QueryResult { + var_values: inference_vars, + region_constraints: QueryRegionConstraints { + region_outlives, + ty_outlives, + }, + certainty, + value: answer, + }); + + debug!( + "make_query_response: canonical_result = {:#?}", + canonical_result + ); + + Ok(canonical_result) +} diff --git a/src/librustc_trans/README.md b/src/librustc_trans/README.md index b69d632a6a0d..d1868ba2abb1 100644 --- a/src/librustc_trans/README.md +++ b/src/librustc_trans/README.md @@ -1,7 +1,7 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - The `trans` crate contains the code to convert from MIR into LLVM IR, and then from LLVM IR into machine code. In general it contains code that runs towards the end of the compilation process. + +For more information about how trans works, see the [rustc guide]. + +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index ee0f2415bd80..19ae1fa0478e 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -30,6 +30,7 @@ use cabi_sparc64; use cabi_nvptx; use cabi_nvptx64; use cabi_hexagon; +use cabi_wasm32; use mir::place::PlaceRef; use mir::operand::OperandValue; use type_::Type; @@ -650,7 +651,7 @@ impl<'a, 'tcx> FnType<'tcx> { -> Self { let fn_ty = instance.ty(cx.tcx); let sig = ty_fn_sig(cx, fn_ty); - let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); FnType::new(cx, sig, &[]) } @@ -722,7 +723,7 @@ impl<'a, 'tcx> FnType<'tcx> { assert!(!sig.variadic && extra_args.is_empty()); match sig.inputs().last().unwrap().sty { - ty::TyTuple(ref tupled_arguments, _) => { + ty::TyTuple(ref tupled_arguments) => { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; tupled_arguments } @@ -778,7 +779,7 @@ impl<'a, 'tcx> FnType<'tcx> { // HACK(eddyb) LLVM inserts `llvm.assume` calls when inlining functions // with align attributes, and those calls later block optimizations. - if !is_return { + if !is_return && !cx.tcx.sess.opts.debugging_opts.arg_align_attributes { attrs.pointee_align = None; } @@ -948,7 +949,13 @@ impl<'a, 'tcx> FnType<'tcx> { "powerpc64" => cabi_powerpc64::compute_abi_info(cx, self), "s390x" => cabi_s390x::compute_abi_info(cx, self), "asmjs" => cabi_asmjs::compute_abi_info(cx, self), - "wasm32" => cabi_asmjs::compute_abi_info(cx, self), + "wasm32" => { + if cx.sess().opts.target_triple.triple().contains("emscripten") { + cabi_asmjs::compute_abi_info(cx, self) + } else { + cabi_wasm32::compute_abi_info(cx, self) + } + } "msp430" => cabi_msp430::compute_abi_info(self), "sparc" => cabi_sparc::compute_abi_info(cx, self), "sparc64" => cabi_sparc64::compute_abi_info(cx, self), diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index d5ec8d1b5526..c968b8525a5b 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -11,11 +11,14 @@ use std::ffi::{CStr, CString}; -use rustc::hir::TransFnAttrFlags; +use rustc::hir::{self, TransFnAttrFlags}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::session::config::Sanitizer; +use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::fx::FxHashMap; use llvm::{self, Attribute, ValueRef}; use llvm::AttributePlace::Function; @@ -89,6 +92,11 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { _ => {} } + // probestack doesn't play nice either with pgo-gen. + if cx.sess().opts.debugging_opts.pgo_gen.is_some() { + return; + } + // Flag our internal `__rust_probestack` function as the stack probe symbol. // This is defined in the `compiler-builtins` crate for each architecture. llvm::AddFunctionAttrStringValue( @@ -139,6 +147,20 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { llfn, llvm::AttributePlace::Function, cstr("target-features\0"), &val); } + + // Note that currently the `wasm-import-module` doesn't do anything, but + // eventually LLVM 7 should read this and ferry the appropriate import + // module to the output file. + if cx.tcx.sess.target.target.arch == "wasm32" { + if let Some(module) = wasm_import_module(cx.tcx, id) { + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr("wasm-import-module\0"), + &module, + ); + } + } } fn cstr(s: &'static str) -> &CStr { @@ -148,9 +170,76 @@ fn cstr(s: &'static str) -> &CStr { pub fn provide(providers: &mut Providers) { providers.target_features_whitelist = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(llvm_util::target_feature_whitelist(tcx.sess) - .iter() - .map(|c| c.to_string()) - .collect()) + if tcx.sess.opts.actually_rustdoc { + // rustdoc needs to be able to document functions that use all the features, so + // whitelist them all + Lrc::new(llvm_util::all_known_features() + .map(|c| c.to_string()) + .collect()) + } else { + Lrc::new(llvm_util::target_feature_whitelist(tcx.sess) + .iter() + .map(|c| c.to_string()) + .collect()) + } }; + + providers.wasm_custom_sections = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + let mut finder = WasmSectionFinder { tcx, list: Vec::new() }; + tcx.hir.krate().visit_all_item_likes(&mut finder); + Lrc::new(finder.list) + }; + + provide_extern(providers); +} + +struct WasmSectionFinder<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + list: Vec, +} + +impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for WasmSectionFinder<'a, 'tcx> { + fn visit_item(&mut self, i: &'tcx hir::Item) { + match i.node { + hir::ItemConst(..) => {} + _ => return, + } + if i.attrs.iter().any(|i| i.check_name("wasm_custom_section")) { + self.list.push(self.tcx.hir.local_def_id(i.id)); + } + } + + fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {} + + fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {} +} + +pub fn provide_extern(providers: &mut Providers) { + providers.wasm_import_module_map = |tcx, cnum| { + let mut ret = FxHashMap(); + for lib in tcx.foreign_modules(cnum).iter() { + let attrs = tcx.get_attrs(lib.def_id); + let mut module = None; + for attr in attrs.iter().filter(|a| a.check_name("wasm_import_module")) { + module = attr.value_str(); + } + let module = match module { + Some(s) => s, + None => continue, + }; + for id in lib.foreign_items.iter() { + assert_eq!(id.krate, cnum); + ret.insert(*id, module.to_string()); + } + } + + Lrc::new(ret) + } +} + +fn wasm_import_module(tcx: TyCtxt, id: DefId) -> Option { + tcx.wasm_import_module_map(id.krate) + .get(&id) + .map(|s| CString::new(&s[..]).unwrap()) } diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs index ecf7bf5036e0..a5649e98baa7 100644 --- a/src/librustc_trans/back/command.rs +++ b/src/librustc_trans/back/command.rs @@ -132,6 +132,13 @@ impl Command { return false } + // Right now LLD doesn't support the `@` syntax of passing an argument + // through files, so regardless of the platform we try to go to the OS + // on this one. + if let Program::Lld(..) = self.program { + return false + } + // Ok so on Windows to spawn a process is 32,768 characters in its // command line [1]. Unfortunately we don't actually have access to that // as it's calculated just before spawning. Instead we perform a diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 636b3984117d..4ffc71ba4703 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use back::wasm; use cc::windows_registry; use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::bytecode::RLIB_BYTECODE_EXTENSION; @@ -30,6 +31,8 @@ use rustc::util::fs::fix_windows_verbatim_for_gcc; use rustc::hir::def_id::CrateNum; use tempdir::TempDir; use rustc_back::{PanicStrategy, RelroLevel}; +use rustc_back::target::TargetTriple; +use rustc_data_structures::fx::FxHashSet; use context::get_reloc_model; use llvm; @@ -80,7 +83,7 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command) { } }; - let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe"); + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s) .or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref())) @@ -690,8 +693,8 @@ fn link_natively(sess: &Session, let mut i = 0; loop { i += 1; - prog = time(sess.time_passes(), "running linker", || { - exec_linker(sess, &mut cmd, tmpdir) + prog = time(sess, "running linker", || { + exec_linker(sess, &mut cmd, out_filename, tmpdir) }); let output = match prog { Ok(ref output) => output, @@ -711,6 +714,7 @@ fn link_natively(sess: &Session, // linking executables as pie. Different versions of gcc seem to use // different quotes in the error message so don't check for them. if sess.target.target.options.linker_is_gnu && + sess.linker_flavor() != LinkerFlavor::Ld && (out.contains("unrecognized command line option") || out.contains("unknown argument")) && out.contains("-no-pie") && @@ -810,9 +814,15 @@ fn link_natively(sess: &Session, Err(e) => sess.fatal(&format!("failed to run dsymutil: {}", e)), } } + + if sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown") { + wasm::rewrite_imports(&out_filename, &trans.crate_info.wasm_imports); + wasm::add_custom_sections(&out_filename, + &trans.crate_info.wasm_custom_sections); + } } -fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) +fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: &Path) -> io::Result { // When attempting to spawn the linker we run a risk of blowing out the @@ -826,12 +836,19 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) // there instead of looking at the command line. if !cmd.very_likely_to_exceed_some_spawn_limit() { match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() { - Ok(child) => return child.wait_with_output(), - Err(ref e) if command_line_too_big(e) => {} + Ok(child) => { + let output = child.wait_with_output(); + flush_linked_file(&output, out_filename)?; + return output; + } + Err(ref e) if command_line_too_big(e) => { + info!("command line to linker was too big: {}", e); + } Err(e) => return Err(e) } } + info!("falling back to passing arguments to linker via an @-file"); let mut cmd2 = cmd.clone(); let mut args = String::new(); for arg in cmd2.take_args() { @@ -856,7 +873,38 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) }; fs::write(&file, &bytes)?; cmd2.arg(format!("@{}", file.display())); - return cmd2.output(); + info!("invoking linker {:?}", cmd2); + let output = cmd2.output(); + flush_linked_file(&output, out_filename)?; + return output; + + #[cfg(unix)] + fn flush_linked_file(_: &io::Result, _: &Path) -> io::Result<()> { + Ok(()) + } + + #[cfg(windows)] + fn flush_linked_file(command_output: &io::Result, out_filename: &Path) + -> io::Result<()> + { + // On Windows, under high I/O load, output buffers are sometimes not flushed, + // even long after process exit, causing nasty, non-reproducible output bugs. + // + // File::sync_all() calls FlushFileBuffers() down the line, which solves the problem. + // + // А full writeup of the original Chrome bug can be found at + // randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp + + if let &Ok(ref out) = command_output { + if out.status.success() { + if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) { + of.sync_all()?; + } + } + } + + Ok(()) + } #[cfg(unix)] fn command_line_too_big(err: &io::Error) -> bool { @@ -996,8 +1044,9 @@ fn link_args(cmd: &mut Linker, } else { // recent versions of gcc can be configured to generate position // independent executables by default. We have to pass -no-pie to - // explicitly turn that off. - if sess.target.target.options.linker_is_gnu { + // explicitly turn that off. Not applicable to ld. + if sess.target.target.options.linker_is_gnu + && sess.linker_flavor() != LinkerFlavor::Ld { cmd.no_position_independent_executable(); } } @@ -1014,7 +1063,11 @@ fn link_args(cmd: &mut Linker, RelroLevel::Partial => { cmd.partial_relro(); }, - RelroLevel::Off => {}, + RelroLevel::Off => { + cmd.no_relro(); + }, + RelroLevel::None => { + }, } // Pass optimization flags down to the linker. @@ -1070,12 +1123,16 @@ fn link_args(cmd: &mut Linker, cmd.build_static_executable(); } + if sess.opts.debugging_opts.pgo_gen.is_some() { + cmd.pgo_gen(); + } + // FIXME (#2397): At some point we want to rpath our guesses as to // where extern libraries might live, based on the // addl_lib_search_paths if sess.opts.cg.rpath { let sysroot = sess.sysroot(); - let target_triple = &sess.opts.target_triple; + let target_triple = sess.opts.target_triple.triple(); let mut get_install_prefix_lib_path = || { let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX"); let tlib = filesearch::relative_target_lib_path(sysroot, target_triple); @@ -1166,9 +1223,56 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // crates. let deps = &trans.crate_info.used_crates_dynamic; + // There's a few internal crates in the standard library (aka libcore and + // libstd) which actually have a circular dependence upon one another. This + // currently arises through "weak lang items" where libcore requires things + // like `rust_begin_unwind` but libstd ends up defining it. To get this + // circular dependence to work correctly in all situations we'll need to be + // sure to correctly apply the `--start-group` and `--end-group` options to + // GNU linkers, otherwise if we don't use any other symbol from the standard + // library it'll get discarded and the whole application won't link. + // + // In this loop we're calculating the `group_end`, after which crate to + // pass `--end-group` and `group_start`, before which crate to pass + // `--start-group`. We currently do this by passing `--end-group` after + // the first crate (when iterating backwards) that requires a lang item + // defined somewhere else. Once that's set then when we've defined all the + // necessary lang items we'll pass `--start-group`. + // + // Note that this isn't amazing logic for now but it should do the trick + // for the current implementation of the standard library. + let mut group_end = None; + let mut group_start = None; + let mut end_with = FxHashSet(); + let info = &trans.crate_info; + for &(cnum, _) in deps.iter().rev() { + if let Some(missing) = info.missing_lang_items.get(&cnum) { + end_with.extend(missing.iter().cloned()); + if end_with.len() > 0 && group_end.is_none() { + group_end = Some(cnum); + } + } + end_with.retain(|item| info.lang_item_to_crate.get(item) != Some(&cnum)); + if end_with.len() == 0 && group_end.is_some() { + group_start = Some(cnum); + break + } + } + + // If we didn't end up filling in all lang items from upstream crates then + // we'll be filling it in with our crate. This probably means we're the + // standard library itself, so skip this for now. + if group_end.is_some() && group_start.is_none() { + group_end = None; + } + let mut compiler_builtins = None; for &(cnum, _) in deps.iter() { + if group_start == Some(cnum) { + cmd.group_start(); + } + // We may not pass all crates through to the linker. Some crates may // appear statically in an existing dylib, meaning we'll pick up all the // symbols from the dylib. @@ -1195,6 +1299,10 @@ fn add_upstream_rust_crates(cmd: &mut Linker, add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0) } } + + if group_end == Some(cnum) { + cmd.group_end(); + } } // compiler-builtins are always placed last to ensure that they're @@ -1317,7 +1425,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib - time(sess.time_passes(), &format!("altering {}.rlib", name), || { + time(sess, &format!("altering {}.rlib", name), || { let cfg = archive_config(sess, &dst, Some(cratepath)); let mut archive = ArchiveBuilder::new(cfg); archive.update_symbols(); diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 3fe667f15437..ebcf06d63be2 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -113,9 +113,11 @@ pub trait Linker { fn gc_sections(&mut self, keep_metadata: bool); fn position_independent_executable(&mut self); fn no_position_independent_executable(&mut self); - fn partial_relro(&mut self); fn full_relro(&mut self); + fn partial_relro(&mut self); + fn no_relro(&mut self); fn optimize(&mut self); + fn pgo_gen(&mut self); fn debuginfo(&mut self); fn no_default_libraries(&mut self); fn build_dylib(&mut self, out_filename: &Path); @@ -123,6 +125,8 @@ pub trait Linker { fn args(&mut self, args: &[String]); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); fn subsystem(&mut self, subsystem: &str); + fn group_start(&mut self); + fn group_end(&mut self); // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?). fn finalize(&mut self) -> Command; } @@ -188,8 +192,9 @@ impl<'a> Linker for GccLinker<'a> { fn add_object(&mut self, path: &Path) { self.cmd.arg(path); } fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); } fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); } - fn partial_relro(&mut self) { self.linker_arg("-z,relro"); } fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); } + fn partial_relro(&mut self) { self.linker_arg("-z,relro"); } + fn no_relro(&mut self) { self.linker_arg("-z,norelro"); } fn build_static_executable(&mut self) { self.cmd.arg("-static"); } fn args(&mut self, args: &[String]) { self.cmd.args(args); } @@ -278,8 +283,37 @@ impl<'a> Linker for GccLinker<'a> { } } + fn pgo_gen(&mut self) { + if !self.sess.target.target.options.linker_is_gnu { return } + + // If we're doing PGO generation stuff and on a GNU-like linker, use the + // "-u" flag to properly pull in the profiler runtime bits. + // + // This is because LLVM otherwise won't add the needed initialization + // for us on Linux (though the extra flag should be harmless if it + // does). + // + // See https://reviews.llvm.org/D14033 and https://reviews.llvm.org/D14030. + // + // Though it may be worth to try to revert those changes upstream, since + // the overhead of the initialization should be minor. + self.cmd.arg("-u"); + self.cmd.arg("__llvm_profile_runtime"); + } + fn debuginfo(&mut self) { - // Don't do anything special here for GNU-style linkers. + match self.sess.opts.debuginfo { + DebugInfoLevel::NoDebugInfo => { + // If we are building without debuginfo enabled and we were called with + // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo + // found when linking to get rid of symbols from libstd. + match self.sess.opts.debugging_opts.strip_debuginfo_if_disabled { + Some(true) => { self.linker_arg("-S"); }, + _ => {}, + } + }, + _ => {}, + }; } fn no_default_libraries(&mut self) { @@ -388,6 +422,18 @@ impl<'a> Linker for GccLinker<'a> { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + fn group_start(&mut self) { + if !self.sess.target.target.options.is_like_osx { + self.linker_arg("--start-group"); + } + } + + fn group_end(&mut self) { + if !self.sess.target.target.options.is_like_osx { + self.linker_arg("--end-group"); + } + } } pub struct MsvcLinker<'a> { @@ -452,11 +498,15 @@ impl<'a> Linker for MsvcLinker<'a> { // noop } + fn full_relro(&mut self) { + // noop + } + fn partial_relro(&mut self) { // noop } - fn full_relro(&mut self) { + fn no_relro(&mut self) { // noop } @@ -503,6 +553,10 @@ impl<'a> Linker for MsvcLinker<'a> { // Needs more investigation of `/OPT` arguments } + fn pgo_gen(&mut self) { + // Nothing needed here. + } + fn debuginfo(&mut self) { // This will cause the Microsoft linker to generate a PDB file // from the CodeView line tables in the object files. @@ -608,6 +662,10 @@ impl<'a> Linker for MsvcLinker<'a> { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + // MSVC doesn't need group indicators + fn group_start(&mut self) {} + fn group_end(&mut self) {} } pub struct EmLinker<'a> { @@ -664,11 +722,15 @@ impl<'a> Linker for EmLinker<'a> { // noop } + fn full_relro(&mut self) { + // noop + } + fn partial_relro(&mut self) { // noop } - fn full_relro(&mut self) { + fn no_relro(&mut self) { // noop } @@ -702,6 +764,10 @@ impl<'a> Linker for EmLinker<'a> { self.cmd.args(&["--memory-init-file", "0"]); } + fn pgo_gen(&mut self) { + // noop, but maybe we need something like the gnu linker? + } + fn debuginfo(&mut self) { // Preserve names or generate source maps depending on debug info self.cmd.arg(match self.sess.opts.debuginfo { @@ -762,6 +828,10 @@ impl<'a> Linker for EmLinker<'a> { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + // Appears not necessary on Emscripten + fn group_start(&mut self) {} + fn group_end(&mut self) {} } fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { @@ -829,10 +899,13 @@ impl Linker for WasmLd { fn position_independent_executable(&mut self) { } + fn full_relro(&mut self) { + } + fn partial_relro(&mut self) { } - fn full_relro(&mut self) { + fn no_relro(&mut self) { } fn build_static_executable(&mut self) { @@ -864,6 +937,9 @@ impl Linker for WasmLd { fn optimize(&mut self) { } + fn pgo_gen(&mut self) { + } + fn debuginfo(&mut self) { } @@ -899,4 +975,8 @@ impl Linker for WasmLd { ::std::mem::swap(&mut cmd, &mut self.cmd); cmd } + + // Not needed for now with LLD + fn group_start(&mut self) {} + fn group_end(&mut self) {} } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index f79651cef3ec..2a473f1ecbcc 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -19,7 +19,7 @@ use llvm; use rustc::hir::def_id::LOCAL_CRATE; use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config::{self, Lto}; -use rustc::util::common::time; +use rustc::util::common::time_ext; use time_graph::Timeline; use {ModuleTranslation, ModuleLlvm, ModuleKind, ModuleSource}; @@ -172,7 +172,7 @@ pub(crate) fn run(cgcx: &CodegenContext, info!("adding bytecode {}", name); let bc_encoded = data.data(); - let (bc, id) = time(cgcx.time_passes, &format!("decode {}", name), || { + let (bc, id) = time_ext(cgcx.time_passes, None, &format!("decode {}", name), || { match DecodedBytecode::new(bc_encoded) { Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), Err(e) => Err(diag_handler.fatal(&e)), @@ -253,7 +253,7 @@ fn fat_lto(cgcx: &CodegenContext, let mut linker = Linker::new(llmod); for (bc_decoded, name) in serialized_modules { info!("linking {:?}", name); - time(cgcx.time_passes, &format!("ll link {:?}", name), || { + time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { let data = bc_decoded.data(); linker.add(&data).map_err(|()| { let msg = format!("failed to load bc of {:?}", name); @@ -498,7 +498,7 @@ fn run_pass_manager(cgcx: &CodegenContext, assert!(!pass.is_null()); llvm::LLVMRustAddPass(pm, pass); - time(cgcx.time_passes, "LTO passes", || + time_ext(cgcx.time_passes, None, "LTO passes", || llvm::LLVMRunPassManager(pm, llmod)); llvm::LLVMDisposePassManager(pm); diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index fd79ae7435ed..d205e6ca4eda 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -223,6 +223,20 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } + if tcx.sess.opts.debugging_opts.pgo_gen.is_some() { + // These are weak symbols that point to the profile version and the + // profile name, which need to be treated as exported so LTO doesn't nix + // them. + const PROFILER_WEAK_SYMBOLS: [&'static str; 2] = [ + "__llvm_profile_raw_version", + "__llvm_profile_filename", + ]; + for sym in &PROFILER_WEAK_SYMBOLS { + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(sym)); + symbols.push((exported_symbol, SymbolExportLevel::C)); + } + } + if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { let symbol_name = metadata_symbol_name(tcx); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); diff --git a/src/librustc_trans/back/wasm.rs b/src/librustc_trans/back/wasm.rs new file mode 100644 index 000000000000..d6d386c9fbe7 --- /dev/null +++ b/src/librustc_trans/back/wasm.rs @@ -0,0 +1,261 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeMap; +use std::fs; +use std::path::Path; +use std::str; + +use rustc_data_structures::fx::FxHashMap; +use serialize::leb128; + +// https://webassembly.github.io/spec/core/binary/modules.html#binary-importsec +const WASM_IMPORT_SECTION_ID: u8 = 2; + +const WASM_EXTERNAL_KIND_FUNCTION: u8 = 0; +const WASM_EXTERNAL_KIND_TABLE: u8 = 1; +const WASM_EXTERNAL_KIND_MEMORY: u8 = 2; +const WASM_EXTERNAL_KIND_GLOBAL: u8 = 3; + +/// Append all the custom sections listed in `sections` to the wasm binary +/// specified at `path`. +/// +/// LLVM 6 which we're using right now doesn't have the ability to create custom +/// sections in wasm files nor does LLD have the ability to merge these sections +/// into one larger section when linking. It's expected that this will +/// eventually get implemented, however! +/// +/// Until that time though this is a custom implementation in rustc to append +/// all sections to a wasm file to the finished product that LLD produces. +/// +/// Support for this is landing in LLVM in https://reviews.llvm.org/D43097, +/// although after that support will need to be in LLD as well. +pub fn add_custom_sections(path: &Path, sections: &BTreeMap>) { + if sections.len() == 0 { + return + } + + let wasm = fs::read(path).expect("failed to read wasm output"); + + // see https://webassembly.github.io/spec/core/binary/modules.html#custom-section + let mut wasm = WasmEncoder { data: wasm }; + for (section, bytes) in sections { + // write the `id` identifier, 0 for a custom section + wasm.byte(0); + + // figure out how long our name descriptor will be + let mut name = WasmEncoder::new(); + name.str(section); + + // write the length of the payload followed by all its contents + wasm.u32((bytes.len() + name.data.len()) as u32); + wasm.data.extend_from_slice(&name.data); + wasm.data.extend_from_slice(bytes); + } + + fs::write(path, &wasm.data).expect("failed to write wasm output"); +} + +/// Rewrite the module imports are listed from in a wasm module given the field +/// name to module name mapping in `import_map`. +/// +/// LLVM 6 which we're using right now doesn't have the ability to configure the +/// module a wasm symbol is import from. Rather all imported symbols come from +/// the bland `"env"` module unconditionally. Furthermore we'd *also* need +/// support in LLD for preserving these import modules, which it unfortunately +/// currently does not. +/// +/// This function is intended as a hack for now where we manually rewrite the +/// wasm output by LLVM to have the correct import modules listed. The +/// `#[wasm_import_module]` attribute in Rust translates to the module that each +/// symbol is imported from, so here we manually go through the wasm file, +/// decode it, rewrite imports, and then rewrite the wasm module. +/// +/// Support for this was added to LLVM in +/// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still +/// needs to be added (AFAIK at the time of this writing) to LLD +pub fn rewrite_imports(path: &Path, import_map: &FxHashMap) { + if import_map.len() == 0 { + return + } + + let wasm = fs::read(path).expect("failed to read wasm output"); + let mut ret = WasmEncoder::new(); + ret.data.extend(&wasm[..8]); + + // skip the 8 byte wasm/version header + for (id, raw) in WasmSections(WasmDecoder::new(&wasm[8..])) { + ret.byte(id); + if id == WASM_IMPORT_SECTION_ID { + info!("rewriting import section"); + let data = rewrite_import_section( + &mut WasmDecoder::new(raw), + import_map, + ); + ret.bytes(&data); + } else { + info!("carry forward section {}, {} bytes long", id, raw.len()); + ret.bytes(raw); + } + } + + fs::write(path, &ret.data).expect("failed to write wasm output"); + + fn rewrite_import_section( + wasm: &mut WasmDecoder, + import_map: &FxHashMap, + ) + -> Vec + { + let mut dst = WasmEncoder::new(); + let n = wasm.u32(); + dst.u32(n); + info!("rewriting {} imports", n); + for _ in 0..n { + rewrite_import_entry(wasm, &mut dst, import_map); + } + return dst.data + } + + fn rewrite_import_entry(wasm: &mut WasmDecoder, + dst: &mut WasmEncoder, + import_map: &FxHashMap) { + // More info about the binary format here is available at: + // https://webassembly.github.io/spec/core/binary/modules.html#import-section + // + // Note that you can also find the whole point of existence of this + // function here, where we map the `module` name to a different one if + // we've got one listed. + let module = wasm.str(); + let field = wasm.str(); + let new_module = if module == "env" { + import_map.get(field).map(|s| &**s).unwrap_or(module) + } else { + module + }; + info!("import rewrite ({} => {}) / {}", module, new_module, field); + dst.str(new_module); + dst.str(field); + let kind = wasm.byte(); + dst.byte(kind); + match kind { + WASM_EXTERNAL_KIND_FUNCTION => dst.u32(wasm.u32()), + WASM_EXTERNAL_KIND_TABLE => { + dst.byte(wasm.byte()); // element_type + dst.limits(wasm.limits()); + } + WASM_EXTERNAL_KIND_MEMORY => dst.limits(wasm.limits()), + WASM_EXTERNAL_KIND_GLOBAL => { + dst.byte(wasm.byte()); // content_type + dst.bool(wasm.bool()); // mutable + } + b => panic!("unknown kind: {}", b), + } + } +} + +struct WasmSections<'a>(WasmDecoder<'a>); + +impl<'a> Iterator for WasmSections<'a> { + type Item = (u8, &'a [u8]); + + fn next(&mut self) -> Option<(u8, &'a [u8])> { + if self.0.data.len() == 0 { + return None + } + + // see https://webassembly.github.io/spec/core/binary/modules.html#sections + let id = self.0.byte(); + let section_len = self.0.u32(); + info!("new section {} / {} bytes", id, section_len); + let section = self.0.skip(section_len as usize); + Some((id, section)) + } +} + +struct WasmDecoder<'a> { + data: &'a [u8], +} + +impl<'a> WasmDecoder<'a> { + fn new(data: &'a [u8]) -> WasmDecoder<'a> { + WasmDecoder { data } + } + + fn byte(&mut self) -> u8 { + self.skip(1)[0] + } + + fn u32(&mut self) -> u32 { + let (n, l1) = leb128::read_u32_leb128(self.data); + self.data = &self.data[l1..]; + return n + } + + fn skip(&mut self, amt: usize) -> &'a [u8] { + let (data, rest) = self.data.split_at(amt); + self.data = rest; + data + } + + fn str(&mut self) -> &'a str { + let len = self.u32(); + str::from_utf8(self.skip(len as usize)).unwrap() + } + + fn bool(&mut self) -> bool { + self.byte() == 1 + } + + fn limits(&mut self) -> (u32, Option) { + let has_max = self.bool(); + (self.u32(), if has_max { Some(self.u32()) } else { None }) + } +} + +struct WasmEncoder { + data: Vec, +} + +impl WasmEncoder { + fn new() -> WasmEncoder { + WasmEncoder { data: Vec::new() } + } + + fn u32(&mut self, val: u32) { + let at = self.data.len(); + leb128::write_u32_leb128(&mut self.data, at, val); + } + + fn byte(&mut self, val: u8) { + self.data.push(val); + } + + fn bytes(&mut self, val: &[u8]) { + self.u32(val.len() as u32); + self.data.extend_from_slice(val); + } + + fn str(&mut self, val: &str) { + self.bytes(val.as_bytes()) + } + + fn bool(&mut self, b: bool) { + self.byte(b as u8); + } + + fn limits(&mut self, limits: (u32, Option)) { + self.bool(limits.1.is_some()); + self.u32(limits.0); + if let Some(c) = limits.1 { + self.u32(c); + } + } +} diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index c0561ff0c173..fc699f7569f1 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -31,7 +31,8 @@ use {CrateTranslation, ModuleSource, ModuleTranslation, CompiledModule, ModuleKi use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::ty::TyCtxt; -use rustc::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry}; +use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passes_entry}; +use rustc::util::common::path2cstr; use rustc::util::fs::{link_or_copy}; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use errors::emitter::{Emitter}; @@ -41,6 +42,7 @@ use syntax_pos::MultiSpan; use syntax_pos::symbol::Symbol; use type_::Type; use context::{is_pie_binary, get_reloc_model}; +use common::{C_bytes_in_context, val_ty}; use jobserver::{Client, Acquired}; use rustc_demangle; @@ -238,6 +240,9 @@ pub struct ModuleConfig { /// Some(level) to optimize binary size, or None to not affect program size. opt_size: Option, + pgo_gen: Option, + pgo_use: String, + // Flags indicating which outputs to produce. emit_no_opt_bc: bool, emit_bc: bool, @@ -261,6 +266,8 @@ pub struct ModuleConfig { // emscripten's ecc compiler, when used as the linker. obj_is_bitcode: bool, no_integrated_as: bool, + embed_bitcode: bool, + embed_bitcode_marker: bool, } impl ModuleConfig { @@ -270,6 +277,9 @@ impl ModuleConfig { opt_level: None, opt_size: None, + pgo_gen: None, + pgo_use: String::new(), + emit_no_opt_bc: false, emit_bc: false, emit_bc_compressed: false, @@ -278,6 +288,8 @@ impl ModuleConfig { emit_asm: false, emit_obj: false, obj_is_bitcode: false, + embed_bitcode: false, + embed_bitcode_marker: false, no_integrated_as: false, no_verify: false, @@ -298,6 +310,17 @@ impl ModuleConfig { self.time_passes = sess.time_passes(); self.inline_threshold = sess.opts.cg.inline_threshold; self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode; + let embed_bitcode = sess.target.target.options.embed_bitcode || + sess.opts.debugging_opts.embed_bitcode; + if embed_bitcode { + match sess.opts.optimize { + config::OptLevel::No | + config::OptLevel::Less => { + self.embed_bitcode_marker = embed_bitcode; + } + _ => self.embed_bitcode = embed_bitcode, + } + } // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. Otherwise configure other optimization aspects @@ -475,8 +498,13 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo opt.message)); } } - - _ => (), + llvm::diagnostic::PGO(diagnostic_ref) => { + let msg = llvm::build_string(|s| { + llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) + }).expect("non-UTF8 PGO diagnostic"); + diag_handler.warn(&msg); + } + llvm::diagnostic::UnknownDiagnostic(..) => {}, } } @@ -563,11 +591,19 @@ unsafe fn optimize(cgcx: &CodegenContext, diag_handler.abort_if_errors(); // Finally, run the actual optimization passes - time(config.time_passes, &format!("llvm function passes [{}]", module_name.unwrap()), || - llvm::LLVMRustRunFunctionPassManager(fpm, llmod)); + time_ext(config.time_passes, + None, + &format!("llvm function passes [{}]", module_name.unwrap()), + || { + llvm::LLVMRustRunFunctionPassManager(fpm, llmod) + }); timeline.record("fpm"); - time(config.time_passes, &format!("llvm module passes [{}]", module_name.unwrap()), || - llvm::LLVMRunPassManager(mpm, llmod)); + time_ext(config.time_passes, + None, + &format!("llvm module passes [{}]", module_name.unwrap()), + || { + llvm::LLVMRunPassManager(mpm, llmod) + }); // Deallocate managers that we're now done with llvm::LLVMDisposePassManager(fpm); @@ -653,7 +689,7 @@ unsafe fn codegen(cgcx: &CodegenContext, let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - if write_bc || config.emit_bc_compressed { + if write_bc || config.emit_bc_compressed || config.embed_bitcode { let thin; let old; let data = if llvm::LLVMRustThinLTOAvailable() { @@ -672,6 +708,11 @@ unsafe fn codegen(cgcx: &CodegenContext, timeline.record("write-bc"); } + if config.embed_bitcode { + embed_bitcode(cgcx, llcx, llmod, Some(data)); + timeline.record("embed-bc"); + } + if config.emit_bc_compressed { let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); let data = bytecode::encode(&mtrans.llmod_id, data); @@ -680,9 +721,11 @@ unsafe fn codegen(cgcx: &CodegenContext, } timeline.record("compress-bc"); } + } else if config.embed_bitcode_marker { + embed_bitcode(cgcx, llcx, llmod, None); } - time(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()), + time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), || -> Result<(), FatalError> { if config.emit_ir { let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); @@ -787,6 +830,59 @@ unsafe fn codegen(cgcx: &CodegenContext, &cgcx.output_filenames)) } +/// Embed the bitcode of an LLVM module in the LLVM module itself. +/// +/// This is done primarily for iOS where it appears to be standard to compile C +/// code at least with `-fembed-bitcode` which creates two sections in the +/// executable: +/// +/// * __LLVM,__bitcode +/// * __LLVM,__cmdline +/// +/// It appears *both* of these sections are necessary to get the linker to +/// recognize what's going on. For us though we just always throw in an empty +/// cmdline section. +/// +/// Furthermore debug/O1 builds don't actually embed bitcode but rather just +/// embed an empty section. +/// +/// Basically all of this is us attempting to follow in the footsteps of clang +/// on iOS. See #35968 for lots more info. +unsafe fn embed_bitcode(cgcx: &CodegenContext, + llcx: ContextRef, + llmod: ModuleRef, + bitcode: Option<&[u8]>) { + let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[])); + let llglobal = llvm::LLVMAddGlobal( + llmod, + val_ty(llconst).to_ref(), + "rustc.embedded.module\0".as_ptr() as *const _, + ); + llvm::LLVMSetInitializer(llglobal, llconst); + let section = if cgcx.opts.target_triple.triple().contains("-ios") { + "__LLVM,__bitcode\0" + } else { + ".llvmbc\0" + }; + llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + + let llconst = C_bytes_in_context(llcx, &[]); + let llglobal = llvm::LLVMAddGlobal( + llmod, + val_ty(llconst).to_ref(), + "rustc.embedded.cmdline\0".as_ptr() as *const _, + ); + llvm::LLVMSetInitializer(llglobal, llconst); + let section = if cgcx.opts.target_triple.triple().contains("-ios") { + "__LLVM,__cmdline\0" + } else { + ".llvmcmd\0" + }; + llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); +} + pub(crate) struct CompiledModules { pub modules: Vec, pub metadata_module: CompiledModule, @@ -847,6 +943,9 @@ pub fn start_async_translation(tcx: TyCtxt, modules_config.passes.push("insert-gcov-profiling".to_owned()) } + modules_config.pgo_gen = sess.opts.debugging_opts.pgo_gen.clone(); + modules_config.pgo_use = sess.opts.debugging_opts.pgo_use.clone(); + modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize)); modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize)); @@ -1961,6 +2060,8 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, config: &ModuleConfig, opt_level: llvm::CodeGenOptLevel, f: &mut FnMut(llvm::PassManagerBuilderRef)) { + use std::ptr; + // Create the PassManagerBuilder for LLVM. We configure it with // reasonable defaults and prepare it to actually populate the pass // manager. @@ -1968,11 +2069,27 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone); let inline_threshold = config.inline_threshold; - llvm::LLVMRustConfigurePassManagerBuilder(builder, - opt_level, - config.merge_functions, - config.vectorize_slp, - config.vectorize_loop); + let pgo_gen_path = config.pgo_gen.as_ref().map(|s| { + let s = if s.is_empty() { "default_%m.profraw" } else { s }; + CString::new(s.as_bytes()).unwrap() + }); + + let pgo_use_path = if config.pgo_use.is_empty() { + None + } else { + Some(CString::new(config.pgo_use.as_bytes()).unwrap()) + }; + + llvm::LLVMRustConfigurePassManagerBuilder( + builder, + opt_level, + config.merge_functions, + config.vectorize_slp, + config.vectorize_loop, + pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + ); + llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32); if opt_size != llvm::CodeGenOptSizeNone { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 49a5b7ac8b90..7ab3499ead36 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -72,8 +72,11 @@ use type_::Type; use type_of::LayoutLlvmExt; use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet}; use CrateInfo; +use rustc_data_structures::sync::Lrc; +use rustc_back::target::TargetTriple; use std::any::Any; +use std::collections::BTreeMap; use std::ffi::CString; use std::str; use std::sync::Arc; @@ -462,7 +465,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc let fn_ty = instance.ty(cx.tcx); let sig = common::ty_fn_sig(cx, fn_ty); - let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let lldecl = match cx.instances.borrow().get(&instance) { Some(&val) => val, @@ -706,13 +709,20 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } + if (tcx.sess.opts.debugging_opts.pgo_gen.is_some() || + !tcx.sess.opts.debugging_opts.pgo_use.is_empty()) && + unsafe { !llvm::LLVMRustPGOAvailable() } + { + tcx.sess.fatal("this compiler's LLVM does not support PGO"); + } + let crate_hash = tcx.crate_hash(LOCAL_CRATE); let link_meta = link::build_link_meta(crate_hash); // Translate the metadata. let llmod_id = "metadata"; let (metadata_llcx, metadata_llmod, metadata) = - time(tcx.sess.time_passes(), "write metadata", || { + time(tcx.sess, "write metadata", || { write_metadata(tcx, llmod_id, &link_meta) }); @@ -790,7 +800,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, llcx, tm: create_target_machine(tcx.sess), }; - time(tcx.sess.time_passes(), "write allocator module", || { + time(tcx.sess, "write allocator module", || { allocator::trans(tcx, &modules, kind) }); @@ -924,11 +934,11 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - time(tcx.sess.time_passes(), + time(tcx.sess, "assert dep graph", || rustc_incremental::assert_dep_graph(tcx)); - time(tcx.sess.time_passes(), + time(tcx.sess, "serialize dep graph", || rustc_incremental::save_dep_graph(tcx)); } @@ -939,7 +949,6 @@ fn collect_and_partition_translation_items<'a, 'tcx>( ) -> (Arc, Arc>>>) { assert_eq!(cnum, LOCAL_CRATE); - let time_passes = tcx.sess.time_passes(); let collection_mode = match tcx.sess.opts.debugging_opts.print_trans_items { Some(ref s) => { @@ -968,7 +977,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( }; let (items, inlining_map) = - time(time_passes, "translation item collection", || { + time(tcx.sess, "translation item collection", || { collector::collect_crate_mono_items(tcx, collection_mode) }); @@ -982,7 +991,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) }; - let codegen_units = time(time_passes, "codegen unit partitioning", || { + let codegen_units = time(tcx.sess, "codegen unit partitioning", || { partitioning::partition(tcx, items.iter().cloned(), strategy, @@ -1071,7 +1080,28 @@ impl CrateInfo { used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic), used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic), used_crate_source: FxHashMap(), + wasm_custom_sections: BTreeMap::new(), + wasm_imports: FxHashMap(), + lang_item_to_crate: FxHashMap(), + missing_lang_items: FxHashMap(), }; + let lang_items = tcx.lang_items(); + + let load_wasm_items = tcx.sess.crate_types.borrow() + .iter() + .any(|c| *c != config::CrateTypeRlib) && + tcx.sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown"); + + if load_wasm_items { + info!("attempting to load all wasm sections"); + for &id in tcx.wasm_custom_sections(LOCAL_CRATE).iter() { + let (name, contents) = fetch_wasm_section(tcx, id); + info.wasm_custom_sections.entry(name) + .or_insert(Vec::new()) + .extend(contents); + } + info.load_wasm_imports(tcx, LOCAL_CRATE); + } for &cnum in tcx.crates().iter() { info.native_libraries.insert(cnum, tcx.native_libraries(cnum)); @@ -1092,11 +1122,34 @@ impl CrateInfo { if tcx.is_no_builtins(cnum) { info.is_no_builtins.insert(cnum); } + if load_wasm_items { + for &id in tcx.wasm_custom_sections(cnum).iter() { + let (name, contents) = fetch_wasm_section(tcx, id); + info.wasm_custom_sections.entry(name) + .or_insert(Vec::new()) + .extend(contents); + } + info.load_wasm_imports(tcx, cnum); + } + let missing = tcx.missing_lang_items(cnum); + for &item in missing.iter() { + if let Ok(id) = lang_items.require(item) { + info.lang_item_to_crate.insert(item, id.krate); + } + } + info.missing_lang_items.insert(cnum, missing); } - return info } + + fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) { + for (&id, module) in tcx.wasm_import_module_map(cnum).iter() { + let instance = Instance::mono(tcx, id); + let import_name = tcx.symbol_name(instance); + self.wasm_imports.insert(import_name.to_string(), module.clone()); + } + } } fn is_translated_item(tcx: TyCtxt, id: DefId) -> bool { @@ -1224,6 +1277,39 @@ pub fn provide(providers: &mut Providers) { .expect(&format!("failed to find cgu with name {:?}", name)) }; providers.compile_codegen_unit = compile_codegen_unit; + + provide_extern(providers); +} + +pub fn provide_extern(providers: &mut Providers) { + providers.dllimport_foreign_items = |tcx, krate| { + let module_map = tcx.foreign_modules(krate); + let module_map = module_map.iter() + .map(|lib| (lib.def_id, lib)) + .collect::>(); + + let dllimports = tcx.native_libraries(krate) + .iter() + .filter(|lib| { + if lib.kind != cstore::NativeLibraryKind::NativeUnknown { + return false + } + let cfg = match lib.cfg { + Some(ref cfg) => cfg, + None => return true, + }; + attr::cfg_matches(cfg, &tcx.sess.parse_sess, None) + }) + .filter_map(|lib| lib.foreign_module) + .map(|id| &module_map[&id]) + .flat_map(|module| module.foreign_items.iter().cloned()) + .collect(); + Lrc::new(dllimports) + }; + + providers.is_dllimport_foreign_item = |tcx, def_id| { + tcx.dllimport_foreign_items(def_id.krate).contains(&def_id) + }; } pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { @@ -1271,3 +1357,44 @@ mod temp_stable_hash_impls { } } } + +fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec) { + use rustc::mir::interpret::{GlobalId, Value, PrimVal}; + use rustc::middle::const_val::ConstVal; + + info!("loading wasm section {:?}", id); + + let section = tcx.get_attrs(id) + .iter() + .find(|a| a.check_name("wasm_custom_section")) + .expect("missing #[wasm_custom_section] attribute") + .value_str() + .expect("malformed #[wasm_custom_section] attribute"); + + let instance = ty::Instance::mono(tcx, id); + let cid = GlobalId { + instance, + promoted: None + }; + let param_env = ty::ParamEnv::reveal_all(); + let val = tcx.const_eval(param_env.and(cid)).unwrap(); + + let val = match val.val { + ConstVal::Value(val) => val, + ConstVal::Unevaluated(..) => bug!("should be evaluated"), + }; + let val = match val { + Value::ByRef(ptr, _align) => ptr.into_inner_primval(), + ref v => bug!("should be ByRef, was {:?}", v), + }; + let mem = match val { + PrimVal::Ptr(mem) => mem, + ref v => bug!("should be Ptr, was {:?}", v), + }; + assert_eq!(mem.offset, 0); + let alloc = tcx + .interpret_interner + .get_alloc(mem.alloc_id) + .expect("miri allocation never successfully created"); + (section.to_string(), alloc.bytes.clone()) +} diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index d4e05a18e3a5..db803ca8209d 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -344,6 +344,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + pub fn exactudiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + self.count_insn("exactudiv"); + unsafe { + llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname()) + } + } + pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { self.count_insn("sdiv"); unsafe { @@ -910,6 +917,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + pub fn minnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + self.count_insn("minnum"); + unsafe { + let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs); + if instr.is_null() { + bug!("LLVMRustBuildMinNum is not available in LLVM version < 6.0"); + } + instr + } + } + pub fn maxnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + self.count_insn("maxnum"); + unsafe { + let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs); + if instr.is_null() { + bug!("LLVMRustBuildMaxNum is not available in LLVM version < 6.0"); + } + instr + } + } + pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef { self.count_insn("select"); unsafe { @@ -955,6 +983,147 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fadd_fast"); + unsafe { + // FIXME: add a non-fast math version once + // https://bugs.llvm.org/show_bug.cgi?id=36732 + // is fixed. + let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0"); + } + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmul_fast"); + unsafe { + // FIXME: add a non-fast math version once + // https://bugs.llvm.org/show_bug.cgi?id=36732 + // is fixed. + let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0"); + } + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.add"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.mul"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.and"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.or"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.xor"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmin"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmax"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmin_fast"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); + } + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmax_fast"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); + } + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef { + self.count_insn("vector.reduce.min"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef { + self.count_insn("vector.reduce.max"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0"); + } + instr + } + } + pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef { self.count_insn("extractvalue"); assert_eq!(idx as c_uint as u64, idx); diff --git a/src/librustc_trans/cabi_mips64.rs b/src/librustc_trans/cabi_mips64.rs index 94bf53cee1ed..231fe4c6edb6 100644 --- a/src/librustc_trans/cabi_mips64.rs +++ b/src/librustc_trans/cabi_mips64.rs @@ -28,18 +28,6 @@ fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) { arg.extend_integer_width_to(bits); } -fn bits_to_int_reg(bits: u64) -> Reg { - if bits <= 8 { - Reg::i8() - } else if bits <= 16 { - Reg::i16() - } else if bits <= 32 { - Reg::i32() - } else { - Reg::i64() - } -} - fn float_reg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &ArgType<'tcx>, i: usize) -> Option { match ret.layout.field(cx, i).abi { layout::Abi::Scalar(ref scalar) => match scalar.value { @@ -82,7 +70,7 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) // Cast to a uniform int structure ret.cast_to(Uniform { - unit: bits_to_int_reg(bits), + unit: Reg::i64(), total: size }); } else { diff --git a/src/librustc_trans/cabi_wasm32.rs b/src/librustc_trans/cabi_wasm32.rs new file mode 100644 index 000000000000..5530a03d65dd --- /dev/null +++ b/src/librustc_trans/cabi_wasm32.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use abi::{FnType, ArgType}; +use context::CodegenCx; + +fn classify_ret_ty<'a, 'tcx>(_cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) { + ret.extend_integer_width_to(32); +} + +fn classify_arg_ty(arg: &mut ArgType) { + arg.extend_integer_width_to(32); +} + +pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) { + if !fty.ret.is_ignore() { + classify_ret_ty(cx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { continue; } + classify_arg_ty(arg); + } +} diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 54cc561e8041..1dcf349e23bd 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -25,7 +25,6 @@ use type_of::LayoutLlvmExt; use rustc::hir::def_id::DefId; use rustc::ty::{self, TypeFoldable}; use rustc::ty::layout::LayoutOf; -use rustc::traits; use rustc::ty::subst::Substs; use rustc_back::PanicStrategy; @@ -185,7 +184,7 @@ pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, cx, ty::Instance::resolve( cx.tcx, - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), def_id, substs ).unwrap() diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 7c4e2340d5bd..e83e73c8ae75 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -25,7 +25,6 @@ use declare; use type_::Type; use type_of::LayoutLlvmExt; use value::Value; -use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; @@ -40,15 +39,15 @@ use syntax_pos::{Span, DUMMY_SP}; pub use context::CodegenCx; pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) + ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) } pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::empty(traits::Reveal::All)) + ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) } pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_freeze(tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) + ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP) } /* @@ -270,6 +269,19 @@ pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef { } } +pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> { + unsafe { + if is_const_real(v) { + let mut loses_info: llvm::Bool = ::std::mem::uninitialized(); + let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool); + let loses_info = if loses_info == 1 { true } else { false }; + Some((r, loses_info)) + } else { + None + } + } +} + pub fn const_to_uint(v: ValueRef) -> u64 { unsafe { llvm::LLVMConstIntGetZExtValue(v) @@ -282,6 +294,13 @@ pub fn is_const_integral(v: ValueRef) -> bool { } } +pub fn is_const_real(v: ValueRef) -> bool { + unsafe { + !llvm::LLVMIsAConstantFP(v).is_null() + } +} + + #[inline] fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index dc5e78895944..1f2c3cc883c6 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -14,7 +14,6 @@ use llvm::{ContextRef, ModuleRef, ValueRef}; use rustc::dep_graph::DepGraphSafe; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::traits; use debuginfo; use callee; use base; @@ -435,7 +434,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { use syntax_pos::DUMMY_SP; - if ty.is_sized(self.tcx.at(DUMMY_SP), ty::ParamEnv::empty(traits::Reveal::All)) { + if ty.is_sized(self.tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) { return false; } @@ -464,7 +463,7 @@ impl<'a, 'tcx> LayoutOf> for &'a CodegenCx<'a, 'tcx> { type TyLayout = TyLayout<'tcx>; fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - self.tcx.layout_of(ty::ParamEnv::empty(traits::Reveal::All).and(ty)) + self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) .unwrap_or_else(|e| match e { LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()), _ => bug!("failed to get layout for `{}`: {}", ty, e) diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index d20b51ca0fdf..f3d95cf794ba 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -30,7 +30,7 @@ use rustc::ty::util::TypeIdHasher; use rustc::ich::Fingerprint; use rustc::ty::Instance; use common::CodegenCx; -use rustc::ty::{self, AdtKind, Ty, TyCtxt}; +use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; use rustc::session::config; use rustc::util::nodemap::FxHashMap; @@ -353,13 +353,16 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, span: Span) -> MetadataCreationResult { - let signature = cx.tcx.erase_late_bound_regions_and_normalize(&signature); + let signature = cx.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &signature, + ); let mut signature_metadata: Vec = Vec::with_capacity(signature.inputs().len() + 1); // return type signature_metadata.push(match signature.output().sty { - ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), + ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), _ => type_metadata(cx, signature.output(), span) }); @@ -530,7 +533,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::TyFloat(_) => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::TyTuple(ref elements, _) if elements.is_empty() => { + ty::TyTuple(ref elements) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } ty::TyArray(typ, _) | @@ -589,7 +592,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } ty::TyGenerator(def_id, substs, _) => { let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| { - cx.tcx.fully_normalize_associated_types_in(&t) + cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) }).collect(); prepare_tuple_metadata(cx, t, @@ -618,7 +621,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, usage_site_span).finalize(cx) } }, - ty::TyTuple(ref elements, _) => { + ty::TyTuple(ref elements) => { prepare_tuple_metadata(cx, t, &elements[..], @@ -728,7 +731,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let (name, encoding) = match t.sty { ty::TyNever => ("!", DW_ATE_unsigned), - ty::TyTuple(ref elements, _) if elements.is_empty() => + ty::TyTuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::TyBool => ("bool", DW_ATE_boolean), ty::TyChar => ("char", DW_ATE_unsigned_char), diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 16279f31836a..7664c88679e0 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -30,7 +30,7 @@ use abi::Abi; use common::CodegenCx; use builder::Builder; use monomorphize::Instance; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, ParamEnv, Ty}; use rustc::mir; use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; @@ -312,7 +312,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // Return type -- llvm::DIBuilder wants this at index 0 signature.push(match sig.output().sty { - ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), + ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) }); @@ -351,7 +351,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty { + if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { for &argument_type in args { signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); } @@ -378,7 +378,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name_to_append_suffix_to.push_str(","); } - let actual_type = cx.tcx.fully_normalize_associated_types_in(&actual_type); + let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type); // Add actual type name to <...> clause of function name let actual_type_name = compute_debuginfo_type_name(cx, actual_type, @@ -391,7 +391,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { let names = get_type_parameter_names(cx, generics); substs.types().zip(names).map(|(ty, name)| { - let actual_type = cx.tcx.fully_normalize_associated_types_in(&ty); + let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { @@ -429,7 +429,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| { // If the method does *not* belong to a trait, proceed if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { - let impl_self_ty = cx.tcx.trans_impl_self_ty(impl_def_id, instance.substs); + let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions( + instance.substs, + ty::ParamEnv::reveal_all(), + &cx.tcx.type_of(impl_def_id), + ); // Only "class" methods are generally understood by LLVM, // so avoid methods on other types (e.g. `<*mut T>::null`). diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index a88eb9ae3547..96ed4e884711 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -53,7 +53,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, push_item_name(cx, def.did, qualified, output); push_type_params(cx, substs, output); }, - ty::TyTuple(component_types, _) => { + ty::TyTuple(component_types) => { output.push('('); for &component_type in component_types { push_debuginfo_type_name(cx, component_type, true, output); @@ -117,8 +117,10 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, }, ty::TyDynamic(ref trait_data, ..) => { if let Some(principal) = trait_data.principal() { - let principal = cx.tcx.erase_late_bound_regions_and_normalize( - &principal); + let principal = cx.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &principal, + ); push_item_name(cx, principal.def_id, false, output); push_type_params(cx, principal.substs, output); } @@ -138,7 +140,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output.push_str("fn("); - let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(cx, parameter_type, true, output); diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index aa1cd0c27e79..c2010feb1b63 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -22,7 +22,7 @@ use llvm::{self, ValueRef}; use llvm::AttributePlace::Function; -use rustc::ty::Ty; +use rustc::ty::{self, Ty}; use rustc::session::config::Sanitizer; use rustc_back::PanicStrategy; use abi::{Abi, FnType}; @@ -127,7 +127,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, fn_type: Ty<'tcx>) -> ValueRef { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); let sig = common::ty_fn_sig(cx, fn_type); - let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); let fty = FnType::new(cx, sig, &[]); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 3f87ce7e0479..5c67f8091141 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -100,7 +100,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, }; let sig = callee_ty.fn_sig(tcx); - let sig = tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = &*tcx.item_name(def_id); @@ -289,7 +289,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | "bitreverse" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | - "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => { + "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" => { let ty = arg_tys[0]; match int_type_width_signed(ty, cx) { Some((width, signed)) => @@ -343,6 +343,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, "overflowing_add" => bx.add(args[0].immediate(), args[1].immediate()), "overflowing_sub" => bx.sub(args[0].immediate(), args[1].immediate()), "overflowing_mul" => bx.mul(args[0].immediate(), args[1].immediate()), + "exact_div" => + if signed { + bx.exactsdiv(args[0].immediate(), args[1].immediate()) + } else { + bx.exactudiv(args[0].immediate(), args[1].immediate()) + }, "unchecked_div" => if signed { bx.sdiv(args[0].immediate(), args[1].immediate()) @@ -1018,14 +1024,22 @@ fn generic_simd_intrinsic<'a, 'tcx>( name, $($fmt)*)); } } - macro_rules! require { - ($cond: expr, $($fmt: tt)*) => { - if !$cond { + macro_rules! return_error { + ($($fmt: tt)*) => { + { emit_error!($($fmt)*); return Err(()); } } } + + macro_rules! require { + ($cond: expr, $($fmt: tt)*) => { + if !$cond { + return_error!($($fmt)*); + } + }; + } macro_rules! require_simd { ($ty: expr, $position: expr) => { require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) @@ -1035,7 +1049,10 @@ fn generic_simd_intrinsic<'a, 'tcx>( let tcx = bx.tcx(); - let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx)); + let sig = tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &callee_ty.fn_sig(tcx), + ); let arg_tys = sig.inputs(); // every intrinsic takes a SIMD vector as its first argument @@ -1142,6 +1159,182 @@ fn generic_simd_intrinsic<'a, 'tcx>( return Ok(bx.extract_element(args[0].immediate(), args[1].immediate())) } + if name == "simd_select" { + let m_elem_ty = in_elem; + let m_len = in_len; + let v_len = arg_tys[1].simd_size(tcx); + require!(m_len == v_len, + "mismatched lengths: mask length `{}` != other vector length `{}`", + m_len, v_len + ); + match m_elem_ty.sty { + ty::TyInt(_) => {}, + _ => { + return_error!("mask element type is `{}`, expected `i_`", m_elem_ty); + } + } + // truncate the mask to a vector of i1s + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, m_len as u64); + let m_i1s = bx.trunc(args[0].immediate(), i1xn); + return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); + } + + macro_rules! arith_red { + ($name:tt : $integer_reduce:ident, $float_reduce:ident, $ordered:expr) => { + if name == $name { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_) | ty::TyUint(_) => { + let r = bx.$integer_reduce(args[0].immediate()); + if $ordered { + // if overflow occurs, the result is the + // mathematical result modulo 2^n: + if name.contains("mul") { + Ok(bx.mul(args[1].immediate(), r)) + } else { + Ok(bx.add(args[1].immediate(), r)) + } + } else { + Ok(bx.$integer_reduce(args[0].immediate())) + } + }, + ty::TyFloat(f) => { + // ordered arithmetic reductions take an accumulator + let acc = if $ordered { + let acc = args[1].immediate(); + // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36734 + // * if the accumulator of the fadd isn't 0, incorrect + // code is generated + // * if the accumulator of the fmul isn't 1, incorrect + // code is generated + match const_get_real(acc) { + None => return_error!("accumulator of {} is not a constant", $name), + Some((v, loses_info)) => { + if $name.contains("mul") && v != 1.0_f64 { + return_error!("accumulator of {} is not 1.0", $name); + } else if $name.contains("add") && v != 0.0_f64 { + return_error!("accumulator of {} is not 0.0", $name); + } else if loses_info { + return_error!("accumulator of {} loses information", $name); + } + } + } + acc + } else { + // unordered arithmetic reductions do not: + match f.bit_width() { + 32 => C_undef(Type::f32(bx.cx)), + 64 => C_undef(Type::f64(bx.cx)), + v => { + return_error!(r#" +unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, + $name, in_ty, in_elem, v, ret_ty + ) + } + } + + }; + Ok(bx.$float_reduce(acc, args[0].immediate())) + } + _ => { + return_error!( + "unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty + ) + }, + } + } + } + } + + arith_red!("simd_reduce_add_ordered": vector_reduce_add, vector_reduce_fadd_fast, true); + arith_red!("simd_reduce_mul_ordered": vector_reduce_mul, vector_reduce_fmul_fast, true); + arith_red!("simd_reduce_add_unordered": vector_reduce_add, vector_reduce_fadd_fast, false); + arith_red!("simd_reduce_mul_unordered": vector_reduce_mul, vector_reduce_fmul_fast, false); + + macro_rules! minmax_red { + ($name:tt: $int_red:ident, $float_red:ident) => { + if name == $name { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.$int_red(args[0].immediate(), true)) + }, + ty::TyUint(_u) => { + Ok(bx.$int_red(args[0].immediate(), false)) + }, + ty::TyFloat(_f) => { + Ok(bx.$float_red(args[0].immediate())) + } + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty) + }, + } + } + + } + } + + minmax_red!("simd_reduce_min": vector_reduce_min, vector_reduce_fmin); + minmax_red!("simd_reduce_max": vector_reduce_max, vector_reduce_fmax); + + minmax_red!("simd_reduce_min_nanless": vector_reduce_min, vector_reduce_fmin_fast); + minmax_red!("simd_reduce_max_nanless": vector_reduce_max, vector_reduce_fmax_fast); + + macro_rules! bitwise_red { + ($name:tt : $red:ident, $boolean:expr) => { + if name == $name { + let input = if !$boolean { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + args[0].immediate() + } else { + match in_elem.sty { + ty::TyInt(_) | ty::TyUint(_) => {}, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty) + } + } + + // boolean reductions operate on vectors of i1s: + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, in_len as u64); + bx.trunc(args[0].immediate(), i1xn) + }; + return match in_elem.sty { + ty::TyInt(_) | ty::TyUint(_) => { + let r = bx.$red(input); + Ok( + if !$boolean { + r + } else { + bx.zext(r, Type::bool(bx.cx)) + } + ) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty) + }, + } + } + } + } + + bitwise_red!("simd_reduce_and": vector_reduce_and, false); + bitwise_red!("simd_reduce_or": vector_reduce_or, false); + bitwise_red!("simd_reduce_xor": vector_reduce_xor, false); + bitwise_red!("simd_reduce_all": vector_reduce_and, true); + bitwise_red!("simd_reduce_any": vector_reduce_or, true); + if name == "simd_cast" { require_simd!(ret_ty, "return"); let out_len = ret_ty.simd_size(tcx); @@ -1239,6 +1432,8 @@ fn generic_simd_intrinsic<'a, 'tcx>( simd_and: TyUint, TyInt => and; simd_or: TyUint, TyInt => or; simd_xor: TyUint, TyInt => xor; + simd_fmax: TyFloat => maxnum; + simd_fmin: TyFloat => minnum; } span_bug!(span, "unknown SIMD intrinsic"); } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 74df5127269a..e8a1eb3071a2 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -24,16 +24,15 @@ #![feature(custom_attribute)] #![feature(fs_read_write)] #![allow(unused_attributes)] -#![feature(i128_type)] -#![feature(i128)] -#![feature(inclusive_range)] -#![feature(inclusive_range_syntax)] +#![cfg_attr(stage0, feature(i128_type, i128))] +#![cfg_attr(stage0, feature(inclusive_range_syntax))] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] -#![feature(slice_patterns)] -#![feature(conservative_impl_trait)] +#![cfg_attr(stage0, feature(slice_patterns))] +#![cfg_attr(stage0, feature(conservative_impl_trait))] #![feature(optin_builtin_traits)] +#![feature(inclusive_range_fields)] use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; @@ -72,12 +71,14 @@ pub use llvm_util::target_features; use std::any::Any; use std::path::PathBuf; use std::sync::mpsc; +use std::collections::BTreeMap; use rustc_data_structures::sync::Lrc; use rustc::dep_graph::DepGraph; use rustc::hir::def_id::CrateNum; use rustc::middle::cstore::MetadataLoader; use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource}; +use rustc::middle::lang_items::LangItem; use rustc::session::{Session, CompileIncomplete}; use rustc::session::config::{OutputFilenames, OutputType, PrintRequest}; use rustc::ty::{self, TyCtxt}; @@ -98,6 +99,7 @@ mod back { pub mod symbol_export; pub mod write; mod rpath; + mod wasm; } mod abi; @@ -123,6 +125,7 @@ mod cabi_sparc64; mod cabi_x86; mod cabi_x86_64; mod cabi_x86_win64; +mod cabi_wasm32; mod callee; mod common; mod consts; @@ -200,7 +203,7 @@ impl TransCrate for LlvmTransCrate { target_features(sess) } - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { box metadata::LlvmMetadataLoader } @@ -213,6 +216,8 @@ impl TransCrate for LlvmTransCrate { fn provide_extern(&self, providers: &mut ty::maps::Providers) { back::symbol_export::provide_extern(providers); + base::provide_extern(providers); + attributes::provide_extern(providers); } fn trans_crate<'a, 'tcx>( @@ -238,7 +243,7 @@ impl TransCrate for LlvmTransCrate { back::write::dump_incremental_data(&trans); } - time(sess.time_passes(), + time(sess, "serialize work products", move || rustc_incremental::save_work_products(sess, &dep_graph)); @@ -251,7 +256,7 @@ impl TransCrate for LlvmTransCrate { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - time(sess.time_passes(), "linking", || { + time(sess, "linking", || { back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str()); }); @@ -399,6 +404,10 @@ struct CrateInfo { used_crate_source: FxHashMap>, used_crates_static: Vec<(CrateNum, LibSource)>, used_crates_dynamic: Vec<(CrateNum, LibSource)>, + wasm_custom_sections: BTreeMap>, + wasm_imports: FxHashMap, + lang_item_to_crate: FxHashMap, + missing_lang_items: FxHashMap>>, } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index 45445a48e233..1c8f09ce7b3f 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -61,6 +61,9 @@ unsafe fn configure_llvm(sess: &Session) { add("rustc"); // fake program name if sess.time_llvm_passes() { add("-time-passes"); } if sess.print_llvm_passes() { add("-debug-pass=Structure"); } + if sess.opts.debugging_opts.disable_instrumentation_preinliner { + add("-disable-preinline"); + } for arg in &sess.opts.cg.llvm_args { add(&(*arg)); @@ -92,6 +95,7 @@ const X86_WHITELIST: &'static [&'static str] = &["aes", "avx", "avx2", "avx512bw "bmi1", "bmi2", "fma", "fxsr", "lzcnt", "mmx", "pclmulqdq", "popcnt", "rdrand", "rdseed", + "sha", "sse", "sse2", "sse3", "sse4.1", "sse4.2", "sse4a", "ssse3", "tbm", "xsave", "xsavec", @@ -104,7 +108,21 @@ const POWERPC_WHITELIST: &'static [&'static str] = &["altivec", "power8-vector", "power9-vector", "vsx"]; -const MIPS_WHITELIST: &'static [&'static str] = &["msa"]; +const MIPS_WHITELIST: &'static [&'static str] = &["fp64", "msa"]; + +/// When rustdoc is running, provide a list of all known features so that all their respective +/// primtives may be documented. +/// +/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this +/// iterator! +pub fn all_known_features() -> impl Iterator { + ARM_WHITELIST.iter().cloned() + .chain(AARCH64_WHITELIST.iter().cloned()) + .chain(X86_WHITELIST.iter().cloned()) + .chain(HEXAGON_WHITELIST.iter().cloned()) + .chain(POWERPC_WHITELIST.iter().cloned()) + .chain(MIPS_WHITELIST.iter().cloned()) +} pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { let arch = if sess.target.target.arch == "x86_64" { diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index efb5338f680a..93bc89f0914f 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -12,7 +12,6 @@ use llvm::{self, ValueRef, BasicBlockRef}; use rustc::middle::lang_items; use rustc::ty::{self, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf}; -use rustc::traits; use rustc::mir; use abi::{Abi, FnType, ArgType, PassMode}; use base; @@ -282,7 +281,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ty::TyDynamic(..) => { let fn_ty = drop_fn.ty(bx.cx.tcx); let sig = common::ty_fn_sig(bx.cx, fn_ty); - let sig = bx.tcx().erase_late_bound_regions_and_normalize(&sig); + let sig = bx.tcx().normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); let fn_ty = FnType::new_vtable(bx.cx, sig, &[]); args = &args[..1]; (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty) @@ -419,7 +421,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let (instance, mut llfn) = match callee.layout.ty.sty { ty::TyFnDef(def_id, substs) => { (Some(ty::Instance::resolve(bx.cx.tcx, - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), def_id, substs).unwrap()), None) @@ -431,7 +433,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { }; let def = instance.map(|i| i.def); let sig = callee.layout.ty.fn_sig(bx.tcx()); - let sig = bx.tcx().erase_late_bound_regions_and_normalize(&sig); + let sig = bx.tcx().normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); let abi = sig.abi; // Handle intrinsics old trans wants Expr's for, ourselves. @@ -705,7 +710,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let layout = cx.layout_of(cx.tcx.intern_tup(&[ cx.tcx.mk_mut_ptr(cx.tcx.types.u8), cx.tcx.types.i32 - ], false)); + ])); let slot = PlaceRef::alloca(bx, layout, "personalityslot"); self.personality_slot = Some(slot); slot diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 6aa8b7e5449f..977c7c983d6f 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -12,7 +12,6 @@ use llvm::{self, ValueRef}; use rustc::middle::const_val::{ConstVal, ConstEvalErr}; use rustc_mir::interpret::{read_target_uint, const_val_field}; use rustc::hir::def_id::DefId; -use rustc::traits; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; use rustc::mir::interpret::{Allocation, GlobalId, MemoryPointer, PrimVal, Value as MiriValue}; @@ -126,7 +125,7 @@ pub fn trans_static_initializer<'a, 'tcx>( instance, promoted: None }; - let param_env = ty::ParamEnv::empty(traits::Reveal::All); + let param_env = ty::ParamEnv::reveal_all(); cx.tcx.const_eval(param_env.and(cid))?; let alloc_id = cx @@ -152,7 +151,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { match constant.val { ConstVal::Unevaluated(def_id, ref substs) => { let tcx = bx.tcx(); - let param_env = ty::ParamEnv::empty(traits::Reveal::All); + let param_env = ty::ParamEnv::reveal_all(); let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap(); let cid = GlobalId { instance, @@ -172,7 +171,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ) -> Result> { match constant.literal { mir::Literal::Promoted { index } => { - let param_env = ty::ParamEnv::empty(traits::Reveal::All); + let param_env = ty::ParamEnv::reveal_all(); let cid = mir::interpret::GlobalId { instance: self.instance, promoted: Some(index), @@ -201,7 +200,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let values: Result, _> = (0..fields).map(|field| { let field = const_val_field( bx.tcx(), - ty::ParamEnv::empty(traits::Reveal::All), + ty::ParamEnv::reveal_all(), self.instance, None, mir::Field::new(field as usize), diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index a1044ac87e4c..11dabbeae743 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -16,7 +16,6 @@ use rustc::ty::{self, TypeFoldable}; use rustc::ty::layout::{LayoutOf, TyLayout}; use rustc::mir::{self, Mir}; use rustc::ty::subst::Substs; -use rustc::infer::TransNormalize; use rustc::session::config::FullDebugInfo; use base; use builder::Builder; @@ -108,9 +107,13 @@ pub struct FunctionCx<'a, 'tcx:'a> { impl<'a, 'tcx> FunctionCx<'a, 'tcx> { pub fn monomorphize(&self, value: &T) -> T - where T: TransNormalize<'tcx> + where T: TypeFoldable<'tcx> { - self.cx.tcx.trans_apply_param_substs(self.param_substs, value) + self.cx.tcx.subst_and_normalize_erasing_regions( + self.param_substs, + ty::ParamEnv::reveal_all(), + value, + ) } pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) { @@ -445,7 +448,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let arg_ty = fx.monomorphize(&arg_decl.ty); let tupled_arg_tys = match arg_ty.sty { - ty::TyTuple(ref tys, _) => tys, + ty::TyTuple(ref tys) => tys, _ => bug!("spread argument isn't a tuple?!") }; diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index fa0514952d21..93702bfbbf3b 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -399,7 +399,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { lhs.immediate(), rhs.immediate(), lhs.layout.ty); let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty); - let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool], false); + let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool]); let operand = OperandRef { val: result, layout: bx.cx.layout_of(operand_ty) diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index b5b748494019..579b07929a2f 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -84,6 +84,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } mir::StatementKind::EndRegion(_) | mir::StatementKind::Validate(..) | + mir::StatementKind::UserAssertTy(..) | mir::StatementKind::Nop => bx, } } diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index af957500f700..f37114ee4acd 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -258,7 +258,10 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { cx.layout_of(self.ty.boxed_ty()).llvm_type(cx).ptr_to() } ty::TyFnPtr(sig) => { - let sig = cx.tcx.erase_late_bound_regions_and_normalize(&sig); + let sig = cx.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to() } _ => self.scalar_llvm_type_at(cx, scalar, Size::from_bytes(0)) diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 6a3fd21f3a77..99de124c6e1a 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -21,11 +21,10 @@ #![feature(box_syntax)] #![feature(custom_attribute)] #![allow(unused_attributes)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(quote)] #![feature(rustc_diagnostic_macros)] -#![feature(slice_patterns)] -#![feature(conservative_impl_trait)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] extern crate ar; extern crate flate2; diff --git a/src/librustc_trans_utils/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs index 267c8d2bd03c..47bbd67fb5c7 100644 --- a/src/librustc_trans_utils/symbol_names_test.rs +++ b/src/librustc_trans_utils/symbol_names_test.rs @@ -15,7 +15,6 @@ //! paths etc in all kinds of annoying scenarios. use rustc::hir; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::ty::TyCtxt; use syntax::ast; @@ -34,8 +33,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.dep_graph.with_ignore(|| { let mut visitor = SymbolNamesTest { tcx: tcx }; - // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like - tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir.krate().visit_all_item_likes(&mut visitor); }) } @@ -66,23 +64,16 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - +impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { self.process_attrs(item.id); - intravisit::walk_item(self, item); } - fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - self.process_attrs(ti.id); - intravisit::walk_trait_item(self, ti) + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.process_attrs(trait_item.id); } - fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - self.process_attrs(ii.id); - intravisit::walk_impl_item(self, ii) + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { + self.process_attrs(impl_item.id); } } diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 0d4811c4b025..5cf9819288b5 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -58,7 +58,7 @@ pub trait TransCrate { fn print_version(&self) {} fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] } - fn metadata_loader(&self) -> Box; + fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers); fn provide_extern(&self, _providers: &mut Providers); fn trans_crate<'a, 'tcx>( @@ -84,7 +84,7 @@ pub trait TransCrate { pub struct DummyTransCrate; impl TransCrate for DummyTransCrate { - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { box DummyMetadataLoader(()) } @@ -195,7 +195,7 @@ impl TransCrate for MetadataOnlyTransCrate { } } - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { box NoLlvmMetadataLoader } diff --git a/src/librustc_typeck/README.md b/src/librustc_typeck/README.md index 1abc914e7d66..f00597cb27f0 100644 --- a/src/librustc_typeck/README.md +++ b/src/librustc_typeck/README.md @@ -1,48 +1,5 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). +For high-level intro to how type checking works in rustc, see the +[type checking] chapter of the [rustc guide]. -The `rustc_typeck` crate contains the source for "type collection" and -"type checking", as well as a few other bits of related functionality. -(It draws heavily on the [type inferencing][infer] and -[trait solving][traits] code found in librustc.) - -[infer]: ../librustc/infer/README.md -[traits]: ../librustc/traits/README.md - -## Type collection - -Type "collection" is the process of converting the types found in the -HIR (`hir::Ty`), which represent the syntactic things that the user -wrote, into the **internal representation** used by the compiler -(`Ty<'tcx>`) -- we also do similar conversions for where-clauses and -other bits of the function signature. - -To try and get a sense for the difference, consider this function: - -```rust -struct Foo { } -fn foo(x: Foo, y: self::Foo) { .. } -// ^^^ ^^^^^^^^^ -``` - -Those two parameters `x` and `y` each have the same type: but they -will have distinct `hir::Ty` nodes. Those nodes will have different -spans, and of course they encode the path somewhat differently. But -once they are "collected" into `Ty<'tcx>` nodes, they will be -represented by the exact same internal type. - -Collection is defined as a bundle of queries (e.g., `type_of`) for -computing information about the various functions, traits, and other -items in the crate being compiled. Note that each of these queries is -concerned with *interprocedural* things -- for example, for a function -definition, collection will figure out the type and signature of the -function, but it will not visit the *body* of the function in any way, -nor examine type annotations on local variables (that's the job of -type *checking*). - -For more details, see the `collect` module. - -## Type checking - -TODO +[type checking]: https://rust-lang-nursery.github.io/rustc-guide/type-checking.html +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0df1225cf262..0e93277983f8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -27,6 +27,7 @@ use std::slice; use require_c_abi_if_variadic; use util::common::ErrorReported; use util::nodemap::FxHashSet; +use errors::FatalError; use std::iter; use syntax::{abi, ast}; @@ -337,7 +338,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::Trait(trait_def_id) => trait_def_id, Def::TraitAlias(alias_def_id) => alias_def_id, Def::Err => { - self.tcx().sess.fatal("cannot continue compilation due to previous error"); + FatalError.raise(); } _ => unreachable!(), } @@ -530,7 +531,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let msg = format!("associated type `{}` is private", binding.item_name); tcx.sess.span_err(binding.span, &msg); } - tcx.check_stability(assoc_ty.def_id, ref_id, binding.span); + tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span); Ok(candidate.map_bound(|trait_ref| { ty::ProjectionPredicate { @@ -868,7 +869,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let msg = format!("{} `{}` is private", def.kind_name(), assoc_name); tcx.sess.span_err(span, &msg); } - tcx.check_stability(item.def_id, ref_id, span); + tcx.check_stability(item.def_id, Some(ref_id), span); (ty, def) } @@ -1050,7 +1051,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.never }, hir::TyTup(ref fields) => { - tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)), false) + tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t))) } hir::TyBareFn(ref bf) => { require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index eb02c05fd395..ae373fbad224 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -23,7 +23,6 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::cmp; use syntax::ast; use syntax::codemap::Spanned; -use syntax::feature_gate; use syntax::ptr::P; use syntax_pos::Span; @@ -114,42 +113,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; if pat_adjustments.len() > 0 { - if tcx.features().match_default_bindings { - debug!("default binding mode is now {:?}", def_bm); - self.inh.tables.borrow_mut() - .pat_adjustments_mut() - .insert(pat.hir_id, pat_adjustments); - } else { - let mut ref_sp = pat.span; - let mut id = pat.id; - loop { // make span include all enclosing `&` to avoid confusing diag output - id = tcx.hir.get_parent_node(id); - let node = tcx.hir.find(id); - if let Some(hir::map::NodePat(pat)) = node { - if let hir::PatKind::Ref(..) = pat.node { - ref_sp = pat.span; - } else { - break; - } - } else { - break; - } - } - let sp = ref_sp.to(pat.span); - let mut err = feature_gate::feature_err( - &tcx.sess.parse_sess, - "match_default_bindings", - sp, - feature_gate::GateIssue::Language, - "non-reference pattern used to match a reference", - ); - if let Ok(snippet) = tcx.sess.codemap().span_to_snippet(sp) { - err.span_suggestion(sp, - "consider using a reference", - format!("&{}", &snippet)); - } - err.emit(); - } + debug!("default binding mode is now {:?}", def_bm); + self.inh.tables.borrow_mut() + .pat_adjustments_mut() + .insert(pat.hir_id, pat_adjustments); } } else if let PatKind::Ref(..) = pat.node { // When you encounter a `&pat` pattern, reset to "by @@ -319,7 +286,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut expected_len = elements.len(); if ddpos.is_some() { // Require known type only when `..` is present - if let ty::TyTuple(ref tys, _) = + if let ty::TyTuple(ref tys) = self.structurally_resolved_type(pat.span, expected).sty { expected_len = tys.len(); } @@ -329,10 +296,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let element_tys_iter = (0..max_len).map(|_| self.next_ty_var( // FIXME: MiscVariable for now, obtaining the span and name information // from all tuple elements isn't trivial. - ty::UniverseIndex::ROOT, TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); - let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false)); + let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys)); self.demand_eqtype(pat.span, expected, pat_ty); for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat_walk(elem, &element_tys[i], def_bm, true); @@ -340,8 +306,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pat_ty } PatKind::Box(ref inner) => { - let inner_ty = self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(inner.span)); + let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span)); let uniq_ty = tcx.mk_box(inner_ty); if self.check_dereferencable(pat.span, expected, &inner) { @@ -374,7 +339,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } _ => { let inner_ty = self.next_ty_var( - ty::UniverseIndex::ROOT, TypeVariableOrigin::TypeInference(inner.span)); let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl }; let region = self.next_region_var(infer::PatternRegion(pat.span)); @@ -633,8 +597,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // ...but otherwise we want to use any supertype of the // discriminant. This is sort of a workaround, see note (*) in // `check_pat` for some details. - discrim_ty = self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(discrim.span)); + discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span)); self.check_expr_has_type_or_error(discrim, discrim_ty); }; @@ -695,8 +658,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // arm for inconsistent arms or to the whole match when a `()` type // is required). Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety, - _ => self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(expr.span)), + _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)), }; CoerceMany::with_coercion_sites(coerce_first, arms) }; @@ -861,7 +823,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); self.check_pat_walk(&subpat, field_ty, def_bm, true); - self.tcx.check_stability(variant.fields[i].did, pat.id, subpat.span); + self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span); } } else { let subpats_ending = if subpats.len() == 1 { "" } else { "s" }; @@ -904,6 +866,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // Keep track of which fields have already appeared in the pattern. let mut used_fields = FxHashMap(); + let mut inexistent_fields = vec![]; // Typecheck each field. for &Spanned { node: ref field, span } in fields { let field_ty = match used_fields.entry(field.name) { @@ -922,39 +885,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); vacant.insert(span); field_map.get(&field.name) .map(|f| { - self.tcx.check_stability(f.did, pat_id, span); + self.tcx.check_stability(f.did, Some(pat_id), span); self.field_ty(span, f, substs) }) .unwrap_or_else(|| { - let mut err = struct_span_err!( - tcx.sess, - span, - E0026, - "{} `{}` does not have a field named `{}`", - kind_name, - tcx.item_path_str(variant.did), - field.name - ); - err.span_label(span, - format!("{} `{}` does not have field `{}`", - kind_name, - tcx.item_path_str(variant.did), - field.name)); - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "This error indicates that a struct pattern attempted to \ - extract a non-existent field from a struct. Struct fields \ - are identified by the name used before the colon : so struct \ - patterns should resemble the declaration of the struct type \ - being matched.\n\n\ - If you are using shorthand field patterns but want to refer \ - to the struct field by a different name, you should rename \ - it explicitly." - ); - } - err.emit(); - + inexistent_fields.push((span, field.name)); tcx.types.err }) } @@ -963,6 +899,47 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); self.check_pat_walk(&field.pat, field_ty, def_bm, true); } + if inexistent_fields.len() > 0 { + let (field_names, t, plural) = if inexistent_fields.len() == 1 { + (format!("a field named `{}`", inexistent_fields[0].1), "this", "") + } else { + (format!("fields named {}", + inexistent_fields.iter() + .map(|(_, name)| format!("`{}`", name)) + .collect::>() + .join(", ")), "these", "s") + }; + let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::>(); + let mut err = struct_span_err!(tcx.sess, + spans, + E0026, + "{} `{}` does not have {}", + kind_name, + tcx.item_path_str(variant.did), + field_names); + if let Some((span, _)) = inexistent_fields.last() { + err.span_label(*span, + format!("{} `{}` does not have {} field{}", + kind_name, + tcx.item_path_str(variant.did), + t, + plural)); + } + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "This error indicates that a struct pattern attempted to \ + extract a non-existent field from a struct. Struct fields \ + are identified by the name used before the colon : so struct \ + patterns should resemble the declaration of the struct type \ + being matched.\n\n\ + If you are using shorthand field patterns but want to refer \ + to the struct field by a different name, you should rename \ + it explicitly." + ); + } + err.emit(); + } + // Require `..` if struct has non_exhaustive attribute. if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc { span_err!(tcx.sess, span, E0638, @@ -979,13 +956,25 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); tcx.sess.span_err(span, "`..` cannot be used in union patterns"); } } else if !etc { - for field in variant.fields + let unmentioned_fields = variant.fields .iter() - .filter(|field| !used_fields.contains_key(&field.name)) { + .map(|field| field.name) + .filter(|field| !used_fields.contains_key(&field)) + .collect::>(); + if unmentioned_fields.len() > 0 { + let field_names = if unmentioned_fields.len() == 1 { + format!("field `{}`", unmentioned_fields[0]) + } else { + format!("fields {}", + unmentioned_fields.iter() + .map(|name| format!("`{}`", name)) + .collect::>() + .join(", ")) + }; let mut diag = struct_span_err!(tcx.sess, span, E0027, - "pattern does not mention field `{}`", - field.name); - diag.span_label(span, format!("missing field `{}`", field.name)); + "pattern does not mention {}", + field_names); + diag.span_label(span, format!("missing {}", field_names)); if variant.ctor_kind == CtorKind::Fn { diag.note("trying to match a tuple variant with a struct variant pattern"); } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 3d61ffe39336..b1fb0938698c 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -16,7 +16,7 @@ use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; use rustc::ty::{self, TyCtxt, TypeFoldable, Ty}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use syntax::abi; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -182,7 +182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // For initial two-phase borrow // deployment, conservatively omit // overloaded function call ops. - allow_two_phase_borrow: false, + allow_two_phase_borrow: AllowTwoPhase::No, } }; autoref = Some(Adjustment { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 48bd7b14fc96..8db8e52b10d4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -38,7 +38,7 @@ //! expression, `e as U2` is not necessarily so (in fact it will only be valid if //! `U1` coerces to `U2`). -use super::{Diverges, FnCtxt}; +use super::FnCtxt; use errors::DiagnosticBuilder; use hir::def_id::DefId; @@ -47,6 +47,7 @@ use rustc::hir; use rustc::session::Session; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; +use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::cast::{CastKind, CastTy}; use rustc::ty::subst::Substs; use rustc::middle::lang_items; @@ -59,7 +60,6 @@ use util::common::ErrorReported; pub struct CastCheck<'tcx> { expr: &'tcx hir::Expr, expr_ty: Ty<'tcx>, - expr_diverges: Diverges, cast_ty: Ty<'tcx>, cast_span: Span, span: Span, @@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - ty::TyTuple(fields, _) => match fields.last() { + ty::TyTuple(fields) => match fields.last() { None => Some(PointerKind::Thin), Some(f) => self.pointer_kind(f, span)? }, @@ -183,7 +183,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, expr_ty: Ty<'tcx>, - expr_diverges: Diverges, cast_ty: Ty<'tcx>, cast_span: Span, span: Span) @@ -191,7 +190,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { let check = CastCheck { expr, expr_ty, - expr_diverges, cast_ty, cast_span, span, @@ -437,8 +435,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, self.expr_ty, - self.expr_diverges, - fcx.tcx.mk_fn_ptr(f)); + fcx.tcx.mk_fn_ptr(f), + AllowTwoPhase::No); if !res.is_ok() { return Err(CastError::NonScalar); } @@ -620,7 +618,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool { - fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, self.cast_ty).is_ok() + fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok() } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 72e4b726a22b..68b0560355fc 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -110,8 +110,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { |_, _| span_bug!(expr.span, "closure has region param"), |_, _| { self.infcx - .next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::ClosureSynthetic(expr.span)) + .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)) }, ); let substs = ty::ClosureSubsts { substs }; @@ -140,7 +139,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // the `closures` table. let sig = bound_sig.map_bound(|sig| { self.tcx.mk_fn_sig( - iter::once(self.tcx.intern_tup(sig.inputs(), false)), + iter::once(self.tcx.intern_tup(sig.inputs())), sig.output(), sig.variadic, sig.unsafety, @@ -312,7 +311,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); let input_tys = match arg_param_ty.sty { - ty::TyTuple(tys, _) => tys.into_iter(), + ty::TyTuple(tys) => tys.into_iter(), _ => { return None; } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index abb0acd699cb..a8d1f69dfe84 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -66,9 +66,8 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::infer::{Coercion, InferResult, InferOk}; use rustc::infer::type_variable::TypeVariableOrigin; -use rustc::lint; use rustc::traits::{self, ObligationCause, ObligationCauseCode}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; @@ -85,6 +84,13 @@ struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, cause: ObligationCause<'tcx>, use_lub: bool, + /// Determines whether or not allow_two_phase_borrow is set on any + /// autoref adjustments we create while coercing. We don't want to + /// allow deref coercions to create two-phase borrows, at least initially, + /// but we do need two-phase borrows for function argument reborrows. + /// See #47489 and #48598 + /// See docs on the "AllowTwoPhase" type for a more detailed discussion + allow_two_phase: AllowTwoPhase, } impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> { @@ -124,10 +130,13 @@ fn success<'tcx>(adj: Vec>, } impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { - fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self { + fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, + cause: ObligationCause<'tcx>, + allow_two_phase: AllowTwoPhase) -> Self { Coerce { fcx, cause, + allow_two_phase, use_lub: false, } } @@ -177,7 +186,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // micro-optimization: no need for this if `b` is // already resolved in some way. let diverging_ty = self.next_diverging_ty_var( - ty::UniverseIndex::ROOT, TypeVariableOrigin::AdjustmentType(self.cause.span)); self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny)) } else { @@ -425,10 +433,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let mutbl = match mt_b.mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { - // Deref-coercion is a case where we deliberately - // disallow two-phase borrows in its initial - // deployment; see discussion on PR #47489. - allow_two_phase_borrow: false, + allow_two_phase_borrow: self.allow_two_phase, } }; adjustments.push(Adjustment { @@ -474,7 +479,10 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let mutbl = match mt_b.mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { - allow_two_phase_borrow: false, + // We don't allow two-phase borrows here, at least for initial + // implementation. If it happens that this coercion is a function argument, + // the reborrow in coerce_borrowed_ptr will pick it up. + allow_two_phase_borrow: AllowTwoPhase::No, } }; Some((Adjustment { @@ -511,7 +519,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. let origin = TypeVariableOrigin::MiscVariable(self.cause.span); - let coerce_target = self.next_ty_var(ty::UniverseIndex::ROOT, origin); + let coerce_target = self.next_ty_var(origin); let mut coercion = self.unify_and(coerce_target, target, |target| { let unsize = Adjustment { kind: Adjust::Unsize, @@ -572,7 +580,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // Object safety violations or miscellaneous. Err(err) => { - self.report_selection_error(&obligation, &err); + self.report_selection_error(&obligation, &err, false); // Treat this like an obligation and follow through // with the unsizing - the lack of a coercion should // be silent, as it causes a type mismatch later. @@ -752,29 +760,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn try_coerce(&self, expr: &hir::Expr, expr_ty: Ty<'tcx>, - expr_diverges: Diverges, - target: Ty<'tcx>) + target: Ty<'tcx>, + allow_two_phase: AllowTwoPhase) -> RelateResult<'tcx, Ty<'tcx>> { let source = self.resolve_type_vars_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); - // Special-ish case: we can coerce any type `T` into the `!` - // type, but only if the source expression diverges. - if target.is_never() && expr_diverges.always() { - debug!("permit coercion to `!` because expr diverges"); - if self.can_eq(self.param_env, source, target).is_err() { - self.tcx.lint_node( - lint::builtin::COERCE_NEVER, - expr.id, - expr.span, - &format!("cannot coerce `{}` to !", source) - ); - return Ok(target); - } - } - let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable); - let coerce = Coerce::new(self, cause); + let coerce = Coerce::new(self, cause, allow_two_phase); let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?; let (adjustments, _) = self.register_infer_ok_obligations(ok); @@ -788,7 +781,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("coercion::can({:?} -> {:?})", source, target); let cause = self.cause(syntax_pos::DUMMY_SP, ObligationCauseCode::ExprAssignable); - let coerce = Coerce::new(self, cause); + // We don't ever need two-phase here since we throw out the result of the coercion + let coerce = Coerce::new(self, cause, AllowTwoPhase::No); self.probe(|_| coerce.coerce(source, target)).is_ok() } @@ -857,7 +851,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return Ok(fn_ptr); } - let mut coerce = Coerce::new(self, cause.clone()); + // Configure a Coerce instance to compute the LUB. + // We don't allow two-phase borrows on any autorefs this creates since we + // probably aren't processing function arguments here and even if we were, + // they're going to get autorefed again anyway and we can apply 2-phase borrows + // at that time. + let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No); coerce.use_lub = true; // First try to coerce the new expression to the type of the previous ones, @@ -1123,7 +1122,8 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> if self.pushed == 0 { // Special-case the first expression we are coercing. // To be honest, I'm not entirely sure why we do this. - fcx.try_coerce(expression, expression_ty, expression_diverges, self.expected_ty) + // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why + fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No) } else { match self.expressions { Expressions::Dynamic(ref exprs) => diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index d0419382bc31..e1e3dea9a2a1 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -218,8 +218,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id); let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), - Reveal::UserFacing, - ty::UniverseIndex::ROOT); + Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, @@ -334,7 +333,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None); + infcx.report_fulfillment_errors(errors, None, false); return Err(ErrorReported); } @@ -501,9 +500,13 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::TraitContainer(_) => tcx.mk_self_type() }; let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); - let param_env = ty::ParamEnv::empty(Reveal::All); + let param_env = ty::ParamEnv::reveal_all(); tcx.infer_ctxt().enter(|infcx| { + let self_arg_ty = tcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_arg_ty) + ); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok(); match ExplicitSelf::determine(self_arg_ty, can_eq_self) { ExplicitSelf::ByValue => "self".to_string(), @@ -755,7 +758,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); tcx.infer_ctxt().enter(|infcx| { - let param_env = ty::ParamEnv::empty(Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); let inh = Inherited::new(infcx, impl_c.def_id); let infcx = &inh.infcx; @@ -835,7 +838,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all obligations are satisfied by the implementation's // version. if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(errors, None); + infcx.report_fulfillment_errors(errors, None, false); return; } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index d2702d0810ed..ecfe14160502 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -16,11 +16,13 @@ use rustc::traits::ObligationCause; use syntax::ast; use syntax::util::parser::PREC_POSTFIX; -use syntax_pos::{self, Span}; +use syntax_pos::Span; use rustc::hir; -use rustc::hir::print; use rustc::hir::def::Def; +use rustc::hir::map::NodeItem; +use rustc::hir::{Item, ItemConst, print}; use rustc::ty::{self, Ty, AssociatedItem}; +use rustc::ty::adjustment::AllowTwoPhase; use errors::{DiagnosticBuilder, CodeMapper}; use super::method::probe; @@ -79,9 +81,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, - expected: Ty<'tcx>) + expected: Ty<'tcx>, + allow_two_phase: AllowTwoPhase) -> Ty<'tcx> { - let (ty, err) = self.demand_coerce_diag(expr, checked_ty, expected); + let (ty, err) = self.demand_coerce_diag(expr, checked_ty, expected, allow_two_phase); if let Some(mut err) = err { err.emit(); } @@ -96,11 +99,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_coerce_diag(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, - expected: Ty<'tcx>) + expected: Ty<'tcx>, + allow_two_phase: AllowTwoPhase) -> (Ty<'tcx>, Option>) { let expected = self.resolve_type_vars_with_obligations(expected); - let e = match self.try_coerce(expr, checked_ty, self.diverges.get(), expected) { + let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) { Ok(ty) => return (ty, None), Err(e) => e }; @@ -139,7 +143,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) { err.span_suggestion(expr.span, msg, suggestion); } else if !self.check_for_cast(&mut err, expr, expr_ty, expected) { - let methods = self.get_conversion_methods(expected, checked_ty); + let methods = self.get_conversion_methods(expr.span, expected, checked_ty); if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) { let suggestions = iter::repeat(expr_text).zip(methods.iter()) .map(|(receiver, method)| format!("{}.{}()", receiver, method.name)) @@ -154,9 +158,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (expected, Some(err)) } - fn get_conversion_methods(&self, expected: Ty<'tcx>, checked_ty: Ty<'tcx>) + fn get_conversion_methods(&self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>) -> Vec { - let mut methods = self.probe_for_return_type(syntax_pos::DUMMY_SP, + let mut methods = self.probe_for_return_type(span, probe::Mode::MethodCall, expected, checked_ty, @@ -318,6 +322,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>) -> bool { + let parent_id = self.tcx.hir.get_parent_node(expr.id); + match self.tcx.hir.find(parent_id) { + Some(parent) => { + // Shouldn't suggest `.into()` on `const`s. + if let NodeItem(Item { node: ItemConst(_, _), .. }) = parent { + // FIXME(estebank): modify once we decide to suggest `as` casts + return false; + } + } + None => {} + }; + let will_truncate = "will truncate the source value"; let depending_on_isize = "will truncate or zero-extend depending on the bit width of \ `isize`"; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 165cfe6604e8..b8aa39a202be 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -16,10 +16,10 @@ use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::middle::region; use rustc::ty::subst::{Subst, Substs, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::traits::{self, Reveal, ObligationCause}; +use rustc::traits::{ObligationCause, TraitEngine}; use util::common::ErrorReported; -use util::nodemap::FxHashSet; +use syntax::ast; use syntax_pos::Span; /// check_drop_impl confirms that the Drop implementation identified by @@ -84,13 +84,13 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( tcx.infer_ctxt().enter(|ref infcx| { let impl_param_env = tcx.param_env(self_type_did); let tcx = infcx.tcx; - let mut fulfillment_cx = traits::FulfillmentContext::new(); + let mut fulfillment_cx = TraitEngine::new(tcx); let named_type = tcx.type_of(self_type_did); let drop_impl_span = tcx.def_span(drop_impl_did); let fresh_impl_substs = - infcx.fresh_substs_for_item(ty::UniverseIndex::ROOT, drop_impl_span, drop_impl_did); + infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did); let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs); let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id); @@ -112,7 +112,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) { // this could be reached when we get lazy normalization - infcx.report_fulfillment_errors(errors, None); + infcx.report_fulfillment_errors(errors, None, false); return Err(ErrorReported); } @@ -126,7 +126,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // it did the wrong thing, so I chose to preserve existing // behavior, since it ought to be simply more // conservative. -nmatsakis - let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty(Reveal::UserFacing)); + let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); infcx.resolve_regions_and_report_errors(drop_impl_did, ®ion_scope_tree, &outlives_env); Ok(()) @@ -282,6 +282,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>( rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, span: Span, + body_id: ast::NodeId, scope: region::Scope) -> Result<(), ErrorReported> { @@ -297,46 +298,15 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>( }; let parent_scope = rcx.tcx.mk_region(ty::ReScope(parent_scope)); let origin = || infer::SubregionOrigin::SafeDestructor(span); - - let ty = rcx.fcx.resolve_type_vars_if_possible(&ty); - let for_ty = ty; - let mut types = vec![(ty, 0)]; - let mut known = FxHashSet(); - while let Some((ty, depth)) = types.pop() { - let ty::DtorckConstraint { - dtorck_types, outlives - } = rcx.tcx.dtorck_constraint_for_ty(span, for_ty, depth, ty)?; - - for ty in dtorck_types { - let ty = rcx.fcx.normalize_associated_types_in(span, &ty); - let ty = rcx.fcx.resolve_type_vars_with_obligations(ty); - let ty = rcx.fcx.resolve_type_and_region_vars_if_possible(&ty); - match ty.sty { - // All parameters live for the duration of the - // function. - ty::TyParam(..) => {} - - // A projection that we couldn't resolve - it - // might have a destructor. - ty::TyProjection(..) | ty::TyAnon(..) => { - rcx.type_must_outlive(origin(), ty, parent_scope); - } - - _ => { - if let None = known.replace(ty) { - types.push((ty, depth+1)); - } - } - } - } - - for outlive in outlives { - match outlive.unpack() { - UnpackedKind::Lifetime(lt) => rcx.sub_regions(origin(), parent_scope, lt), - UnpackedKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope), - } + let cause = &ObligationCause::misc(span, body_id); + let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty); + debug!("dropck_outlives = {:#?}", infer_ok); + let kinds = rcx.fcx.register_infer_ok_obligations(infer_ok); + for kind in kinds { + match kind.unpack() { + UnpackedKind::Lifetime(r) => rcx.sub_regions(origin(), parent_scope, r), + UnpackedKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope), } } - Ok(()) } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 2e00040d99a7..377e3a891840 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -87,7 +87,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0), param(0)], - tcx.intern_tup(&[param(0), tcx.types.bool], false)), + tcx.intern_tup(&[param(0), tcx.types.bool])), "load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)), "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], @@ -281,9 +281,9 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec![param(0), param(0)], - tcx.intern_tup(&[param(0), tcx.types.bool], false)), + tcx.intern_tup(&[param(0), tcx.types.bool])), - "unchecked_div" | "unchecked_rem" => + "unchecked_div" | "unchecked_rem" | "exact_div" => (1, vec![param(0), param(0)], param(0)), "unchecked_shl" | "unchecked_shr" => (1, vec![param(0), param(0)], param(0)), @@ -355,12 +355,22 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } "simd_add" | "simd_sub" | "simd_mul" | "simd_rem" | "simd_div" | "simd_shl" | "simd_shr" | - "simd_and" | "simd_or" | "simd_xor" => { + "simd_and" | "simd_or" | "simd_xor" | + "simd_fmin" | "simd_fmax" => { (1, vec![param(0), param(0)], param(0)) } "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)), "simd_cast" => (2, vec![param(0)], param(1)), + "simd_select" => (2, vec![param(0), param(1), param(1)], param(1)), + "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool), + "simd_reduce_add_ordered" | "simd_reduce_mul_ordered" + => (2, vec![param(0), param(1)], param(1)), + "simd_reduce_add_unordered" | "simd_reduce_mul_unordered" | + "simd_reduce_and" | "simd_reduce_or" | "simd_reduce_xor" | + "simd_reduce_min" | "simd_reduce_max" | + "simd_reduce_min_nanless" | "simd_reduce_max_nanless" + => (2, vec![param(0)], param(1)), name if name.starts_with("simd_shuffle") => { match name["simd_shuffle".len()..].parse() { Ok(n) => { @@ -441,7 +451,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>( match *expected { Void => match t.sty { - ty::TyTuple(ref v, _) if v.is_empty() => {}, + ty::TyTuple(ref v) if v.is_empty() => {}, _ => simple_error(&format!("`{}`", t), "()"), }, // (The width we pass to LLVM doesn't concern the type checker.) @@ -515,7 +525,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>( } Aggregate(_flatten, ref expected_contents) => { match t.sty { - ty::TyTuple(contents, _) => { + ty::TyTuple(contents) => { if contents.len() != expected_contents.len() { simple_error(&format!("tuple with length {}", contents.len()), &format!("tuple with length {}", expected_contents.len())); diff --git a/src/librustc_typeck/check/method/README.md b/src/librustc_typeck/check/method/README.md deleted file mode 100644 index b5d317d60253..000000000000 --- a/src/librustc_typeck/check/method/README.md +++ /dev/null @@ -1,111 +0,0 @@ -# Method lookup - -Method lookup can be rather complex due to the interaction of a number -of factors, such as self types, autoderef, trait lookup, etc. This -file provides an overview of the process. More detailed notes are in -the code itself, naturally. - -One way to think of method lookup is that we convert an expression of -the form: - - receiver.method(...) - -into a more explicit UFCS form: - - Trait::method(ADJ(receiver), ...) // for a trait call - ReceiverType::method(ADJ(receiver), ...) // for an inherent method call - -Here `ADJ` is some kind of adjustment, which is typically a series of -autoderefs and then possibly an autoref (e.g., `&**receiver`). However -we sometimes do other adjustments and coercions along the way, in -particular unsizing (e.g., converting from `[T; n]` to `[T]`). - -## The Two Phases - -Method lookup is divided into two major phases: probing (`probe.rs`) -and confirmation (`confirm.rs`). The probe phase is when we decide -what method to call and how to adjust the receiver. The confirmation -phase "applies" this selection, updating the side-tables, unifying -type variables, and otherwise doing side-effectful things. - -One reason for this division is to be more amenable to caching. The -probe phase produces a "pick" (`probe::Pick`), which is designed to be -cacheable across method-call sites. Therefore, it does not include -inference variables or other information. - -## Probe phase - -The probe phase (`probe.rs`) decides what method is being called and -how to adjust the receiver. - -### Steps - -The first thing that the probe phase does is to create a series of -*steps*. This is done by progressively dereferencing the receiver type -until it cannot be deref'd anymore, as well as applying an optional -"unsize" step. So if the receiver has type `Rc>`, this -might yield: - - Rc> - Box<[T; 3]> - [T; 3] - [T] - -### Candidate assembly - -We then search along those steps to create a list of *candidates*. A -`Candidate` is a method item that might plausibly be the method being -invoked. For each candidate, we'll derive a "transformed self type" -that takes into account explicit self. - -Candidates are grouped into two kinds, inherent and extension. - -**Inherent candidates** are those that are derived from the -type of the receiver itself. So, if you have a receiver of some -nominal type `Foo` (e.g., a struct), any methods defined within an -impl like `impl Foo` are inherent methods. Nothing needs to be -imported to use an inherent method, they are associated with the type -itself (note that inherent impls can only be defined in the same -module as the type itself). - -FIXME: Inherent candidates are not always derived from impls. If you -have a trait object, such as a value of type `Box`, then the -trait methods (`to_string()`, in this case) are inherently associated -with it. Another case is type parameters, in which case the methods of -their bounds are inherent. However, this part of the rules is subject -to change: when DST's "impl Trait for Trait" is complete, trait object -dispatch could be subsumed into trait matching, and the type parameter -behavior should be reconsidered in light of where clauses. - -**Extension candidates** are derived from imported traits. If I have -the trait `ToString` imported, and I call `to_string()` on a value of -type `T`, then we will go off to find out whether there is an impl of -`ToString` for `T`. These kinds of method calls are called "extension -methods". They can be defined in any module, not only the one that -defined `T`. Furthermore, you must import the trait to call such a -method. - -So, let's continue our example. Imagine that we were calling a method -`foo` with the receiver `Rc>` and there is a trait `Foo` -that defines it with `&self` for the type `Rc` as well as a method -on the type `Box` that defines `Foo` but with `&mut self`. Then we -might have two candidates: - - &Rc> from the impl of `Foo` for `Rc` where `U=Box - &mut Box<[T; 3]>> from the inherent impl on `Box` where `U=[T; 3]` - -### Candidate search - -Finally, to actually pick the method, we will search down the steps, -trying to match the receiver type against the candidate types. At -each step, we also consider an auto-ref and auto-mut-ref to see whether -that makes any of the candidates match. We pick the first step where -we find a match. - -In the case of our example, the first step is `Rc>`, -which does not itself match any candidate. But when we autoref it, we -get the type `&Rc>` which does match. We would then -recursively consider all where-clauses that appear on the impl: if -those match (or we cannot rule out that they do), then this is the -method we would pick. Otherwise, we would continue down the series of -steps. diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index b777ac30920c..3705c53a76fa 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -17,7 +17,8 @@ use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty}; use rustc::ty::subst::Subst; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, OverloadedDeref}; +use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; +use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk}; use syntax_pos::Span; @@ -170,7 +171,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { hir::MutMutable => AutoBorrowMutability::Mutable { // Method call receivers are the primary use case // for two-phase borrows. - allow_two_phase_borrow: true, + allow_two_phase_borrow: AllowTwoPhase::Yes, } }; adjustments.push(Adjustment { @@ -259,7 +260,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // the process we will unify the transformed-self-type // of the method with the actual type in order to // unify some of these variables. - self.fresh_substs_for_item(ty::UniverseIndex::ROOT, self.span, trait_def_id) + self.fresh_substs_for_item(self.span, trait_def_id) } probe::WhereClausePick(ref poly_trait_ref) => { @@ -309,7 +310,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // variables. let method_generics = self.tcx.generics_of(pick.item.def_id); let mut fn_segment = Some((segment, method_generics)); - self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true); + self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true, false); // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. @@ -336,7 +337,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { { self.to_ty(ast_ty) } else { - self.type_var_for_def(ty::UniverseIndex::ROOT, self.span, def) + self.type_var_for_def(self.span, def) } }) } @@ -544,7 +545,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // For initial two-phase borrow // deployment, conservatively omit // overloaded operators. - allow_two_phase_borrow: false, + allow_two_phase_borrow: AllowTwoPhase::No, } }; adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(region, mutbl)); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f7bb1a6a2323..e33e4c518924 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Method lookup: the secret sauce of Rust. See `README.md`. +//! Method lookup: the secret sauce of Rust. See the [rustc guide] chapter. +//! +//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/method-lookup.html use check::FnCtxt; use hir::def::Def; @@ -169,7 +171,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .unwrap().insert(import_def_id); } - self.tcx.check_stability(pick.item.def_id, call_expr.id, span); + self.tcx.check_stability(pick.item.def_id, Some(call_expr.id), span); let result = self.confirm_method(span, self_expr, @@ -255,7 +257,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else if let Some(ref input_types) = opt_input_types { input_types[def.index as usize - 1] } else { - self.type_var_for_def(ty::UniverseIndex::ROOT, span, def) + self.type_var_for_def(span, def) } }); @@ -369,7 +371,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let def = pick.item.def(); - self.tcx.check_stability(def.def_id(), expr_id, span); + self.tcx.check_stability(def.def_id(), Some(expr_id), span); Ok(def) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4d344eb27990..fa2022e8cc99 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -23,9 +23,10 @@ use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable}; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::util::nodemap::FxHashSet; use rustc::infer::{self, InferOk}; +use rustc::middle::stability; use syntax::ast; use syntax::util::lev_distance::{lev_distance, find_best_match_for_name}; -use syntax_pos::Span; +use syntax_pos::{Span, symbol::Symbol}; use rustc::hir; use rustc::lint; use std::mem; @@ -38,6 +39,7 @@ pub use self::PickKind::*; /// Boolean flag used to indicate if this search is for a suggestion /// or not. If true, we can allow ambiguity and so forth. +#[derive(Clone, Copy)] pub struct IsSuggestion(pub bool); struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -65,6 +67,8 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting unsatisfied_predicates: Vec>, + + is_suggestion: IsSuggestion, } impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> { @@ -276,8 +280,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // this creates one big transaction so that all type variables etc // that we create during the probe process are removed later self.probe(|_| { - let mut probe_cx = - ProbeContext::new(self, span, mode, method_name, return_type, Rc::new(steps)); + let mut probe_cx = ProbeContext::new( + self, span, mode, method_name, return_type, Rc::new(steps), is_suggestion, + ); probe_cx.assemble_inherent_candidates(); match scope { @@ -326,7 +331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if reached_raw_pointer && !self.tcx.features().arbitrary_self_types { // this case used to be allowed by the compiler, - // so we do a future-compat lint here for the 2015 epoch + // so we do a future-compat lint here for the 2015 edition // (see https://github.com/rust-lang/rust/issues/46906) if self.tcx.sess.rust_2018() { span_err!(self.tcx.sess, span, E0908, @@ -378,7 +383,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { mode: Mode, method_name: Option, return_type: Option>, - steps: Rc>>) + steps: Rc>>, + is_suggestion: IsSuggestion) -> ProbeContext<'a, 'gcx, 'tcx> { ProbeContext { fcx, @@ -394,6 +400,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { allow_similar_names: false, private_candidate: None, unsatisfied_predicates: Vec::new(), + is_suggestion, } } @@ -729,9 +736,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { Def::Method(def_id) => { let fty = self.tcx.fn_sig(def_id); self.probe(|_| { - let substs = self.fresh_substs_for_item(ty::UniverseIndex::ROOT, - self.span, - method.def_id); + let substs = self.fresh_substs_for_item(self.span, method.def_id); let fty = fty.subst(self.tcx, substs); let (fty, _) = self.replace_late_bound_regions_with_fresh_var( self.span, infer::FnCall, &fty); @@ -937,30 +942,57 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); let mut possibly_unsatisfied_predicates = Vec::new(); + let mut unstable_candidates = Vec::new(); - debug!("searching inherent candidates"); - if let Some(pick) = self.consider_candidates(self_ty, - &self.inherent_candidates, - &mut possibly_unsatisfied_predicates) { - return Some(pick); + for (kind, candidates) in &[ + ("inherent", &self.inherent_candidates), + ("extension", &self.extension_candidates), + ] { + debug!("searching {} candidates", kind); + let res = self.consider_candidates( + self_ty, + candidates.iter(), + &mut possibly_unsatisfied_predicates, + Some(&mut unstable_candidates), + ); + if let Some(pick) = res { + if !self.is_suggestion.0 && !unstable_candidates.is_empty() { + if let Ok(p) = &pick { + // Emit a lint if there are unstable candidates alongside the stable ones. + // + // We suppress warning if we're picking the method only because it is a + // suggestion. + self.emit_unstable_name_collision_hint(p, &unstable_candidates); + } + } + return Some(pick); + } } - debug!("searching extension candidates"); - let res = self.consider_candidates(self_ty, - &self.extension_candidates, - &mut possibly_unsatisfied_predicates); - if let None = res { + debug!("searching unstable candidates"); + let res = self.consider_candidates( + self_ty, + unstable_candidates.into_iter().map(|(c, _)| c), + &mut possibly_unsatisfied_predicates, + None, + ); + if res.is_none() { self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates); } res } - fn consider_candidates(&self, - self_ty: Ty<'tcx>, - probes: &[Candidate<'tcx>], - possibly_unsatisfied_predicates: &mut Vec>) - -> Option> { - let mut applicable_candidates: Vec<_> = probes.iter() + fn consider_candidates<'b, ProbesIter>( + &self, + self_ty: Ty<'tcx>, + probes: ProbesIter, + possibly_unsatisfied_predicates: &mut Vec>, + unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, + ) -> Option> + where + ProbesIter: Iterator> + Clone, + { + let mut applicable_candidates: Vec<_> = probes.clone() .map(|probe| { (probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates)) }) @@ -975,8 +1007,20 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } } + if let Some(uc) = unstable_candidates { + applicable_candidates.retain(|&(p, _)| { + if let stability::EvalResult::Deny { feature, .. } = + self.tcx.eval_stability(p.item.def_id, None, self.span) + { + uc.push((p, feature)); + return false; + } + true + }); + } + if applicable_candidates.len() > 1 { - let sources = probes.iter() + let sources = probes .map(|p| self.candidate_source(p, self_ty)) .collect(); return Some(Err(MethodError::Ambiguity(sources))); @@ -991,6 +1035,39 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }) } + fn emit_unstable_name_collision_hint( + &self, + stable_pick: &Pick, + unstable_candidates: &[(&Candidate<'tcx>, Symbol)], + ) { + let mut diag = self.tcx.struct_span_lint_node( + lint::builtin::UNSTABLE_NAME_COLLISION, + self.fcx.body_id, + self.span, + "a method with this name may be added to the standard library in the future", + ); + + // FIXME: This should be a `span_suggestion` instead of `help`. However `self.span` only + // highlights the method name, so we can't use it. Also consider reusing the code from + // `report_method_error()`. + diag.help(&format!( + "call with fully qualified syntax `{}(...)` to keep using the current method", + self.tcx.item_path_str(stable_pick.item.def_id), + )); + + if ::rustc::session::config::nightly_options::is_nightly_build() { + for (candidate, feature) in unstable_candidates { + diag.note(&format!( + "add #![feature({})] to the crate attributes to enable `{}`", + feature, + self.tcx.item_path_str(candidate.item.def_id), + )); + } + } + + diag.emit(); + } + fn select_trait_candidate(&self, trait_ref: ty::TraitRef<'tcx>) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> { @@ -1190,7 +1267,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let steps = self.steps.clone(); self.probe(|_| { let mut pcx = ProbeContext::new(self.fcx, self.span, self.mode, self.method_name, - self.return_type, steps); + self.return_type, steps, IsSuggestion(true)); pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); pcx.assemble_extension_candidates_for_traits_in_scope(ast::DUMMY_NODE_ID)?; @@ -1310,7 +1387,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { if i < substs.len() { substs.type_at(i) } else { - self.type_var_for_def(ty::UniverseIndex::ROOT, self.span, def) + self.type_var_for_def(self.span, def) } }); xform_fn_sig.subst(self.tcx, substs) @@ -1327,7 +1404,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { def_id, |_, _| self.tcx.types.re_erased, |_, _| self.next_ty_var( - ty::UniverseIndex::ROOT, TypeVariableOrigin::SubstitutionPlaceholder( self.tcx.def_span(def_id)))) } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5c20490f8230..4bc2d8ce123a 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -22,12 +22,14 @@ use rustc::traits::{Obligation, SelectionContext}; use util::nodemap::FxHashSet; use syntax::ast; +use syntax::util::lev_distance::find_best_match_for_name; use errors::DiagnosticBuilder; use syntax_pos::Span; use rustc::hir; use rustc::hir::print; use rustc::infer::type_variable::TypeVariableOrigin; +use rustc::ty::TyAdt; use std::cell; use std::cmp::Ordering; @@ -54,8 +56,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.autoderef(span, ty).any(|(ty, _)| { self.probe(|_| { let fn_once_substs = tcx.mk_substs_trait(ty, - &[self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(span))]); + &[self.next_ty_var(TypeVariableOrigin::MiscVariable(span))]); let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs); let poly_trait_ref = trait_ref.to_poly_trait_ref(); let obligation = @@ -179,9 +180,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let actual = self.resolve_type_vars_if_possible(&rcvr_ty); let ty_string = self.ty_to_string(actual); let is_method = mode == Mode::MethodCall; + let mut suggestion = None; let type_str = if is_method { "method" } else if actual.is_enum() { + if let TyAdt(ref adt_def, _) = actual.sty { + let names = adt_def.variants.iter().map(|s| &s.name); + suggestion = find_best_match_for_name(names, + &item_name.as_str(), + None); + } "variant" } else { match (item_name.as_str().chars().next(), actual.is_fresh_ty()) { @@ -256,7 +264,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.emit(); return; } else { - struct_span_err!( + let mut err = struct_span_err!( tcx.sess, span, E0599, @@ -264,7 +272,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { type_str, item_name, ty_string - ) + ); + if let Some(suggestion) = suggestion { + err.note(&format!("did you mean `{}::{}`?", type_str, suggestion)); + } + err } } else { tcx.sess.diagnostic().struct_dummy() @@ -718,8 +730,15 @@ impl<'a> Iterator for AllTraits<'a> { TraitInfo::new(*info) }) } + + fn size_hint(&self) -> (usize, Option) { + let len = self.borrow.as_ref().unwrap().len() - self.idx; + (len, Some(len)) + } } +impl<'a> ExactSizeIterator for AllTraits<'a> {} + struct UsePlacementFinder<'a, 'tcx: 'a, 'gcx: 'tcx> { target_module: ast::NodeId, @@ -767,7 +786,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, ' // don't suggest placing a use before the prelude // import or other generated ones if item.span.ctxt().outer().expn_info().is_none() { - self.span = Some(item.span.with_hi(item.span.lo())); + self.span = Some(item.span.shrink_to_lo()); self.found_use = true; return; } @@ -779,12 +798,12 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, ' if item.span.ctxt().outer().expn_info().is_none() { // don't insert between attributes and an item if item.attrs.is_empty() { - self.span = Some(item.span.with_hi(item.span.lo())); + self.span = Some(item.span.shrink_to_lo()); } else { // find the first attribute on the item for attr in &item.attrs { if self.span.map_or(true, |span| attr.span < span) { - self.span = Some(attr.span.with_hi(attr.span.lo())); + self.span = Some(attr.span.shrink_to_lo()); } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 19085ff039ec..27e0f6ad6ddd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,9 +95,9 @@ use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::mir::interpret::{GlobalId}; use rustc::ty::subst::{Kind, Subst, Substs}; -use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; +use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate}; -use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt, Discr}; @@ -195,7 +195,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { locals: RefCell>>, - fulfillment_cx: RefCell>, + fulfillment_cx: RefCell>>, // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or @@ -362,8 +362,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { /// hard constraint exists, creates a fresh type variable. fn coercion_target_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span) -> Ty<'tcx> { self.only_has_type(fcx) - .unwrap_or_else(|| fcx.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(span))) + .unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span))) } } @@ -634,7 +633,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { maybe_tables: infcx.in_progress_tables, }, infcx, - fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), + fulfillment_cx: RefCell::new(TraitEngine::new(tcx)), locals: RefCell::new(NodeMap()), deferred_call_resolutions: RefCell::new(DefIdMap()), deferred_cast_checks: RefCell::new(Vec::new()), @@ -718,6 +717,18 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum })?) } +fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::check_item_well_formed(tcx, def_id); +} + +fn check_trait_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::check_trait_item(tcx, def_id); +} + +fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::check_impl_item(tcx, def_id); +} + pub fn provide(providers: &mut Providers) { *providers = Providers { typeck_item_bodies, @@ -725,6 +736,9 @@ pub fn provide(providers: &mut Providers) { has_typeck_tables, adt_destructor, used_trait_imports, + check_item_well_formed, + check_trait_item_well_formed, + check_impl_item_well_formed, ..*providers }; } @@ -873,11 +887,12 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; // All type checking constraints were added, try to fallback unsolved variables. - fcx.select_obligations_where_possible(); + fcx.select_obligations_where_possible(false); + let mut fallback_has_occurred = false; for ty in &fcx.unsolved_variables() { - fcx.fallback_if_possible(ty); + fallback_has_occurred |= fcx.fallback_if_possible(ty); } - fcx.select_obligations_where_possible(); + fcx.select_obligations_where_possible(fallback_has_occurred); // Even though coercion casts provide type hints, we check casts after fallback for // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. @@ -922,8 +937,7 @@ impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> { match ty_opt { None => { // infer the variable's type - let var_ty = self.fcx.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(span)); + let var_ty = self.fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); self.fcx.locals.borrow_mut().insert(nid, var_ty); var_ty } @@ -944,10 +958,19 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { // Add explicitly-declared locals. fn visit_local(&mut self, local: &'gcx hir::Local) { let o_ty = match local.ty { - Some(ref ty) => Some(self.fcx.to_ty(&ty)), - None => None + Some(ref ty) => { + let o_ty = self.fcx.to_ty(&ty); + + let (c_ty, _orig_values) = self.fcx.inh.infcx.canonicalize_response(&o_ty); + debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); + self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty); + + Some(o_ty) + }, + None => None, }; self.assign(local.span, local.id, o_ty); + debug!("Local variable {:?} is assigned type {}", local.pat, self.fcx.ty_to_string( @@ -1027,8 +1050,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let span = body.value.span; if body.is_generator && can_be_generator.is_some() { - let yield_ty = fcx.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(span)); + let yield_ty = fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType); fcx.yield_ty = Some(yield_ty); } @@ -1061,8 +1083,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // This ensures that all nested generators appear before the entry of this generator. // resolve_generator_interiors relies on this property. let gen_ty = if can_be_generator.is_some() && body.is_generator { - let witness = fcx.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(span)); + let witness = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span)); let interior = ty::GeneratorInterior { witness, movable: can_be_generator.unwrap() == hir::GeneratorMovability::Movable, @@ -1100,30 +1121,27 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let mut actual_return_ty = coercion.complete(&fcx); if actual_return_ty.is_never() { actual_return_ty = fcx.next_diverging_ty_var( - ty::UniverseIndex::ROOT, TypeVariableOrigin::DivergingFn(span)); } fcx.demand_suptype(span, ret_ty, actual_return_ty); - if fcx.tcx.features().termination_trait { - // If the termination trait language item is activated, check that the main return type - // implements the termination trait. - if let Some(term_id) = fcx.tcx.lang_items().termination() { - if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() { - if id == fn_id { - match fcx.sess().entry_type.get() { - Some(config::EntryMain) => { - let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); - let trait_ref = ty::TraitRef::new(term_id, substs); - let cause = traits::ObligationCause::new( - span, fn_id, ObligationCauseCode::MainFunctionType); + // Check that the main return type implements the termination trait. + if let Some(term_id) = fcx.tcx.lang_items().termination() { + if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() { + if id == fn_id { + match fcx.sess().entry_type.get() { + Some(config::EntryMain) => { + let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); + let trait_ref = ty::TraitRef::new(term_id, substs); + let return_ty_span = decl.output.span(); + let cause = traits::ObligationCause::new( + return_ty_span, fn_id, ObligationCauseCode::MainFunctionType); - inherited.register_predicate( - traits::Obligation::new( - cause, param_env, trait_ref.to_predicate())); - }, - _ => {}, - } + inherited.register_predicate( + traits::Obligation::new( + cause, param_env, trait_ref.to_predicate())); + }, + _ => {}, } } } @@ -1166,9 +1184,15 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item let _indenter = indenter(); match it.node { // Consts can play a role in type-checking, so they are included here. - hir::ItemStatic(..) | + hir::ItemStatic(..) => { + tcx.typeck_tables_of(tcx.hir.local_def_id(it.id)); + } hir::ItemConst(..) => { tcx.typeck_tables_of(tcx.hir.local_def_id(it.id)); + if it.attrs.iter().any(|a| a.check_name("wasm_custom_section")) { + let def_id = tcx.hir.local_def_id(it.id); + check_const_is_u8_array(tcx, def_id, it.span); + } } hir::ItemEnum(ref enum_definition, _) => { check_enum(tcx, @@ -1222,9 +1246,11 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item if !generics.types.is_empty() { let mut err = struct_span_err!(tcx.sess, item.span, E0044, "foreign items may not have type parameters"); - span_help!(&mut err, item.span, - "consider using specialization instead of \ - type parameters"); + err.span_label(item.span, "can't have type parameters"); + // FIXME: once we start storing spans for type arguments, turn this into a + // suggestion. + err.help("use specialization instead of type parameters by replacing them \ + with concrete types like `u32`"); err.emit(); } @@ -1238,6 +1264,21 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item } } +fn check_const_is_u8_array<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + span: Span) { + match tcx.type_of(def_id).sty { + ty::TyArray(t, _) => { + match t.sty { + ty::TyUint(ast::UintTy::U8) => return, + _ => {} + } + } + _ => {} + } + tcx.sess.span_err(span, "must be an array of bytes like `[u8; N]`"); +} + fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, item: &hir::Item) { @@ -1692,14 +1733,13 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { } fn ty_infer(&self, span: Span) -> Ty<'tcx> { - self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(span)) + self.next_ty_var(TypeVariableOrigin::TypeInference(span)) } fn ty_infer_for_def(&self, ty_param_def: &ty::TypeParameterDef, span: Span) -> Ty<'tcx> { - self.type_var_for_def(ty::UniverseIndex::ROOT, span, ty_param_def) + self.type_var_for_def(span, ty_param_def) } fn projected_ty_from_poly_trait_ref(&self, @@ -1837,7 +1877,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // possible. This can help substantially when there are // indirect dependencies that don't seem worth tracking // precisely. - self.select_obligations_where_possible(); + self.select_obligations_where_possible(false); ty = self.resolve_type_vars_if_possible(&ty); debug!("resolve_type_vars_with_obligations: ty={:?}", ty); @@ -2154,18 +2194,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn resolve_generator_interiors(&self, def_id: DefId) { let mut generators = self.deferred_generator_interiors.borrow_mut(); for (body_id, interior) in generators.drain(..) { - self.select_obligations_where_possible(); + self.select_obligations_where_possible(false); generator_interior::resolve_interior(self, def_id, body_id, interior); } } // Tries to apply a fallback to `ty` if it is an unsolved variable. - // Non-numerics get replaced with ! or () (depending on whether - // feature(never_type) is enabled), unconstrained ints with i32, + // Non-numerics get replaced with !, unconstrained ints with i32, // unconstrained floats with f64. // Fallback becomes very dubious if we have encountered type-checking errors. // In that case, fallback to TyError. - fn fallback_if_possible(&self, ty: Ty<'tcx>) { + // The return value indicates whether fallback has occured. + fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; @@ -2174,25 +2214,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ if self.is_tainted_by_errors() => self.tcx().types.err, UnconstrainedInt => self.tcx.types.i32, UnconstrainedFloat => self.tcx.types.f64, - Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(), - Neither => return + Neither if self.type_var_diverges(ty) => self.tcx.types.never, + Neither => return false, }; debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback); self.demand_eqtype(syntax_pos::DUMMY_SP, ty, fallback); + true } fn select_all_obligations_or_error(&self) { debug!("select_all_obligations_or_error"); if let Err(errors) = self.fulfillment_cx.borrow_mut().select_all_or_error(&self) { - self.report_fulfillment_errors(&errors, self.inh.body_id); + self.report_fulfillment_errors(&errors, self.inh.body_id, false); } } /// Select as many obligations as we can at present. - fn select_obligations_where_possible(&self) { + fn select_obligations_where_possible(&self, fallback_has_occurred: bool) { match self.fulfillment_cx.borrow_mut().select_where_possible(self) { Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } + Err(errors) => { + self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred); + }, } } @@ -2321,8 +2364,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If some lookup succeeds, write callee into table and extract index/element // type from the method signature. // If some lookup succeeded, install method in table - let input_ty = self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::AutoDeref(base_expr.span)); + let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span)); let method = self.try_overloaded_place_op( expr.span, self_ty, &[input_ty], needs, PlaceOp::Index); @@ -2335,12 +2377,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mutbl = match mt.mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { - // FIXME (#46747): arguably indexing is - // "just another kind of call"; perhaps it - // would be more consistent to allow - // two-phase borrows for .index() - // receivers here. - allow_two_phase_borrow: false, + // Indexing can be desugared to a method call, + // so maybe we could use two-phase here. + // See the documentation of AllowTwoPhase for why that's + // not the case today. + allow_two_phase_borrow: AllowTwoPhase::No, } }; adjustments.push(Adjustment { @@ -2438,7 +2479,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)], + TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])], }; self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr, @@ -2514,7 +2555,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if sugg_unit { let sugg_span = sess.codemap().end_point(expr_sp); // remove closing `)` from the span - let sugg_span = sugg_span.with_hi(sugg_span.lo()); + let sugg_span = sugg_span.shrink_to_lo(); err.span_suggestion( sugg_span, "expected the unit value `()`; create it with empty parentheses", @@ -2531,16 +2572,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let formal_tys = if tuple_arguments == TupleArguments { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { - ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { + ty::TyTuple(arg_types) if arg_types.len() != args.len() => { parameter_count_error(tcx.sess, sp, expr_sp, arg_types.len(), args.len(), "E0057", false, def_span, false); expected_arg_tys = &[]; self.err_args(args.len()) } - ty::TyTuple(arg_types, _) => { + ty::TyTuple(arg_types) => { expected_arg_tys = match expected_arg_tys.get(0) { Some(&ty) => match ty.sty { - ty::TyTuple(ref tys, _) => &tys, + ty::TyTuple(ref tys) => &tys, _ => &[] }, None => &[] @@ -2596,7 +2637,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // an "opportunistic" vtable resolution of any trait bounds on // the call. This helps coercions. if check_closures { - self.select_obligations_where_possible(); + self.select_obligations_where_possible(false); } // For variadic functions, we don't have a declared type for all of @@ -2643,7 +2684,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // to, which is `expected_ty` if `rvalue_hint` returns an // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. let coerce_ty = expected.and_then(|e| e.only_has_type(self)); - self.demand_coerce(&arg, checked_ty, coerce_ty.unwrap_or(formal_ty)); + // We're processing function arguments so we definitely want to use + // two-phase borrows. + self.demand_coerce(&arg, + checked_ty, + coerce_ty.unwrap_or(formal_ty), + AllowTwoPhase::Yes); // 3. Relate the expected type and the formal one, // if the expected type was used for the coercion. @@ -2761,7 +2807,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id), "expression with never type wound up being adjusted"); let adj_ty = self.next_diverging_ty_var( - ty::UniverseIndex::ROOT, TypeVariableOrigin::AdjustmentType(expr.span)); self.apply_adjustments(expr, vec![Adjustment { kind: Adjust::NeverToAny, @@ -2806,7 +2851,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr, ExpectHasType(expected), needs); - self.demand_coerce(expr, ty, expected) + // checks don't need two phase + self.demand_coerce(expr, ty, expected, AllowTwoPhase::No) } fn check_expr_with_hint(&self, expr: &'gcx hir::Expr, @@ -2839,7 +2885,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ity = self.tcx.type_of(did); debug!("impl_self_ty: ity={:?}", ity); - let substs = self.fresh_substs_for_item(ty::UniverseIndex::ROOT, span, did); + let substs = self.fresh_substs_for_item(span, did); let substd_ty = self.instantiate_type_scheme(span, &substs, &ity); TypeAndSubsts { substs: substs, ty: substd_ty } @@ -2861,9 +2907,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // is polymorphic) and the expected return type. // No argument expectations are produced if unification fails. let origin = self.misc(call_span); - let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret); + let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret); - // FIXME(#15760) can't use try! here, FromError doesn't default + // FIXME(#27336) can't use ? here, Try::from_error doesn't default // to identity so the resulting type is not constrained. match ures { Ok(ok) => { @@ -2871,19 +2917,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // we can. We don't care if some things turn // out unconstrained or ambiguous, as we're // just trying to get hints here. - let result = self.save_and_restore_in_snapshot_flag(|_| { - let mut fulfill = FulfillmentContext::new(); - let ok = ok; // FIXME(#30046) + self.save_and_restore_in_snapshot_flag(|_| { + let mut fulfill = TraitEngine::new(self.tcx); for obligation in ok.obligations { fulfill.register_predicate_obligation(self, obligation); } fulfill.select_where_possible(self) - }); - - match result { - Ok(()) => { } - Err(_) => return Err(()), - } + }).map_err(|_| ())?; } Err(_) => return Err(()), } @@ -3042,7 +3082,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.apply_adjustments(base, adjustments); autoderef.finalize(); - self.tcx.check_stability(field.did, expr.id, expr.span); + self.tcx.check_stability(field.did, Some(expr.id), expr.span); return field_ty; } @@ -3096,10 +3136,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; } ty::TyRawPtr(..) => { - err.note(&format!("`{0}` is a native pointer; perhaps you need to deref \ - with `(*{0}).{1}`", - self.tcx.hir.node_to_pretty_string(base.id), - field.node)); + let base = self.tcx.hir.node_to_pretty_string(base.id); + let msg = format!("`{}` is a native pointer; try dereferencing it", base); + let suggestion = format!("(*{}).{}", base, field.node); + err.span_suggestion(field.span, &msg, suggestion); } _ => {} } @@ -3183,7 +3223,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) { let field_ty = self.field_ty(expr.span, field, substs); if field.vis.is_accessible_from(def_scope, self.tcx) { - self.tcx.check_stability(field.did, expr.id, expr.span); + self.tcx.check_stability(field.did, Some(expr.id), expr.span); Some(field_ty) } else { private_candidate = Some((base_def.did, field_ty)); @@ -3193,7 +3233,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } } - ty::TyTuple(ref v, _) => { + ty::TyTuple(ref v) => { tuple_like = true; v.get(idx.node).cloned() } @@ -3328,7 +3368,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // struct-like enums (yet...), but it's definitely not // a bug to have construct one. if adt_kind != ty::AdtKind::Enum { - tcx.check_stability(v_field.did, expr_id, field.span); + tcx.check_stability(v_field.did, Some(expr_id), field.span); } self.field_ty(field.span, v_field, substs) @@ -3639,7 +3679,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // (It shouldn't actually matter for unary ops whether // we enable two-phase borrows or not, since a unary // op has no additional operands.) - allow_two_phase_borrow: false, + allow_two_phase_borrow: AllowTwoPhase::No, } }; self.apply_adjustments(oprnd, vec![Adjustment { @@ -3945,7 +3985,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let t_cast = self.resolve_type_vars_if_possible(&t_cast); let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast)); let t_cast = self.resolve_type_vars_if_possible(&t_cast); - let diverges = self.diverges.get(); // Eagerly check for some obvious errors. if t_expr.references_error() || t_cast.references_error() { @@ -3953,7 +3992,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { // Defer other checks until we're done type checking. let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); - match cast::CastCheck::new(self, e, t_expr, diverges, t_cast, t.span, expr.span) { + match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { Ok(cast_check) => { deferred_cast_checks.push(cast_check); t_cast @@ -3979,8 +4018,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let element_ty = if !args.is_empty() { let coerce_to = uty.unwrap_or_else( - || self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(expr.span))); + || self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span))); let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args); assert_eq!(self.diverges.get(), Diverges::Maybe); for e in args { @@ -3990,14 +4028,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } coerce.complete(self) } else { - self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::TypeInference(expr.span)) + self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span)) }; tcx.mk_array(element_ty, args.len() as u64) } hir::ExprRepeat(ref element, count) => { let count_def_id = tcx.hir.body_owner_def_id(count); - let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing); + let param_env = ty::ParamEnv::empty(); let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); let instance = ty::Instance::resolve( tcx.global_tcx(), @@ -4031,8 +4068,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (uty, uty) } None => { - let t: Ty = self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(element.span)); + let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span)); let element_ty = self.check_expr_has_type_or_error(&element, t); (element_ty, t) } @@ -4060,7 +4096,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let flds = expected.only_has_type(self).and_then(|ty| { let ty = self.resolve_type_vars_with_obligations(ty); match ty.sty { - ty::TyTuple(ref flds, _) => Some(&flds[..]), + ty::TyTuple(ref flds) => Some(&flds[..]), _ => None } }); @@ -4078,7 +4114,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; t }); - let tuple = tcx.mk_tup(elt_ts_iter, false); + let tuple = tcx.mk_tup(elt_ts_iter); if tuple.references_error() { tcx.types.err } else { @@ -4107,7 +4143,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let base_t = self.structurally_resolved_type(expr.span, base_t); match self.lookup_indexing(expr, base, base_t, idx_t, needs) { Some((index_ty, element_ty)) => { - self.demand_coerce(idx, idx_t, index_ty); + // two-phase not needed because index_ty is never mutable + self.demand_coerce(idx, idx_t, index_ty, AllowTwoPhase::No); element_ty } None => { @@ -4772,9 +4809,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - self.check_path_parameter_count(span, &mut type_segment, false); - self.check_path_parameter_count(span, &mut fn_segment, false); - self.check_impl_trait(span, &mut fn_segment); + let supress_mismatch = self.check_impl_trait(span, &mut fn_segment); + self.check_path_parameter_count(span, &mut type_segment, false, supress_mismatch); + self.check_path_parameter_count(span, &mut fn_segment, false, supress_mismatch); let (fn_start, has_self) = match (type_segment, fn_segment) { (_, Some((_, generics))) => { @@ -4811,7 +4848,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Handle Self first, so we can adjust the index to match the AST. if has_self && i == 0 { return opt_self_ty.unwrap_or_else(|| { - self.type_var_for_def(ty::UniverseIndex::ROOT, span, def) + self.type_var_for_def(span, def) }); } i -= has_self as usize; @@ -4844,7 +4881,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This can also be reached in some error cases: // We prefer to use inference variables instead of // TyError to let type inference recover somewhat. - self.type_var_for_def(ty::UniverseIndex::ROOT, span, def) + self.type_var_for_def(span, def) } }); @@ -4927,7 +4964,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_path_parameter_count(&self, span: Span, segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, - is_method_call: bool) { + is_method_call: bool, + supress_mismatch_error: bool) { let (lifetimes, types, infer_types, bindings) = segment.map_or( (&[][..], &[][..], true, &[][..]), |(s, _)| s.parameters.as_ref().map_or( @@ -4967,7 +5005,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters, we force instantiate_value_path to // use inference variables instead of the provided types. *segment = None; - } else if types.len() < required_len && !infer_types { + } else if types.len() < required_len && !infer_types && !supress_mismatch_error { let expected_text = count_type_params(required_len); let actual_text = count_type_params(types.len()); struct_span_err!(self.tcx.sess, span, E0089, @@ -5034,10 +5072,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Report error if there is an explicit type parameter when using `impl Trait`. fn check_impl_trait(&self, span: Span, - segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) + -> bool { use hir::SyntheticTyParamKind::*; - segment.map(|(path_segment, generics)| { + let segment = segment.map(|(path_segment, generics)| { let explicit = !path_segment.infer_types; let impl_trait = generics.types.iter() .any(|ty_param| { @@ -5058,7 +5097,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.emit(); } + + impl_trait }); + + segment.unwrap_or(false) } // Resolves `typ` by a single level if `typ` is a type variable. diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 47a229cbd3b5..efc1e2a80ceb 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -14,7 +14,7 @@ use super::{FnCtxt, Needs}; use super::method::MethodCallee; use rustc::ty::{self, Ty, TypeFoldable, TypeVariants}; use rustc::ty::TypeVariants::{TyStr, TyRef, TyAdt}; -use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::infer::type_variable::TypeVariableOrigin; use errors; use syntax_pos::Span; @@ -174,10 +174,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // trait matching creating lifetime constraints that are too strict. // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. - let lhs_ty = self.check_expr_coercable_to_type_with_needs( - lhs_expr, - self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(lhs_expr.span)), + let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr, + self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)), lhs_needs); let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); @@ -187,8 +185,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // using this variable as the expected type, which sometimes lets // us do better coercions than we would be able to do otherwise, // particularly for things like `String + &String`. - let rhs_ty_var = self.next_ty_var(ty::UniverseIndex::ROOT, - TypeVariableOrigin::MiscVariable(rhs_expr.span)); + let rhs_ty_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(rhs_expr.span)); let result = self.lookup_op_method(lhs_ty, &[rhs_ty_var], Op::Binary(op, is_assign)); @@ -206,7 +203,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::MutMutable => AutoBorrowMutability::Mutable { // Allow two-phase borrows for binops in initial deployment // since they desugar to methods - allow_two_phase_borrow: true, + allow_two_phase_borrow: AllowTwoPhase::Yes, } }; let autoref = Adjustment { @@ -223,7 +220,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::MutMutable => AutoBorrowMutability::Mutable { // Allow two-phase borrows for binops in initial deployment // since they desugar to methods - allow_two_phase_borrow: true, + allow_two_phase_borrow: AllowTwoPhase::Yes, } }; let autoref = Adjustment { @@ -479,7 +476,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match method { Some(ok) => { let method = self.register_infer_ok_obligations(ok); - self.select_obligations_where_possible(); + self.select_obligations_where_possible(false); Ok(method) } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index cfe8aa99bfa0..b5e862fac958 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -411,8 +411,9 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.type_of_node_must_outlive(origin, hir_id, var_region); let typ = self.resolve_node_type(hir_id); + let body_id = self.body_id; let _ = dropck::check_safety_of_destructor_if_necessary( - self, typ, span, var_scope); + self, typ, span, body_id, var_scope); }) } } @@ -884,8 +885,9 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { match *region { ty::ReScope(rvalue_scope) => { let typ = self.resolve_type(cmt.ty); + let body_id = self.body_id; let _ = dropck::check_safety_of_destructor_if_necessary( - self, typ, span, rvalue_scope); + self, typ, span, body_id, rvalue_scope); } ty::ReStatic => {} _ => { @@ -1162,10 +1164,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// constraint that `'z <= 'a`. Given this setup, let's clarify the /// parameters in (roughly) terms of the example: /// + /// ```plain,ignore (pseudo-Rust) /// A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T` /// borrow_region ^~ ref_region ^~ /// borrow_kind ^~ ref_kind ^~ /// ref_cmt ^ + /// ``` /// /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc). /// diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index ab148afafbe0..4fc3344dab2a 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .upvar_tys(closure_def_id, self.tcx) .zip(final_upvar_tys) { - self.demand_eqtype(span, final_upvar_ty, upvar_ty); + self.demand_suptype(span, upvar_ty, final_upvar_ty); } // If we are also inferred the closure kind here, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index d10ee358e072..406ff9463a03 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -26,17 +26,11 @@ use errors::{DiagnosticBuilder, DiagnosticId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; -pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - code: ObligationCauseCode<'tcx>, -} - /// Helper type of a temporary returned by .for_item(...). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>). struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, - code: ObligationCauseCode<'gcx>, id: ast::NodeId, span: Span, param_env: ty::ParamEnv<'tcx>, @@ -45,585 +39,597 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { fn with_fcx(&'tcx mut self, f: F) where F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, - &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec> + TyCtxt<'b, 'gcx, 'gcx>) -> Vec> { - let code = self.code.clone(); let id = self.id; let span = self.span; let param_env = self.param_env; self.inherited.enter(|inh| { let fcx = FnCtxt::new(&inh, param_env, id); - let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { - tcx: fcx.tcx.global_tcx(), - code, - }); + let wf_tys = f(&fcx, fcx.tcx.global_tcx()); fcx.select_all_obligations_or_error(); fcx.regionck_item(id, span, &wf_tys); }); } } -impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) - -> CheckTypeWellFormedVisitor<'a, 'gcx> { - CheckTypeWellFormedVisitor { - tcx, - code: ObligationCauseCode::MiscObligation - } - } +/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are +/// well-formed, meaning that they do not require any constraints not declared in the struct +/// definition itself. For example, this definition would be illegal: +/// +/// struct Ref<'a, T> { x: &'a T } +/// +/// because the type did not declare that `T:'a`. +/// +/// We do this check as a pre-pass before checking fn bodies because if these constraints are +/// not included it frequently leads to confusing errors in fn bodies. So it's better to check +/// the types first. +pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item = tcx.hir.expect_item(node_id); - /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are - /// well-formed, meaning that they do not require any constraints not declared in the struct - /// definition itself. For example, this definition would be illegal: - /// - /// struct Ref<'a, T> { x: &'a T } - /// - /// because the type did not declare that `T:'a`. - /// - /// We do this check as a pre-pass before checking fn bodies because if these constraints are - /// not included it frequently leads to confusing errors in fn bodies. So it's better to check - /// the types first. - fn check_item_well_formed(&mut self, item: &hir::Item) { - let tcx = self.tcx; - debug!("check_item_well_formed(it.id={}, it.name={})", - item.id, - tcx.item_path_str(tcx.hir.local_def_id(item.id))); + debug!("check_item_well_formed(it.id={}, it.name={})", + item.id, + tcx.item_path_str(def_id)); - match item.node { - // Right now we check that every default trait implementation - // has an implementation of itself. Basically, a case like: - // - // `impl Trait for T {}` - // - // has a requirement of `T: Trait` which was required for default - // method implementations. Although this could be improved now that - // there's a better infrastructure in place for this, it's being left - // for a follow-up work. - // - // Since there's such a requirement, we need to check *just* positive - // implementations, otherwise things like: - // - // impl !Send for T {} - // - // won't be allowed unless there's an *explicit* implementation of `Send` - // for `T` - hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { - let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)) - .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); - if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { - tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); - } - if polarity == hir::ImplPolarity::Positive { - self.check_impl(item, self_ty, trait_ref); - } else { - // FIXME(#27579) what amount of WF checking do we need for neg impls? - if trait_ref.is_some() && !is_auto { - span_err!(tcx.sess, item.span, E0192, - "negative impls are only allowed for \ - auto traits (e.g., `Send` and `Sync`)") - } + match item.node { + // Right now we check that every default trait implementation + // has an implementation of itself. Basically, a case like: + // + // `impl Trait for T {}` + // + // has a requirement of `T: Trait` which was required for default + // method implementations. Although this could be improved now that + // there's a better infrastructure in place for this, it's being left + // for a follow-up work. + // + // Since there's such a requirement, we need to check *just* positive + // implementations, otherwise things like: + // + // impl !Send for T {} + // + // won't be allowed unless there's an *explicit* implementation of `Send` + // for `T` + hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { + let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)) + .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { + tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); + } + if polarity == hir::ImplPolarity::Positive { + check_impl(tcx, item, self_ty, trait_ref); + } else { + // FIXME(#27579) what amount of WF checking do we need for neg impls? + if trait_ref.is_some() && !is_auto { + span_err!(tcx.sess, item.span, E0192, + "negative impls are only allowed for \ + auto traits (e.g., `Send` and `Sync`)") } } - hir::ItemFn(..) => { - self.check_item_fn(item); - } - hir::ItemStatic(..) => { - self.check_item_type(item); - } - hir::ItemConst(..) => { - self.check_item_type(item); - } - hir::ItemStruct(ref struct_def, ref ast_generics) => { - self.check_type_defn(item, false, |fcx| { - vec![fcx.non_enum_variant(struct_def)] - }); - - self.check_variances_for_type_defn(item, ast_generics); - } - hir::ItemUnion(ref struct_def, ref ast_generics) => { - self.check_type_defn(item, true, |fcx| { - vec![fcx.non_enum_variant(struct_def)] - }); - - self.check_variances_for_type_defn(item, ast_generics); - } - hir::ItemEnum(ref enum_def, ref ast_generics) => { - self.check_type_defn(item, true, |fcx| { - fcx.enum_variants(enum_def) - }); - - self.check_variances_for_type_defn(item, ast_generics); - } - hir::ItemTrait(..) => { - self.check_trait(item); - } - _ => {} } + hir::ItemFn(..) => { + check_item_fn(tcx, item); + } + hir::ItemStatic(..) => { + check_item_type(tcx, item); + } + hir::ItemConst(..) => { + check_item_type(tcx, item); + } + hir::ItemStruct(ref struct_def, ref ast_generics) => { + check_type_defn(tcx, item, false, |fcx| { + vec![fcx.non_enum_variant(struct_def)] + }); + + check_variances_for_type_defn(tcx, item, ast_generics); + } + hir::ItemUnion(ref struct_def, ref ast_generics) => { + check_type_defn(tcx, item, true, |fcx| { + vec![fcx.non_enum_variant(struct_def)] + }); + + check_variances_for_type_defn(tcx, item, ast_generics); + } + hir::ItemEnum(ref enum_def, ref ast_generics) => { + check_type_defn(tcx, item, true, |fcx| { + fcx.enum_variants(enum_def) + }); + + check_variances_for_type_defn(tcx, item, ast_generics); + } + hir::ItemTrait(..) => { + check_trait(tcx, item); + } + _ => {} } +} - fn check_associated_item(&mut self, - item_id: ast::NodeId, - span: Span, - sig_if_method: Option<&hir::MethodSig>) { - let code = self.code.clone(); - self.for_id(item_id, span).with_fcx(|fcx, this| { - let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); +pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let trait_item = tcx.hir.expect_trait_item(node_id); - let (mut implied_bounds, self_ty) = match item.container { - ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), - ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), - fcx.tcx.type_of(def_id)) - }; + let method_sig = match trait_item.node { + hir::TraitItemKind::Method(ref sig, _) => Some(sig), + _ => None + }; + check_associated_item(tcx, trait_item.id, trait_item.span, method_sig); +} - match item.kind { - ty::AssociatedKind::Const => { +pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let impl_item = tcx.hir.expect_impl_item(node_id); + + let method_sig = match impl_item.node { + hir::ImplItemKind::Method(ref sig, _) => Some(sig), + _ => None + }; + check_associated_item(tcx, impl_item.id, impl_item.span, method_sig); +} + +fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + span: Span, + sig_if_method: Option<&hir::MethodSig>) { + let code = ObligationCauseCode::MiscObligation; + for_id(tcx, item_id, span).with_fcx(|fcx, tcx| { + let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id)); + + let (mut implied_bounds, self_ty) = match item.container { + ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), + ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), + fcx.tcx.type_of(def_id)) + }; + + match item.kind { + ty::AssociatedKind::Const => { + let ty = fcx.tcx.type_of(item.def_id); + let ty = fcx.normalize_associated_types_in(span, &ty); + fcx.register_wf_obligation(ty, span, code.clone()); + } + ty::AssociatedKind::Method => { + reject_shadowing_type_parameters(fcx.tcx, item.def_id); + let sig = fcx.tcx.fn_sig(item.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + check_fn_or_method(tcx, fcx, span, sig, + item.def_id, &mut implied_bounds); + let sig_if_method = sig_if_method.expect("bad signature for method"); + check_method_receiver(fcx, sig_if_method, &item, self_ty); + } + ty::AssociatedKind::Type => { + if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.normalize_associated_types_in(span, &ty); fcx.register_wf_obligation(ty, span, code.clone()); } - ty::AssociatedKind::Method => { - reject_shadowing_type_parameters(fcx.tcx, item.def_id); - let sig = fcx.tcx.fn_sig(item.def_id); - let sig = fcx.normalize_associated_types_in(span, &sig); - this.check_fn_or_method(fcx, span, sig, - item.def_id, &mut implied_bounds); - let sig_if_method = sig_if_method.expect("bad signature for method"); - this.check_method_receiver(fcx, sig_if_method, &item, self_ty); - } - ty::AssociatedKind::Type => { - if item.defaultness.has_value() { - let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in(span, &ty); - fcx.register_wf_obligation(ty, span, code.clone()); - } - } } + } - implied_bounds - }) - } + implied_bounds + }) +} - fn for_item<'tcx>(&self, item: &hir::Item) - -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { - self.for_id(item.id, item.span) - } - - fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) +fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { - let def_id = self.tcx.hir.local_def_id(id); - CheckWfFcxBuilder { - inherited: Inherited::build(self.tcx, def_id), - code: self.code.clone(), - id, - span, - param_env: self.tcx.param_env(def_id), - } + for_id(tcx, item.id, item.span) +} + +fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span) + -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { + let def_id = tcx.hir.local_def_id(id); + CheckWfFcxBuilder { + inherited: Inherited::build(tcx, def_id), + id, + span, + param_env: tcx.param_env(def_id), } +} - /// In a type definition, we check that to ensure that the types of the fields are well-formed. - fn check_type_defn(&mut self, item: &hir::Item, all_sized: bool, mut lookup_fields: F) - where F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) -> Vec> - { - self.for_item(item).with_fcx(|fcx, this| { - let variants = lookup_fields(fcx); - let def_id = fcx.tcx.hir.local_def_id(item.id); - let packed = fcx.tcx.adt_def(def_id).repr.packed(); +/// In a type definition, we check that to ensure that the types of the fields are well-formed. +fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, all_sized: bool, mut lookup_fields: F) + where F: for<'fcx, 'gcx, 'tcx2> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx2>) -> Vec> +{ + for_item(tcx, item).with_fcx(|fcx, fcx_tcx| { + let variants = lookup_fields(fcx); + let def_id = fcx.tcx.hir.local_def_id(item.id); + let packed = fcx.tcx.adt_def(def_id).repr.packed(); - for variant in &variants { - // For DST, or when drop needs to copy things around, all - // intermediate types must be sized. - let needs_drop_copy = || { - packed && { - let ty = variant.fields.last().unwrap().ty; - let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(this.tcx) - .unwrap_or_else(|| { - span_bug!(item.span, "inference variables in {:?}", ty) - }); - ty.needs_drop(this.tcx, this.tcx.param_env(def_id)) - } - }; - let unsized_len = if - all_sized || - variant.fields.is_empty() || - needs_drop_copy() - { - 0 - } else { - 1 - }; - for field in &variant.fields[..variant.fields.len() - unsized_len] { - fcx.register_bound( - field.ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new(field.span, - fcx.body_id, - traits::FieldSized(match item.node.adt_kind() { - Some(i) => i, - None => bug!(), - }))); + for variant in &variants { + // For DST, or when drop needs to copy things around, all + // intermediate types must be sized. + let needs_drop_copy = || { + packed && { + let ty = variant.fields.last().unwrap().ty; + let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) + .unwrap_or_else(|| { + span_bug!(item.span, "inference variables in {:?}", ty) + }); + ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) } - - // All field types must be well-formed. - for field in &variant.fields { - fcx.register_wf_obligation(field.ty, field.span, this.code.clone()) - } - } - - self.check_where_clauses(fcx, item.span, def_id); - - vec![] // no implied bounds in a struct def'n - }); - } - - fn check_trait(&mut self, item: &hir::Item) { - let trait_def_id = self.tcx.hir.local_def_id(item.id); - self.for_item(item).with_fcx(|fcx, _| { - self.check_where_clauses(fcx, item.span, trait_def_id); - vec![] - }); - } - - fn check_item_fn(&mut self, item: &hir::Item) { - self.for_item(item).with_fcx(|fcx, this| { - let def_id = fcx.tcx.hir.local_def_id(item.id); - let sig = fcx.tcx.fn_sig(def_id); - let sig = fcx.normalize_associated_types_in(item.span, &sig); - let mut implied_bounds = vec![]; - this.check_fn_or_method(fcx, item.span, sig, - def_id, &mut implied_bounds); - implied_bounds - }) - } - - fn check_item_type(&mut self, - item: &hir::Item) - { - debug!("check_item_type: {:?}", item); - - self.for_item(item).with_fcx(|fcx, this| { - let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id)); - let item_ty = fcx.normalize_associated_types_in(item.span, &ty); - - fcx.register_wf_obligation(item_ty, item.span, this.code.clone()); - - vec![] // no implied bounds in a const etc - }); - } - - fn check_impl(&mut self, - item: &hir::Item, - ast_self_ty: &hir::Ty, - ast_trait_ref: &Option) - { - debug!("check_impl: {:?}", item); - - self.for_item(item).with_fcx(|fcx, this| { - let item_def_id = fcx.tcx.hir.local_def_id(item.id); - - match *ast_trait_ref { - Some(ref ast_trait_ref) => { - let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); - for obligation in obligations { - fcx.register_predicate(obligation); - } - } - None => { - let self_ty = fcx.tcx.type_of(item_def_id); - let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty); - fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone()); - } - } - - this.check_where_clauses(fcx, item.span, item_def_id); - - fcx.impl_implied_bounds(item_def_id, item.span) - }); - } - - /// Checks where clauses and inline bounds that are declared on def_id. - fn check_where_clauses<'fcx, 'tcx>(&mut self, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - span: Span, - def_id: DefId) { - use ty::subst::Subst; - use rustc::ty::TypeFoldable; - - let mut predicates = fcx.tcx.predicates_of(def_id); - let mut substituted_predicates = Vec::new(); - - let generics = self.tcx.generics_of(def_id); - let is_our_default = |def: &ty::TypeParameterDef| - def.has_default && def.index >= generics.parent_count() as u32; - - // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. - // For example this forbids the declaration: - // struct Foo> { .. } - // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. - for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) { - let ty = fcx.tcx.type_of(d); - // ignore dependent defaults -- that is, where the default of one type - // parameter includes another (e.g., ). In those cases, we can't - // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { - fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone()); - } - } - - // Check that trait predicates are WF when params are substituted by their defaults. - // We don't want to overly constrain the predicates that may be written but we want to - // catch cases where a default my never be applied such as `struct Foo`. - // Therefore we check if a predicate which contains a single type param - // with a concrete default is WF with that default substituted. - // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. - // - // First we build the defaulted substitution. - let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| { - // All regions are identity. - fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data())) - }, |def, _| { - // If the param has a default, - if is_our_default(def) { - let default_ty = fcx.tcx.type_of(def.def_id); - // and it's not a dependent default - if !default_ty.needs_subst() { - // then substitute with the default. - return default_ty; - } - } - // Mark unwanted params as err. - fcx.tcx.types.err - }); - // Now we build the substituted predicates. - for &pred in predicates.predicates.iter() { - struct CountParams { params: FxHashSet } - impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - match t.sty { - ty::TyParam(p) => { - self.params.insert(p.idx); - t.super_visit_with(self) - } - _ => t.super_visit_with(self) - } - } - } - let mut param_count = CountParams { params: FxHashSet() }; - pred.visit_with(&mut param_count); - let substituted_pred = pred.subst(fcx.tcx, substs); - // Don't check non-defaulted params, dependent defaults or preds with multiple params. - if substituted_pred.references_error() || param_count.params.len() > 1 { - continue; - } - // Avoid duplication of predicates that contain no parameters, for example. - if !predicates.predicates.contains(&substituted_pred) { - substituted_predicates.push(substituted_pred); - } - } - - predicates.predicates.extend(substituted_predicates); - let predicates = predicates.instantiate_identity(fcx.tcx); - let predicates = fcx.normalize_associated_types_in(span, &predicates); - - let obligations = - predicates.predicates - .iter() - .flat_map(|p| ty::wf::predicate_obligations(fcx, - fcx.param_env, - fcx.body_id, - p, - span)); - - for obligation in obligations { - fcx.register_predicate(obligation); - } - } - - fn check_fn_or_method<'fcx, 'tcx>(&mut self, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - span: Span, - sig: ty::PolyFnSig<'tcx>, - def_id: DefId, - implied_bounds: &mut Vec>) - { - let sig = fcx.normalize_associated_types_in(span, &sig); - let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); - - for input_ty in sig.inputs() { - fcx.register_wf_obligation(&input_ty, span, self.code.clone()); - } - implied_bounds.extend(sig.inputs()); - - fcx.register_wf_obligation(sig.output(), span, self.code.clone()); - - // FIXME(#25759) return types should not be implied bounds - implied_bounds.push(sig.output()); - - self.check_where_clauses(fcx, span, def_id); - } - - fn check_method_receiver<'fcx, 'tcx>(&mut self, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - method_sig: &hir::MethodSig, - method: &ty::AssociatedItem, - self_ty: Ty<'tcx>) - { - // check that the method has a valid receiver type, given the type `Self` - debug!("check_method_receiver({:?}, self_ty={:?})", - method, self_ty); - - if !method.method_has_self_argument { - return; - } - - let span = method_sig.decl.inputs[0].span; - - let sig = fcx.tcx.fn_sig(method.def_id); - let sig = fcx.normalize_associated_types_in(span, &sig); - let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig); - - debug!("check_method_receiver: sig={:?}", sig); - - let self_ty = fcx.normalize_associated_types_in(span, &self_ty); - let self_ty = fcx.tcx.liberate_late_bound_regions( - method.def_id, - &ty::Binder(self_ty) - ); - - let self_arg_ty = sig.inputs()[0]; - - let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); - let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); - let self_arg_ty = fcx.tcx.liberate_late_bound_regions( - method.def_id, - &ty::Binder(self_arg_ty) - ); - - let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); - - loop { - if let Some((potential_self_ty, _)) = autoderef.next() { - debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", - potential_self_ty, self_ty); - - if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { - autoderef.finalize(); - if let Some(mut err) = fcx.demand_eqtype_with_origin( - &cause, self_ty, potential_self_ty) { - err.emit(); - } - break - } - } else { - fcx.tcx.sess.diagnostic().mut_span_err( - span, &format!("invalid `self` type: {:?}", self_arg_ty)) - .note(&format!("type must be `{:?}` or a type that dereferences to it`", self_ty)) - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") - .code(DiagnosticId::Error("E0307".into())) - .emit(); - return - } - } - - let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); - let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); - - if !fcx.tcx.features().arbitrary_self_types { - match self_kind { - ExplicitSelf::ByValue | - ExplicitSelf::ByReference(_, _) | - ExplicitSelf::ByBox => (), - - ExplicitSelf::ByRawPointer(_) => { - feature_gate::feature_err( - &fcx.tcx.sess.parse_sess, - "arbitrary_self_types", - span, - GateIssue::Language, - "raw pointer `self` is unstable") - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") - .emit(); - } - - ExplicitSelf::Other => { - feature_gate::feature_err( - &fcx.tcx.sess.parse_sess, - "arbitrary_self_types", - span, - GateIssue::Language,"arbitrary `self` types are unstable") - .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") - .emit(); - } - } - } - } - - fn check_variances_for_type_defn(&self, - item: &hir::Item, - ast_generics: &hir::Generics) - { - let item_def_id = self.tcx.hir.local_def_id(item.id); - let ty = self.tcx.type_of(item_def_id); - if self.tcx.has_error_field(ty) { - return; - } - - let ty_predicates = self.tcx.predicates_of(item_def_id); - assert_eq!(ty_predicates.parent, None); - let variances = self.tcx.variances_of(item_def_id); - - let mut constrained_parameters: FxHashSet<_> = - variances.iter().enumerate() - .filter(|&(_, &variance)| variance != ty::Bivariant) - .map(|(index, _)| Parameter(index as u32)) - .collect(); - - identify_constrained_type_params(self.tcx, - ty_predicates.predicates.as_slice(), - None, - &mut constrained_parameters); - - for (index, _) in variances.iter().enumerate() { - if constrained_parameters.contains(&Parameter(index as u32)) { - continue; - } - - let (span, name) = match ast_generics.params[index] { - hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()), - hir::GenericParam::Type(ref tp) => (tp.span, tp.name), }; - self.report_bivariance(span, name); + let unsized_len = if + all_sized || + variant.fields.is_empty() || + needs_drop_copy() + { + 0 + } else { + 1 + }; + for field in &variant.fields[..variant.fields.len() - unsized_len] { + fcx.register_bound( + field.ty, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + traits::ObligationCause::new(field.span, + fcx.body_id, + traits::FieldSized(match item.node.adt_kind() { + Some(i) => i, + None => bug!(), + }))); + } + + // All field types must be well-formed. + for field in &variant.fields { + fcx.register_wf_obligation(field.ty, field.span, + ObligationCauseCode::MiscObligation) + } } - } - fn report_bivariance(&self, - span: Span, - param_name: ast::Name) - { - let mut err = error_392(self.tcx, span, param_name); + check_where_clauses(tcx, fcx, item.span, def_id); - let suggested_marker_id = self.tcx.lang_items().phantom_data(); - match suggested_marker_id { - Some(def_id) => { - err.help( - &format!("consider removing `{}` or using a marker such as `{}`", - param_name, - self.tcx.item_path_str(def_id))); + vec![] // no implied bounds in a struct def'n + }); +} + +fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { + let trait_def_id = tcx.hir.local_def_id(item.id); + for_item(tcx, item).with_fcx(|fcx, _| { + check_where_clauses(tcx, fcx, item.span, trait_def_id); + vec![] + }); +} + +fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { + for_item(tcx, item).with_fcx(|fcx, tcx| { + let def_id = fcx.tcx.hir.local_def_id(item.id); + let sig = fcx.tcx.fn_sig(def_id); + let sig = fcx.normalize_associated_types_in(item.span, &sig); + let mut implied_bounds = vec![]; + check_fn_or_method(tcx, fcx, item.span, sig, + def_id, &mut implied_bounds); + implied_bounds + }) +} + +fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item) +{ + debug!("check_item_type: {:?}", item); + + for_item(tcx, item).with_fcx(|fcx, _this| { + let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id)); + let item_ty = fcx.normalize_associated_types_in(item.span, &ty); + + fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation); + + vec![] // no implied bounds in a const etc + }); +} + +fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, + ast_self_ty: &hir::Ty, + ast_trait_ref: &Option) +{ + debug!("check_impl: {:?}", item); + + for_item(tcx, item).with_fcx(|fcx, tcx| { + let item_def_id = fcx.tcx.hir.local_def_id(item.id); + + match *ast_trait_ref { + Some(ref ast_trait_ref) => { + let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); + let trait_ref = + fcx.normalize_associated_types_in( + ast_trait_ref.path.span, &trait_ref); + let obligations = + ty::wf::trait_obligations(fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span); + for obligation in obligations { + fcx.register_predicate(obligation); + } } None => { - // no lang items, no help! + let self_ty = fcx.tcx.type_of(item_def_id); + let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty); + fcx.register_wf_obligation(self_ty, ast_self_ty.span, + ObligationCauseCode::MiscObligation); } } - err.emit(); + + check_where_clauses(tcx, fcx, item.span, item_def_id); + + fcx.impl_implied_bounds(item_def_id, item.span) + }); +} + +/// Checks where clauses and inline bounds that are declared on def_id. +fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + def_id: DefId) { + use ty::subst::Subst; + use rustc::ty::TypeFoldable; + + let mut predicates = fcx.tcx.predicates_of(def_id); + let mut substituted_predicates = Vec::new(); + + let generics = tcx.generics_of(def_id); + let is_our_default = |def: &ty::TypeParameterDef| + def.has_default && def.index >= generics.parent_count() as u32; + + // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. + // For example this forbids the declaration: + // struct Foo> { .. } + // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold. + for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) { + let ty = fcx.tcx.type_of(d); + // ignore dependent defaults -- that is, where the default of one type + // parameter includes another (e.g., ). In those cases, we can't + // be sure if it will error or not as user might always specify the other. + if !ty.needs_subst() { + fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), + ObligationCauseCode::MiscObligation); + } } + + // Check that trait predicates are WF when params are substituted by their defaults. + // We don't want to overly constrain the predicates that may be written but we want to + // catch cases where a default my never be applied such as `struct Foo`. + // Therefore we check if a predicate which contains a single type param + // with a concrete default is WF with that default substituted. + // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`. + // + // First we build the defaulted substitution. + let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| { + // All regions are identity. + fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data())) + }, |def, _| { + // If the param has a default, + if is_our_default(def) { + let default_ty = fcx.tcx.type_of(def.def_id); + // and it's not a dependent default + if !default_ty.needs_subst() { + // then substitute with the default. + return default_ty; + } + } + // Mark unwanted params as err. + fcx.tcx.types.err + }); + // Now we build the substituted predicates. + for &pred in predicates.predicates.iter() { + struct CountParams { params: FxHashSet } + impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { + fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + match t.sty { + ty::TyParam(p) => { + self.params.insert(p.idx); + t.super_visit_with(self) + } + _ => t.super_visit_with(self) + } + } + } + let mut param_count = CountParams { params: FxHashSet() }; + pred.visit_with(&mut param_count); + let substituted_pred = pred.subst(fcx.tcx, substs); + // Don't check non-defaulted params, dependent defaults or preds with multiple params. + if substituted_pred.references_error() || param_count.params.len() > 1 { + continue; + } + // Avoid duplication of predicates that contain no parameters, for example. + if !predicates.predicates.contains(&substituted_pred) { + substituted_predicates.push(substituted_pred); + } + } + + predicates.predicates.extend(substituted_predicates); + let predicates = predicates.instantiate_identity(fcx.tcx); + let predicates = fcx.normalize_associated_types_in(span, &predicates); + + let obligations = + predicates.predicates + .iter() + .flat_map(|p| ty::wf::predicate_obligations(fcx, + fcx.param_env, + fcx.body_id, + p, + span)); + + for obligation in obligations { + fcx.register_predicate(obligation); + } +} + +fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + sig: ty::PolyFnSig<'tcx>, + def_id: DefId, + implied_bounds: &mut Vec>) +{ + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); + + for input_ty in sig.inputs() { + fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation); + } + implied_bounds.extend(sig.inputs()); + + fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation); + + // FIXME(#25759) return types should not be implied bounds + implied_bounds.push(sig.output()); + + check_where_clauses(tcx, fcx, span, def_id); +} + +fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + method_sig: &hir::MethodSig, + method: &ty::AssociatedItem, + self_ty: Ty<'tcx>) +{ + // check that the method has a valid receiver type, given the type `Self` + debug!("check_method_receiver({:?}, self_ty={:?})", + method, self_ty); + + if !method.method_has_self_argument { + return; + } + + let span = method_sig.decl.inputs[0].span; + + let sig = fcx.tcx.fn_sig(method.def_id); + let sig = fcx.normalize_associated_types_in(span, &sig); + let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig); + + debug!("check_method_receiver: sig={:?}", sig); + + let self_ty = fcx.normalize_associated_types_in(span, &self_ty); + let self_ty = fcx.tcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_ty) + ); + + let self_arg_ty = sig.inputs()[0]; + + let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); + let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty); + let self_arg_ty = fcx.tcx.liberate_late_bound_regions( + method.def_id, + &ty::Binder(self_arg_ty) + ); + + let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers(); + + loop { + if let Some((potential_self_ty, _)) = autoderef.next() { + debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`", + potential_self_ty, self_ty); + + if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() { + autoderef.finalize(); + if let Some(mut err) = fcx.demand_eqtype_with_origin( + &cause, self_ty, potential_self_ty) { + err.emit(); + } + break + } + } else { + fcx.tcx.sess.diagnostic().mut_span_err( + span, &format!("invalid `self` type: {:?}", self_arg_ty)) + .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty)) + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .code(DiagnosticId::Error("E0307".into())) + .emit(); + return + } + } + + let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); + let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); + + if !fcx.tcx.features().arbitrary_self_types { + match self_kind { + ExplicitSelf::ByValue | + ExplicitSelf::ByReference(_, _) | + ExplicitSelf::ByBox => (), + + ExplicitSelf::ByRawPointer(_) => { + feature_gate::feature_err( + &fcx.tcx.sess.parse_sess, + "arbitrary_self_types", + span, + GateIssue::Language, + "raw pointer `self` is unstable") + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .emit(); + } + + ExplicitSelf::Other => { + feature_gate::feature_err( + &fcx.tcx.sess.parse_sess, + "arbitrary_self_types", + span, + GateIssue::Language,"arbitrary `self` types are unstable") + .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box`") + .emit(); + } + } + } +} + +fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, + ast_generics: &hir::Generics) +{ + let item_def_id = tcx.hir.local_def_id(item.id); + let ty = tcx.type_of(item_def_id); + if tcx.has_error_field(ty) { + return; + } + + let ty_predicates = tcx.predicates_of(item_def_id); + assert_eq!(ty_predicates.parent, None); + let variances = tcx.variances_of(item_def_id); + + let mut constrained_parameters: FxHashSet<_> = + variances.iter().enumerate() + .filter(|&(_, &variance)| variance != ty::Bivariant) + .map(|(index, _)| Parameter(index as u32)) + .collect(); + + identify_constrained_type_params(tcx, + ty_predicates.predicates.as_slice(), + None, + &mut constrained_parameters); + + for (index, _) in variances.iter().enumerate() { + if constrained_parameters.contains(&Parameter(index as u32)) { + continue; + } + + let (span, name) = match ast_generics.params[index] { + hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()), + hir::GenericParam::Type(ref tp) => (tp.span, tp.name), + }; + report_bivariance(tcx, span, name); + } +} + +fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + span: Span, + param_name: ast::Name) +{ + let mut err = error_392(tcx, span, param_name); + + let suggested_marker_id = tcx.lang_items().phantom_data(); + match suggested_marker_id { + Some(def_id) => { + err.help( + &format!("consider removing `{}` or using a marker such as `{}`", + param_name, + tcx.item_path_str(def_id))); + } + None => { + // no lang items, no help! + } + } + err.emit(); } fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { @@ -648,6 +654,19 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { } } +pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, +} + +impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) + -> CheckTypeWellFormedVisitor<'a, 'gcx> { + CheckTypeWellFormedVisitor { + tcx, + } + } +} + impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None @@ -655,27 +674,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &hir::Item) { debug!("visit_item: {:?}", i); - self.check_item_well_formed(i); + let def_id = self.tcx.hir.local_def_id(i.id); + ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_item(self, i); } fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) { debug!("visit_trait_item: {:?}", trait_item); - let method_sig = match trait_item.node { - hir::TraitItemKind::Method(ref sig, _) => Some(sig), - _ => None - }; - self.check_associated_item(trait_item.id, trait_item.span, method_sig); + let def_id = self.tcx.hir.local_def_id(trait_item.id); + ty::maps::queries::check_trait_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_trait_item(self, trait_item) } fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) { debug!("visit_impl_item: {:?}", impl_item); - let method_sig = match impl_item.node { - hir::ImplItemKind::Method(ref sig, _) => Some(sig), - _ => None - }; - self.check_associated_item(impl_item.id, impl_item.span, method_sig); + let def_id = self.tcx.hir.local_def_id(impl_item.id); + ty::maps::queries::check_impl_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_impl_item(self, impl_item) } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 862b15743c70..bbd04e0b19ae 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -46,6 +46,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_anon_types(); wbcx.visit_cast_types(); wbcx.visit_free_region_map(); + wbcx.visit_user_provided_tys(); let used_trait_imports = mem::replace( &mut self.tables.borrow_mut().used_trait_imports, @@ -341,6 +342,33 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.tables.free_region_map = free_region_map; } + fn visit_user_provided_tys(&mut self) { + let fcx_tables = self.fcx.tables.borrow(); + debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); + let common_local_id_root = fcx_tables.local_id_root.unwrap(); + + for (&local_id, c_ty) in fcx_tables.user_provided_tys().iter() { + let hir_id = hir::HirId { + owner: common_local_id_root.index, + local_id, + }; + + let c_ty = if let Some(c_ty) = self.tcx().lift_to_global(c_ty) { + c_ty + } else { + span_bug!( + hir_id.to_span(&self.fcx.tcx), + "writeback: `{:?}` missing from the global type context", + c_ty + ); + }; + + self.tables + .user_provided_tys_mut() + .insert(hir_id, c_ty.clone()); + } + } + fn visit_anon_types(&mut self) { let gcx = self.tcx().global_tcx(); for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 2f1c42bbef8c..aa4322783c60 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -15,7 +15,7 @@ use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::middle::region; use rustc::middle::lang_items::UnsizeTraitLangItem; -use rustc::traits::{self, ObligationCause}; +use rustc::traits::{self, TraitEngine, ObligationCause}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::TypeFoldable; use rustc::ty::adjustment::CoerceUnsizedInfo; @@ -172,34 +172,34 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); - let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap(); + let coerce_unsized_trait = gcx.lang_items().coerce_unsized_trait().unwrap(); - let unsize_trait = match tcx.lang_items().require(UnsizeTraitLangItem) { + let unsize_trait = match gcx.lang_items().require(UnsizeTraitLangItem) { Ok(id) => id, Err(err) => { - tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); + gcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); } }; // this provider should only get invoked for local def-ids - let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| { + let impl_node_id = gcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| { bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did) }); - let source = tcx.type_of(impl_did); - let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); + let source = gcx.type_of(impl_did); + let trait_ref = gcx.impl_trait_ref(impl_did).unwrap(); assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.substs.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); - let span = tcx.hir.span(impl_node_id); - let param_env = tcx.param_env(impl_did); + let span = gcx.hir.span(impl_node_id); + let param_env = gcx.param_env(impl_did); assert!(!source.has_escaping_regions()); let err_info = CoerceUnsizedInfo { custom_kind: None }; @@ -208,11 +208,11 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt().enter(|infcx| { + gcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); - let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, - mt_b: ty::TypeAndMut<'tcx>, - mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| { + let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, + mt_b: ty::TypeAndMut<'gcx>, + mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| { if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { infcx.report_mismatched_types(&cause, mk_ptr(mt_b.ty), @@ -225,20 +225,20 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) { (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => { infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); - check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty)) + check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ref(r_b, ty)) } (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) | (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => { - check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)) + check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ptr(ty)) } (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => { if def_a != def_b { - let source_path = tcx.item_path_str(def_a.did); - let target_path = tcx.item_path_str(def_b.did); - span_err!(tcx.sess, + let source_path = gcx.item_path_str(def_a.did); + let target_path = gcx.item_path_str(def_b.did); + span_err!(gcx.sess, span, E0377, "the trait `CoerceUnsized` may only be implemented \ @@ -292,9 +292,9 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let diff_fields = fields.iter() .enumerate() .filter_map(|(i, f)| { - let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); + let (a, b) = (f.ty(gcx, substs_a), f.ty(gcx, substs_b)); - if tcx.type_of(f.did).is_phantom_data() { + if gcx.type_of(f.did).is_phantom_data() { // Ignore PhantomData fields return None; } @@ -321,7 +321,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .collect::>(); if diff_fields.is_empty() { - span_err!(tcx.sess, + span_err!(gcx.sess, span, E0374, "the trait `CoerceUnsized` may only be implemented \ @@ -329,14 +329,14 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, being coerced, none found"); return err_info; } else if diff_fields.len() > 1 { - let item = tcx.hir.expect_item(impl_node_id); + let item = gcx.hir.expect_item(impl_node_id); let span = if let ItemImpl(.., Some(ref t), _, _) = item.node { t.path.span } else { - tcx.hir.span(impl_node_id) + gcx.hir.span(impl_node_id) }; - let mut err = struct_span_err!(tcx.sess, + let mut err = struct_span_err!(gcx.sess, span, E0375, "implementing the trait \ @@ -363,7 +363,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => { - span_err!(tcx.sess, + span_err!(gcx.sess, span, E0376, "the trait `CoerceUnsized` may only be implemented \ @@ -372,11 +372,11 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - let mut fulfill_cx = traits::FulfillmentContext::new(); + let mut fulfill_cx = TraitEngine::new(infcx.tcx); // Register an obligation for `A: Trait`. let cause = traits::ObligationCause::misc(span, impl_node_id); - let predicate = tcx.predicate_for_trait_def(param_env, + let predicate = gcx.predicate_for_trait_def(param_env, cause, trait_def_id, 0, @@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check that all transitive obligations are satisfied. if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors, None); + infcx.report_fulfillment_errors(&errors, None, false); } // Finally, resolve all regions. diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index d3de31d630a9..07b7c600b9f3 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -52,10 +52,10 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) { let did = Some(trait_def_id); let li = tcx.lang_items(); + let span = tcx.sess.codemap().def_span(tcx.span_of_impl(impl_def_id).unwrap()); // Disallow *all* explicit impls of `Sized` and `Unsize` for now. if did == li.sized_trait() { - let span = tcx.span_of_impl(impl_def_id).unwrap(); struct_span_err!(tcx.sess, span, E0322, @@ -66,11 +66,12 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d } if did == li.unsize_trait() { - let span = tcx.span_of_impl(impl_def_id).unwrap(); - span_err!(tcx.sess, - span, - E0328, - "explicit impls for the `Unsize` trait are not permitted"); + struct_span_err!(tcx.sess, + span, + E0328, + "explicit impls for the `Unsize` trait are not permitted") + .span_label(span, "impl of `Unsize` not allowed") + .emit(); return; } @@ -88,14 +89,14 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d } else { return; // everything OK }; - let mut err = struct_span_err!(tcx.sess, - tcx.span_of_impl(impl_def_id).unwrap(), - E0183, - "manual implementations of `{}` are experimental", - trait_name); - help!(&mut err, - "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); - err.emit(); + struct_span_err!(tcx.sess, + span, + E0183, + "manual implementations of `{}` are experimental", + trait_name) + .span_label(span, format!("manual implementations of `{}` are experimental", trait_name)) + .help("add `#![feature(unboxed_closures)]` to the crate attributes to enable") + .emit(); } pub fn provide(providers: &mut Providers) { @@ -168,13 +169,17 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI traits::supertrait_def_ids(tcx, data.principal().unwrap().def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { - span_err!(tcx.sess, - tcx.span_of_impl(impl_def_id).unwrap(), - E0371, - "the object type `{}` automatically \ - implements the trait `{}`", - trait_ref.self_ty(), - tcx.item_path_str(trait_def_id)); + let sp = tcx.sess.codemap().def_span(tcx.span_of_impl(impl_def_id).unwrap()); + struct_span_err!(tcx.sess, + sp, + E0371, + "the object type `{}` automatically implements the trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id)) + .span_label(sp, format!("`{}` automatically implements trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id))) + .emit(); } } } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index c2dfd798a3c4..6d6594e55437 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -40,29 +40,36 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { self.tcx.hir.node_to_string(item.id)); let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; + let cm = self.tcx.sess.codemap(); + let sp = cm.def_span(item.span); match traits::orphan_check(self.tcx, def_id) { Ok(()) => {} Err(traits::OrphanCheckErr::NoLocalInputType) => { struct_span_err!(self.tcx.sess, - item.span, + sp, E0117, "only traits defined in the current crate can be \ implemented for arbitrary types") - .span_label(item.span, "impl doesn't use types inside crate") - .note(&format!("the impl does not reference any types defined in \ - this crate")) + .span_label(sp, "impl doesn't use types inside crate") + .note("the impl does not reference any types defined in this crate") .note("define and implement a trait or new type instead") .emit(); return; } Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { - span_err!(self.tcx.sess, - item.span, - E0210, - "type parameter `{}` must be used as the type parameter for \ - some local type (e.g. `MyStruct`); only traits defined in \ - the current crate can be implemented for a type parameter", - param_ty); + struct_span_err!(self.tcx.sess, + sp, + E0210, + "type parameter `{}` must be used as the type parameter \ + for some local type (e.g. `MyStruct<{}>`)", + param_ty, + param_ty) + .span_label(sp, + format!("type parameter `{}` must be used as the type \ + parameter for some local type", param_ty)) + .note("only traits defined in the current crate can be implemented \ + for a type parameter") + .emit(); return; } } @@ -121,22 +128,29 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { if self_def_id.is_local() { None } else { - Some(format!("cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - self.tcx.item_path_str(trait_def_id))) + Some(( + format!("cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type \ + defined in the current crate", + self.tcx.item_path_str(trait_def_id)), + "can't implement cross-crate trait for type in another crate" + )) } } _ => { - Some(format!("cross-crate traits with a default impl, like `{}`, can \ - only be implemented for a struct/enum type, not `{}`", - self.tcx.item_path_str(trait_def_id), - self_ty)) + Some((format!("cross-crate traits with a default impl, like `{}`, can \ + only be implemented for a struct/enum type, not `{}`", + self.tcx.item_path_str(trait_def_id), + self_ty), + "can't implement cross-crate trait with a default impl for \ + non-struct/enum type")) } }; - if let Some(msg) = msg { - span_err!(self.tcx.sess, item.span, E0321, "{}", msg); + if let Some((msg, label)) = msg { + struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg) + .span_label(sp, label) + .emit(); return; } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a17b35dec42d..59156bf0dfea 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -35,8 +35,9 @@ use rustc::ty::{ToPredicate, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; -use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::ty::util::Discr; +use rustc::util::captures::Captures; +use rustc::util::nodemap::{FxHashSet, FxHashMap}; use syntax::{abi, ast}; use syntax::ast::MetaItemKind; @@ -1281,7 +1282,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, fn early_bound_lifetimes_from_generics<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, ast_generics: &'a hir::Generics) - -> impl Iterator + -> impl Iterator + Captures<'tcx> { ast_generics .lifetimes() @@ -1768,6 +1769,7 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt let whitelist = tcx.target_features_whitelist(LOCAL_CRATE); + let mut inline_span = None; for attr in attrs.iter() { if attr.check_name("cold") { trans_fn_attrs.flags |= TransFnAttrFlags::COLD; @@ -1799,6 +1801,7 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt } MetaItemKind::List(ref items) => { mark_used(attr); + inline_span = Some(attr.span); if items.len() != 1 { span_err!(tcx.sess.diagnostic(), attr.span, E0534, "expected one argument"); @@ -1854,5 +1857,18 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt } } + // If a function uses #[target_feature] it can't be inlined into general + // purpose functions as they wouldn't have the right target features + // enabled. For that reason we also forbid #[inline(always)] as it can't be + // respected. + if trans_fn_attrs.target_features.len() > 0 { + if trans_fn_attrs.inline == InlineAttr::Always { + if let Some(span) = inline_span { + tcx.sess.span_err(span, "cannot use #[inline(always)] with \ + #[target_feature]"); + } + } + } + trans_fn_attrs } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 24044fd2d721..79d7c8e72821 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -721,16 +721,6 @@ fn main() { ``` "##, -E0066: r##" -Box placement expressions (like C++'s "placement new") do not yet support any -place expression except the exchange heap (i.e. `std::boxed::HEAP`). -Furthermore, the syntax is changing to use `in` instead of `box`. See [RFC 470] -and [RFC 809] for more details. - -[RFC 470]: https://github.com/rust-lang/rfcs/pull/470 -[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md -"##, - E0067: r##" The left-hand side of a compound assignment expression must be a place expression. A place expression represents a memory location and includes @@ -1918,16 +1908,16 @@ differs from the behavior for `&T`, which is always `Copy`). E0206: r##" You can only implement `Copy` for a struct or enum. Both of the following -examples will fail, because neither `i32` (primitive type) nor `&'static Bar` -(reference to `Bar`) is a struct or enum: +examples will fail, because neither `[u8; 256]` nor `&'static mut Bar` +(mutable reference to `Bar`) is a struct or enum: ```compile_fail,E0206 -type Foo = i32; +type Foo = [u8; 256]; impl Copy for Foo { } // error #[derive(Copy, Clone)] struct Bar; -impl Copy for &'static Bar { } // error +impl Copy for &'static mut Bar { } // error ``` "##, @@ -3559,8 +3549,6 @@ elements in the array being matched. Example of erroneous code: ```compile_fail,E0527 -#![feature(slice_patterns)] - let r = &[1, 2, 3, 4]; match r { &[a, b] => { // error: pattern requires 2 elements but array @@ -3625,8 +3613,6 @@ An array or slice pattern was matched against some other type. Example of erroneous code: ```compile_fail,E0529 -#![feature(slice_patterns)] - let r: f32 = 1.0; match r { [a, b] => { // error: expected an array or slice, found `f32` @@ -3639,8 +3625,6 @@ Ensure that the pattern and the expression being matched on are of consistent types: ``` -#![feature(slice_patterns)] - let r = [1.0, 2.0]; match r { [a, b] => { // ok! @@ -3800,7 +3784,6 @@ that impl must be declared as an `unsafe impl. Erroneous code example: ```compile_fail,E0569 -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] struct Foo(X); @@ -4606,7 +4589,6 @@ This error indicates that there is a mismatch between generic parameters and impl Trait parameters in a trait declaration versus its impl. ```compile_fail,E0643 -#![feature(universal_impl_trait)] trait Foo { fn foo(&self, _: &impl Iterator); } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 1eed1bf4b71f..faf3ccb1133a 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -42,21 +42,21 @@ use syntax_pos::Span; /// /// Example: /// -/// ``` +/// ```rust,ignore (pseudo-Rust) /// impl Trait for Bar { ... } -/// ^ T does not appear in `Foo` or `Bar`, error! +/// // ^ T does not appear in `Foo` or `Bar`, error! /// /// impl Trait> for Bar { ... } -/// ^ T appears in `Foo`, ok. +/// // ^ T appears in `Foo`, ok. /// /// impl Trait for Bar where Bar: Iterator { ... } -/// ^ T is bound to `::Item`, ok. +/// // ^ T is bound to `::Item`, ok. /// /// impl<'a> Trait for Bar { } -/// ^ 'a is unused, but for back-compat we allow it +/// // ^ 'a is unused, but for back-compat we allow it /// /// impl<'a> Trait for Bar { type X = &'a i32; } -/// ^ 'a is unused and appears in assoc type, error +/// // ^ 'a is unused and appears in assoc type, error /// ``` pub fn impl_wf_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // We will tag this as part of the WF check -- logically, it is, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 40385cabf566..44ecb32a0bf9 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -72,21 +72,23 @@ This API is completely unstable and subject to change. #![allow(non_camel_case_types)] -#![feature(advanced_slice_patterns)] +#![cfg_attr(stage0, feature(advanced_slice_patterns))] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(conservative_impl_trait)] -#![feature(copy_closures, clone_closures)] +#![cfg_attr(stage0, feature(conservative_impl_trait))] +#![cfg_attr(stage0, feature(copy_closures, clone_closures))] #![feature(crate_visibility_modifier)] #![feature(from_ref)] -#![feature(match_default_bindings)] -#![feature(never_type)] +#![cfg_attr(stage0, feature(match_default_bindings))] +#![feature(exhaustive_patterns)] #![feature(option_filter)] #![feature(quote)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] +#![cfg_attr(stage0, feature(never_type))] +#![feature(dyn_trait)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -110,7 +112,7 @@ use rustc::infer::InferOk; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; -use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; +use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine}; use session::{CompileIncomplete, config}; use util::common::time; @@ -158,8 +160,8 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, actual: Ty<'tcx>) -> bool { tcx.infer_ctxt().enter(|ref infcx| { - let param_env = ty::ParamEnv::empty(Reveal::UserFacing); - let mut fulfill_cx = FulfillmentContext::new(); + let param_env = ty::ParamEnv::empty(); + let mut fulfill_cx = TraitEngine::new(infcx.tcx); match infcx.at(&cause, param_env).eq(expected, actual) { Ok(InferOk { obligations, .. }) => { fulfill_cx.register_predicate_obligations(infcx, obligations); @@ -173,7 +175,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match fulfill_cx.select_all_or_error(infcx) { Ok(()) => true, Err(errors) => { - infcx.report_fulfillment_errors(&errors, None); + infcx.report_fulfillment_errors(&errors, None, false); false } } @@ -207,8 +209,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let actual = tcx.fn_sig(main_def_id); - let expected_return_type = if tcx.lang_items().termination().is_some() - && tcx.features().termination_trait { + let expected_return_type = if tcx.lang_items().termination().is_some() { // we take the return type of the given main function, the real check is done // in `check_fn` actual.output().skip_binder() @@ -315,41 +316,39 @@ pub fn provide(providers: &mut Providers) { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { - let time_passes = tcx.sess.time_passes(); - // this ensures that later parts of type checking can assume that items // have valid types and not error tcx.sess.track_errors(|| { - time(time_passes, "type collecting", || + time(tcx.sess, "type collecting", || collect::collect_item_types(tcx)); })?; tcx.sess.track_errors(|| { - time(time_passes, "outlives testing", || + time(tcx.sess, "outlives testing", || outlives::test::test_inferred_outlives(tcx)); })?; tcx.sess.track_errors(|| { - time(time_passes, "impl wf inference", || + time(tcx.sess, "impl wf inference", || impl_wf_check::impl_wf_check(tcx)); })?; tcx.sess.track_errors(|| { - time(time_passes, "coherence checking", || + time(tcx.sess, "coherence checking", || coherence::check_coherence(tcx)); })?; tcx.sess.track_errors(|| { - time(time_passes, "variance testing", || + time(tcx.sess, "variance testing", || variance::test::test_variance(tcx)); })?; - time(time_passes, "wf checking", || check::check_wf_new(tcx))?; + time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?; - time(time_passes, "item-types checking", || check::check_item_types(tcx))?; + time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?; - time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?; + time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?; check_unused::check_crate(tcx); check_for_entry_fn(tcx); diff --git a/src/librustc_typeck/variance/README.md b/src/librustc_typeck/variance/README.md deleted file mode 100644 index 64d3389b34af..000000000000 --- a/src/librustc_typeck/variance/README.md +++ /dev/null @@ -1,276 +0,0 @@ -## Variance of type and lifetime parameters - -This file infers the variance of type and lifetime parameters. The -algorithm is taken from Section 4 of the paper "Taming the Wildcards: -Combining Definition- and Use-Site Variance" published in PLDI'11 and -written by Altidor et al., and hereafter referred to as The Paper. - -This inference is explicitly designed *not* to consider the uses of -types within code. To determine the variance of type parameters -defined on type `X`, we only consider the definition of the type `X` -and the definitions of any types it references. - -We only infer variance for type parameters found on *data types* -like structs and enums. In these cases, there is fairly straightforward -explanation for what variance means. The variance of the type -or lifetime parameters defines whether `T` is a subtype of `T` -(resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B` -(resp. `'a` and `'b`). - -We do not infer variance for type parameters found on traits, fns, -or impls. Variance on trait parameters can make indeed make sense -(and we used to compute it) but it is actually rather subtle in -meaning and not that useful in practice, so we removed it. See the -addendum for some details. Variances on fn/impl parameters, otoh, -doesn't make sense because these parameters are instantiated and -then forgotten, they don't persist in types or compiled -byproducts. - -### The algorithm - -The basic idea is quite straightforward. We iterate over the types -defined and, for each use of a type parameter X, accumulate a -constraint indicating that the variance of X must be valid for the -variance of that use site. We then iteratively refine the variance of -X until all constraints are met. There is *always* a sol'n, because at -the limit we can declare all type parameters to be invariant and all -constraints will be satisfied. - -As a simple example, consider: - - enum Option { Some(A), None } - enum OptionalFn { Some(|B|), None } - enum OptionalMap { Some(|C| -> C), None } - -Here, we will generate the constraints: - - 1. V(A) <= + - 2. V(B) <= - - 3. V(C) <= + - 4. V(C) <= - - -These indicate that (1) the variance of A must be at most covariant; -(2) the variance of B must be at most contravariant; and (3, 4) the -variance of C must be at most covariant *and* contravariant. All of these -results are based on a variance lattice defined as follows: - - * Top (bivariant) - - + - o Bottom (invariant) - -Based on this lattice, the solution `V(A)=+`, `V(B)=-`, `V(C)=o` is the -optimal solution. Note that there is always a naive solution which -just declares all variables to be invariant. - -You may be wondering why fixed-point iteration is required. The reason -is that the variance of a use site may itself be a function of the -variance of other type parameters. In full generality, our constraints -take the form: - - V(X) <= Term - Term := + | - | * | o | V(X) | Term x Term - -Here the notation `V(X)` indicates the variance of a type/region -parameter `X` with respect to its defining class. `Term x Term` -represents the "variance transform" as defined in the paper: - -> If the variance of a type variable `X` in type expression `E` is `V2` - and the definition-site variance of the [corresponding] type parameter - of a class `C` is `V1`, then the variance of `X` in the type expression - `C` is `V3 = V1.xform(V2)`. - -### Constraints - -If I have a struct or enum with where clauses: - - struct Foo { ... } - -you might wonder whether the variance of `T` with respect to `Bar` -affects the variance `T` with respect to `Foo`. I claim no. The -reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t -`Foo`. And then we have a `Foo` that is upcast to `Foo`, where -`X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold. In that -case, the upcast will be illegal, but not because of a variance -failure, but rather because the target type `Foo` is itself just -not well-formed. Basically we get to assume well-formedness of all -types involved before considering variance. - -#### Dependency graph management - -Because variance is a whole-crate inference, its dependency graph -can become quite muddled if we are not careful. To resolve this, we refactor -into two queries: - -- `crate_variances` computes the variance for all items in the current crate. -- `variances_of` accesses the variance for an individual reading; it - works by requesting `crate_variances` and extracting the relevant data. - -If you limit yourself to reading `variances_of`, your code will only -depend then on the inference inferred for that particular item. - -Ultimately, this setup relies on the red-green algorithm. -In particular, every variance query ultimately depends on -- effectively -- -all type definitions in the entire crate (through `crate_variances`), -but since most changes will not result in a change -to the actual results from variance inference, -the `variances_of` query will wind up being considered green after it is re-evaluated. - -### Addendum: Variance on traits - -As mentioned above, we used to permit variance on traits. This was -computed based on the appearance of trait type parameters in -method signatures and was used to represent the compatibility of -vtables in trait objects (and also "virtual" vtables or dictionary -in trait bounds). One complication was that variance for -associated types is less obvious, since they can be projected out -and put to myriad uses, so it's not clear when it is safe to allow -`X::Bar` to vary (or indeed just what that means). Moreover (as -covered below) all inputs on any trait with an associated type had -to be invariant, limiting the applicability. Finally, the -annotations (`MarkerTrait`, `PhantomFn`) needed to ensure that all -trait type parameters had a variance were confusing and annoying -for little benefit. - -Just for historical reference,I am going to preserve some text indicating -how one could interpret variance and trait matching. - -#### Variance and object types - -Just as with structs and enums, we can decide the subtyping -relationship between two object types `&Trait` and `&Trait` -based on the relationship of `A` and `B`. Note that for object -types we ignore the `Self` type parameter -- it is unknown, and -the nature of dynamic dispatch ensures that we will always call a -function that is expected the appropriate `Self` type. However, we -must be careful with the other type parameters, or else we could -end up calling a function that is expecting one type but provided -another. - -To see what I mean, consider a trait like so: - - trait ConvertTo { - fn convertTo(&self) -> A; - } - -Intuitively, If we had one object `O=&ConvertTo` and another -`S=&ConvertTo`, then `S <: O` because `String <: Object` -(presuming Java-like "string" and "object" types, my go to examples -for subtyping). The actual algorithm would be to compare the -(explicit) type parameters pairwise respecting their variance: here, -the type parameter A is covariant (it appears only in a return -position), and hence we require that `String <: Object`. - -You'll note though that we did not consider the binding for the -(implicit) `Self` type parameter: in fact, it is unknown, so that's -good. The reason we can ignore that parameter is precisely because we -don't need to know its value until a call occurs, and at that time (as -you said) the dynamic nature of virtual dispatch means the code we run -will be correct for whatever value `Self` happens to be bound to for -the particular object whose method we called. `Self` is thus different -from `A`, because the caller requires that `A` be known in order to -know the return type of the method `convertTo()`. (As an aside, we -have rules preventing methods where `Self` appears outside of the -receiver position from being called via an object.) - -#### Trait variance and vtable resolution - -But traits aren't only used with objects. They're also used when -deciding whether a given impl satisfies a given trait bound. To set the -scene here, imagine I had a function: - - fn convertAll>(v: &[T]) { - ... - } - -Now imagine that I have an implementation of `ConvertTo` for `Object`: - - impl ConvertTo for Object { ... } - -And I want to call `convertAll` on an array of strings. Suppose -further that for whatever reason I specifically supply the value of -`String` for the type parameter `T`: - - let mut vector = vec!["string", ...]; - convertAll::(vector); - -Is this legal? To put another way, can we apply the `impl` for -`Object` to the type `String`? The answer is yes, but to see why -we have to expand out what will happen: - -- `convertAll` will create a pointer to one of the entries in the - vector, which will have type `&String` -- It will then call the impl of `convertTo()` that is intended - for use with objects. This has the type: - - fn(self: &Object) -> i32 - - It is ok to provide a value for `self` of type `&String` because - `&String <: &Object`. - -OK, so intuitively we want this to be legal, so let's bring this back -to variance and see whether we are computing the correct result. We -must first figure out how to phrase the question "is an impl for -`Object,i32` usable where an impl for `String,i32` is expected?" - -Maybe it's helpful to think of a dictionary-passing implementation of -type classes. In that case, `convertAll()` takes an implicit parameter -representing the impl. In short, we *have* an impl of type: - - V_O = ConvertTo for Object - -and the function prototype expects an impl of type: - - V_S = ConvertTo for String - -As with any argument, this is legal if the type of the value given -(`V_O`) is a subtype of the type expected (`V_S`). So is `V_O <: V_S`? -The answer will depend on the variance of the various parameters. In -this case, because the `Self` parameter is contravariant and `A` is -covariant, it means that: - - V_O <: V_S iff - i32 <: i32 - String <: Object - -These conditions are satisfied and so we are happy. - -#### Variance and associated types - -Traits with associated types -- or at minimum projection -expressions -- must be invariant with respect to all of their -inputs. To see why this makes sense, consider what subtyping for a -trait reference means: - - <: - -means that if I know that `T as Trait`, I also know that `U as -Trait`. Moreover, if you think of it as dictionary passing style, -it means that a dictionary for `` is safe to use where -a dictionary for `` is expected. - -The problem is that when you can project types out from ``, the relationship to types projected out of `` -is completely unknown unless `T==U` (see #21726 for more -details). Making `Trait` invariant ensures that this is true. - -Another related reason is that if we didn't make traits with -associated types invariant, then projection is no longer a -function with a single result. Consider: - -``` -trait Identity { type Out; fn foo(&self); } -impl Identity for T { type Out = T; ... } -``` - -Now if I have `<&'static () as Identity>::Out`, this can be -validly derived as `&'a ()` for any `'a`: - - <&'a () as Identity> <: <&'static () as Identity> - if &'static () < : &'a () -- Identity is contravariant in Self - if 'static : 'a -- Subtyping rules for relations - -This change otoh means that `<'static () as Identity>::Out` is -always `&'static ()` (which might then be upcast to `'a ()`, -separately). This was helpful in solving #21750. - - diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 44ac7a10e828..a24e501aba95 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -287,7 +287,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_mt(current, mt, variance); } - ty::TyTuple(subtys, _) => { + ty::TyTuple(subtys) => { for &subty in subtys { self.add_constraints_from_ty(current, subty, variance); } @@ -423,6 +423,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // way early-bound regions do, so we skip them here. } + ty::ReCanonical(_) | ty::ReFree(..) | ty::ReClosureBound(..) | ty::ReScope(..) | diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index da243650c839..fd2b964103a3 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Module for inferring the variance of type and lifetime -//! parameters. See README.md for details. +//! Module for inferring the variance of type and lifetime parameters. See the [rustc guide] +//! chapter for more info. +//! +//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/variance.html use arena; use rustc::hir; diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index ac3d575b6488..b9ab00130b3c 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -87,7 +87,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> lang_items: lang_items(tcx), }; - // See README.md for a discussion on dep-graph management. + // See the following for a discussion on dep-graph management. + // + // - https://rust-lang-nursery.github.io/rustc-guide/query.html + // - https://rust-lang-nursery.github.io/rustc-guide/variance.html tcx.hir.krate().visit_all_item_likes(&mut terms_cx); terms_cx diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md index b0a5ae3718df..2cfe43a8389b 100644 --- a/src/librustdoc/README.md +++ b/src/librustdoc/README.md @@ -1,172 +1,3 @@ -# The walking tour of rustdoc +For more information about how `librustdoc` works, see the [rustc guide]. -Rustdoc is implemented entirely within the crate `librustdoc`. After partially compiling a crate to -get its AST (technically the HIR map) from rustc, librustdoc performs two major steps past that to -render a set of documentation: - -* "Clean" the AST into a form that's more suited to creating documentation (and slightly more - resistant to churn in the compiler). -* Use this cleaned AST to render a crate's documentation, one page at a time. - -Naturally, there's more than just this, and those descriptions simplify out lots of details, but -that's the high-level overview. - -(Side note: this is a library crate! The `rustdoc` binary is crated using the project in -`src/tools/rustdoc`. Note that literally all that does is call the `main()` that's in this crate's -`lib.rs`, though.) - -## Cheat sheet - -* Use `x.py build --stage 1 src/libstd src/tools/rustdoc` to make a useable rustdoc you can run on - other projects. - * Add `src/libtest` to be able to use `rustdoc --test`. - * If you've used `rustup toolchain link local /path/to/build/$TARGET/stage1` previously, then - after the previous build command, `cargo +local doc` will Just Work. -* Use `x.py doc --stage 1 src/libstd` to use this rustdoc to generate the standard library docs. - * The completed docs will be available in `build/$TARGET/doc/std`, though the bundle is meant to - be used as though you would copy out the `doc` folder to a web server, since that's where the - CSS/JS and landing page are. -* Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of - `fmt::Display` implementations and supplementary functions. -* The types that got `Display` impls above are defined in `clean/mod.rs`, right next to the custom - `Clean` trait used to process them out of the rustc HIR. -* The bits specific to using rustdoc as a test harness are in `test.rs`. -* The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting - doctests from a given block of Markdown. -* The tests on rustdoc *output* are located in `src/test/rustdoc`, where they're handled by the test - runner of rustbuild and the supplementary script `src/etc/htmldocck.py`. -* Tests on search index generation are located in `src/test/rustdoc-js`, as a series of JavaScript - files that encode queries on the standard library search index and expected results. - -## From crate to clean - -In `core.rs` are two central items: the `DocContext` struct, and the `run_core` function. The latter -is where rustdoc calls out to rustc to compile a crate to the point where rustdoc can take over. The -former is a state container used when crawling through a crate to gather its documentation. - -The main process of crate crawling is done in `clean/mod.rs` through several implementations of the -`Clean` trait defined within. This is a conversion trait, which defines one method: - -```rust -pub trait Clean { - fn clean(&self, cx: &DocContext) -> T; -} -``` - -`clean/mod.rs` also defines the types for the "cleaned" AST used later on to render documentation -pages. Each usually accompanies an implementation of `Clean` that takes some AST or HIR type from -rustc and converts it into the appropriate "cleaned" type. "Big" items like modules or associated -items may have some extra processing in its `Clean` implementation, but for the most part these -impls are straightforward conversions. The "entry point" to this module is the `impl Clean -for visit_ast::RustdocVisitor`, which is called by `run_core` above. - -You see, I actually lied a little earlier: There's another AST transformation that happens before -the events in `clean/mod.rs`. In `visit_ast.rs` is the type `RustdocVisitor`, which *actually* -crawls a `hir::Crate` to get the first intermediate representation, defined in `doctree.rs`. This -pass is mainly to get a few intermediate wrappers around the HIR types and to process visibility -and inlining. This is where `#[doc(inline)]`, `#[doc(no_inline)]`, and `#[doc(hidden)]` are -processed, as well as the logic for whether a `pub use` should get the full page or a "Reexport" -line in the module page. - -The other major thing that happens in `clean/mod.rs` is the collection of doc comments and -`#[doc=""]` attributes into a separate field of the Attributes struct, present on anything that gets -hand-written documentation. This makes it easier to collect this documentation later in the process. - -The primary output of this process is a clean::Crate with a tree of Items which describe the -publicly-documentable items in the target crate. - -### Hot potato - -Before moving on to the next major step, a few important "passes" occur over the documentation. -These do things like combine the separate "attributes" into a single string and strip leading -whitespace to make the document easier on the markdown parser, or drop items that are not public or -deliberately hidden with `#[doc(hidden)]`. These are all implemented in the `passes/` directory, one -file per pass. By default, all of these passes are run on a crate, but the ones regarding dropping -private/hidden items can be bypassed by passing `--document-private-items` to rustdoc. - -(Strictly speaking, you can fine-tune the passes run and even add your own, but [we're trying to -deprecate that][44136]. If you need finer-grain control over these passes, please let us know!) - -[44136]: https://github.com/rust-lang/rust/issues/44136 - -## From clean to crate - -This is where the "second phase" in rustdoc begins. This phase primarily lives in the `html/` -folder, and it all starts with `run()` in `html/render.rs`. This code is responsible for setting up -the `Context`, `SharedContext`, and `Cache` which are used during rendering, copying out the static -files which live in every rendered set of documentation (things like the fonts, CSS, and JavaScript -that live in `html/static/`), creating the search index, and printing out the source code rendering, -before beginning the process of rendering all the documentation for the crate. - -Several functions implemented directly on `Context` take the `clean::Crate` and set up some state -between rendering items or recursing on a module's child items. From here the "page rendering" -begins, via an enormous `write!()` call in `html/layout.rs`. The parts that actually generate HTML -from the items and documentation occurs within a series of `std::fmt::Display` implementations and -functions that pass around a `&mut std::fmt::Formatter`. The top-level implementation that writes -out the page body is the `impl<'a> fmt::Display for Item<'a>` in `html/render.rs`, which switches -out to one of several `item_*` functions based on the kind of `Item` being rendered. - -Depending on what kind of rendering code you're looking for, you'll probably find it either in -`html/render.rs` for major items like "what sections should I print for a struct page" or -`html/format.rs` for smaller component pieces like "how should I print a where clause as part of -some other item". - -Whenever rustdoc comes across an item that should print hand-written documentation alongside, it -calls out to `html/markdown.rs` which interfaces with the Markdown parser. This is exposed as a -series of types that wrap a string of Markdown, and implement `fmt::Display` to emit HTML text. It -takes special care to enable certain features like footnotes and tables and add syntax highlighting -to Rust code blocks (via `html/highlight.rs`) before running the Markdown parser. There's also a -function in here (`find_testable_code`) that specifically scans for Rust code blocks so the -test-runner code can find all the doctests in the crate. - -### From soup to nuts - -(alternate title: ["An unbroken thread that stretches from those first `Cell`s to us"][video]) - -[video]: https://www.youtube.com/watch?v=hOLAGYmUQV0 - -It's important to note that the AST cleaning can ask the compiler for information (crucially, -`DocContext` contains a `TyCtxt`), but page rendering cannot. The `clean::Crate` created within -`run_core` is passed outside the compiler context before being handed to `html::render::run`. This -means that a lot of the "supplementary data" that isn't immediately available inside an item's -definition, like which trait is the `Deref` trait used by the language, needs to be collected during -cleaning, stored in the `DocContext`, and passed along to the `SharedContext` during HTML rendering. -This manifests as a bunch of shared state, context variables, and `RefCell`s. - -Also of note is that some items that come from "asking the compiler" don't go directly into the -`DocContext` - for example, when loading items from a foreign crate, rustdoc will ask about trait -implementations and generate new `Item`s for the impls based on that information. This goes directly -into the returned `Crate` rather than roundabout through the `DocContext`. This way, these -implementations can be collected alongside the others, right before rendering the HTML. - -## Other tricks up its sleeve - -All this describes the process for generating HTML documentation from a Rust crate, but there are -couple other major modes that rustdoc runs in. It can also be run on a standalone Markdown file, or -it can run doctests on Rust code or standalone Markdown files. For the former, it shortcuts straight -to `html/markdown.rs`, optionally including a mode which inserts a Table of Contents to the output -HTML. - -For the latter, rustdoc runs a similar partial-compilation to get relevant documentation in -`test.rs`, but instead of going through the full clean and render process, it runs a much simpler -crate walk to grab *just* the hand-written documentation. Combined with the aforementioned -"`find_testable_code`" in `html/markdown.rs`, it builds up a collection of tests to run before -handing them off to the libtest test runner. One notable location in `test.rs` is the function -`make_test`, which is where hand-written doctests get transformed into something that can be -executed. - -## Dotting i's and crossing t's - -So that's rustdoc's code in a nutshell, but there's more things in the repo that deal with it. Since -we have the full `compiletest` suite at hand, there's a set of tests in `src/test/rustdoc` that make -sure the final HTML is what we expect in various situations. These tests also use a supplementary -script, `src/etc/htmldocck.py`, that allows it to look through the final HTML using XPath notation -to get a precise look at the output. The full description of all the commands available to rustdoc -tests is in `htmldocck.py`. - -In addition, there are separate tests for the search index and rustdoc's ability to query it. The -files in `src/test/rustdoc-js` each contain a different search query and the expected results, -broken out by search tab. These files are processed by a script in `src/tools/rustdoc-js` and the -Node.js runtime. These tests don't have as thorough of a writeup, but a broad example that features -results in all tabs can be found in `basic.js`. The basic idea is that you match a given `QUERY` -with a set of `EXPECTED` results, complete with the full item path of each item. +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustdoc.html diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 370fc9bbca24..fe4f785aa915 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -9,6 +9,7 @@ // except according to those terms. use rustc::ty::TypeFoldable; +use std::fmt::Debug; use super::*; @@ -684,14 +685,12 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { new_env = ty::ParamEnv::new( tcx.mk_predicates(normalized_preds), param_env.reveal, - ty::UniverseIndex::ROOT, ); } let final_user_env = ty::ParamEnv::new( tcx.mk_predicates(user_computed_preds.into_iter()), user_env.reveal, - ty::UniverseIndex::ROOT, ); debug!( "evaluate_nested_obligations(ty_did={:?}, trait_did={:?}): succeeded with '{:?}' \ @@ -1081,18 +1080,25 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { return None; } + let mut bounds_vec = bounds.into_iter().collect(); + self.sort_where_bounds(&mut bounds_vec); + Some(WherePredicate::BoundPredicate { ty, - bounds: bounds.into_iter().collect(), + bounds: bounds_vec, }) }) .chain( lifetime_to_bounds .into_iter() .filter(|&(_, ref bounds)| !bounds.is_empty()) - .map(|(lifetime, bounds)| WherePredicate::RegionPredicate { - lifetime, - bounds: bounds.into_iter().collect(), + .map(|(lifetime, bounds)| { + let mut bounds_vec = bounds.into_iter().collect(); + self.sort_where_lifetimes(&mut bounds_vec); + WherePredicate::RegionPredicate { + lifetime, + bounds: bounds_vec, + } }), ) .collect() @@ -1372,40 +1378,64 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // a given set of predicates always appears in the same order - // both for visual consistency between 'rustdoc' runs, and to // make writing tests much easier - fn sort_where_predicates(&self, predicates: &mut Vec) { + #[inline] + fn sort_where_predicates(&self, mut predicates: &mut Vec) { // We should never have identical bounds - and if we do, // they're visually identical as well. Therefore, using // an unstable sort is fine. - predicates.sort_unstable_by(|first, second| { - // This might look horrendously hacky, but it's actually not that bad. - // - // For performance reasons, we use several different FxHashMaps - // in the process of computing the final set of where predicates. - // However, the iteration order of a HashMap is completely unspecified. - // In fact, the iteration of an FxHashMap can even vary between platforms, - // since FxHasher has different behavior for 32-bit and 64-bit platforms. - // - // Obviously, it's extremely undesireable for documentation rendering - // to be depndent on the platform it's run on. Apart from being confusing - // to end users, it makes writing tests much more difficult, as predicates - // can appear in any order in the final result. - // - // To solve this problem, we sort WherePredicates by their Debug - // string. The thing to keep in mind is that we don't really - // care what the final order is - we're synthesizing an impl - // ourselves, so any order can be considered equally valid. - // By sorting the predicates, however, we ensure that for - // a given codebase, all auto-trait impls always render - // in exactly the same way. - // - // Using the Debug impementation for sorting prevents - // us from needing to write quite a bit of almost - // entirely useless code (e.g. how should two - // Types be sorted relative to each other). - // This approach is probably somewhat slower, but - // the small number of items involved (impls - // rarely have more than a few bounds) means - // that it shouldn't matter in practice. + self.unstable_debug_sort(&mut predicates); + } + + // Ensure that the bounds are in a consistent order. The precise + // ordering doesn't actually matter, but it's important that + // a given set of bounds always appears in the same order - + // both for visual consistency between 'rustdoc' runs, and to + // make writing tests much easier + #[inline] + fn sort_where_bounds(&self, mut bounds: &mut Vec) { + // We should never have identical bounds - and if we do, + // they're visually identical as well. Therefore, using + // an unstable sort is fine. + self.unstable_debug_sort(&mut bounds); + } + + #[inline] + fn sort_where_lifetimes(&self, mut bounds: &mut Vec) { + // We should never have identical bounds - and if we do, + // they're visually identical as well. Therefore, using + // an unstable sort is fine. + self.unstable_debug_sort(&mut bounds); + } + + // This might look horrendously hacky, but it's actually not that bad. + // + // For performance reasons, we use several different FxHashMaps + // in the process of computing the final set of where predicates. + // However, the iteration order of a HashMap is completely unspecified. + // In fact, the iteration of an FxHashMap can even vary between platforms, + // since FxHasher has different behavior for 32-bit and 64-bit platforms. + // + // Obviously, it's extremely undesireable for documentation rendering + // to be depndent on the platform it's run on. Apart from being confusing + // to end users, it makes writing tests much more difficult, as predicates + // can appear in any order in the final result. + // + // To solve this problem, we sort WherePredicates and TyParamBounds + // by their Debug string. The thing to keep in mind is that we don't really + // care what the final order is - we're synthesizing an impl or bound + // ourselves, so any order can be considered equally valid. By sorting the + // predicates and bounds, however, we ensure that for a given codebase, all + // auto-trait impls always render in exactly the same way. + // + // Using the Debug impementation for sorting prevents us from needing to + // write quite a bit of almost entirely useless code (e.g. how should two + // Types be sorted relative to each other). It also allows us to solve the + // problem for both WherePredicates and TyParamBounds at the same time. This + // approach is probably somewhat slower, but the small number of items + // involved (impls rarely have more than a few bounds) means that it + // shouldn't matter in practice. + fn unstable_debug_sort(&self, vec: &mut Vec) { + vec.sort_unstable_by(|first, second| { format!("{:?}", first).cmp(&format!("{:?}", second)) }); } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index a769771f8aa8..c228f54217d3 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -138,7 +138,7 @@ impl Cfg { /// Renders the configuration for human display, as a short HTML description. pub(crate) fn render_short_html(&self) -> String { - let mut msg = Html(self).to_string(); + let mut msg = ShortHtml(self).to_string(); if self.should_capitalize_first_letter() { if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { msg[i .. i+1].make_ascii_uppercase(); @@ -149,7 +149,13 @@ impl Cfg { /// Renders the configuration for long display, as a long HTML description. pub(crate) fn render_long_html(&self) -> String { - let mut msg = format!("This is supported on {}", Html(self)); + let on = if self.should_use_with_in_description() { + "with" + } else { + "on" + }; + + let mut msg = format!("This is supported {} {}", on, Html(self)); if self.should_append_only_to_description() { msg.push_str(" only"); } @@ -180,6 +186,13 @@ impl Cfg { } } } + + fn should_use_with_in_description(&self) -> bool { + match *self { + Cfg::Cfg(ref name, _) if name == &"target_feature" => true, + _ => false, + } + } } impl ops::Not for Cfg { @@ -376,6 +389,8 @@ impl<'a> fmt::Display for Html<'a> { }, ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian), ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits), + ("target_feature", Some(feat)) => + return write!(fmt, "target feature {}", feat), _ => "", }; if !human_readable.is_empty() { @@ -390,6 +405,19 @@ impl<'a> fmt::Display for Html<'a> { } } +struct ShortHtml<'a>(&'a Cfg); + +impl<'a> fmt::Display for ShortHtml<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self.0 { + Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => { + write!(fmt, "{}", vendor) + }, + ref cfg => write!(fmt, "{}", Html(cfg)), + } + } +} + #[cfg(test)] mod test { use super::Cfg; @@ -398,6 +426,7 @@ mod test { use syntax::ast::*; use syntax::codemap::dummy_spanned; use syntax_pos::DUMMY_SP; + use syntax::with_globals; fn word_cfg(s: &str) -> Cfg { Cfg::Cfg(Symbol::intern(s), None) @@ -409,479 +438,502 @@ mod test { #[test] fn test_cfg_not() { - assert_eq!(!Cfg::False, Cfg::True); - assert_eq!(!Cfg::True, Cfg::False); - assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test")))); - assert_eq!( - !Cfg::All(vec![word_cfg("a"), word_cfg("b")]), - Cfg::Not(Box::new(Cfg::All(vec![word_cfg("a"), word_cfg("b")]))) - ); - assert_eq!( - !Cfg::Any(vec![word_cfg("a"), word_cfg("b")]), - Cfg::Not(Box::new(Cfg::Any(vec![word_cfg("a"), word_cfg("b")]))) - ); - assert_eq!(!Cfg::Not(Box::new(word_cfg("test"))), word_cfg("test")); + with_globals(|| { + assert_eq!(!Cfg::False, Cfg::True); + assert_eq!(!Cfg::True, Cfg::False); + assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test")))); + assert_eq!( + !Cfg::All(vec![word_cfg("a"), word_cfg("b")]), + Cfg::Not(Box::new(Cfg::All(vec![word_cfg("a"), word_cfg("b")]))) + ); + assert_eq!( + !Cfg::Any(vec![word_cfg("a"), word_cfg("b")]), + Cfg::Not(Box::new(Cfg::Any(vec![word_cfg("a"), word_cfg("b")]))) + ); + assert_eq!(!Cfg::Not(Box::new(word_cfg("test"))), word_cfg("test")); + }) } #[test] fn test_cfg_and() { - let mut x = Cfg::False; - x &= Cfg::True; - assert_eq!(x, Cfg::False); + with_globals(|| { + let mut x = Cfg::False; + x &= Cfg::True; + assert_eq!(x, Cfg::False); - x = word_cfg("test"); - x &= Cfg::False; - assert_eq!(x, Cfg::False); + x = word_cfg("test"); + x &= Cfg::False; + assert_eq!(x, Cfg::False); - x = word_cfg("test2"); - x &= Cfg::True; - assert_eq!(x, word_cfg("test2")); + x = word_cfg("test2"); + x &= Cfg::True; + assert_eq!(x, word_cfg("test2")); - x = Cfg::True; - x &= word_cfg("test3"); - assert_eq!(x, word_cfg("test3")); + x = Cfg::True; + x &= word_cfg("test3"); + assert_eq!(x, word_cfg("test3")); - x &= word_cfg("test4"); - assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")])); + x &= word_cfg("test4"); + assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")])); - x &= word_cfg("test5"); - assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")])); + x &= word_cfg("test5"); + assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")])); - x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]); - assert_eq!(x, Cfg::All(vec![ - word_cfg("test3"), - word_cfg("test4"), - word_cfg("test5"), - word_cfg("test6"), - word_cfg("test7"), - ])); + x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]); + assert_eq!(x, Cfg::All(vec![ + word_cfg("test3"), + word_cfg("test4"), + word_cfg("test5"), + word_cfg("test6"), + word_cfg("test7"), + ])); - let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]); - y &= x; - assert_eq!(y, Cfg::All(vec![ - word_cfg("test3"), - word_cfg("test4"), - word_cfg("test5"), - word_cfg("test6"), - word_cfg("test7"), - Cfg::Any(vec![word_cfg("a"), word_cfg("b")]), - ])); + let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]); + y &= x; + assert_eq!(y, Cfg::All(vec![ + word_cfg("test3"), + word_cfg("test4"), + word_cfg("test5"), + word_cfg("test6"), + word_cfg("test7"), + Cfg::Any(vec![word_cfg("a"), word_cfg("b")]), + ])); - assert_eq!( - word_cfg("a") & word_cfg("b") & word_cfg("c"), - Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")]) - ); + assert_eq!( + word_cfg("a") & word_cfg("b") & word_cfg("c"), + Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")]) + ); + }) } #[test] fn test_cfg_or() { - let mut x = Cfg::True; - x |= Cfg::False; - assert_eq!(x, Cfg::True); + with_globals(|| { + let mut x = Cfg::True; + x |= Cfg::False; + assert_eq!(x, Cfg::True); - x = word_cfg("test"); - x |= Cfg::True; - assert_eq!(x, Cfg::True); + x = word_cfg("test"); + x |= Cfg::True; + assert_eq!(x, Cfg::True); - x = word_cfg("test2"); - x |= Cfg::False; - assert_eq!(x, word_cfg("test2")); + x = word_cfg("test2"); + x |= Cfg::False; + assert_eq!(x, word_cfg("test2")); - x = Cfg::False; - x |= word_cfg("test3"); - assert_eq!(x, word_cfg("test3")); + x = Cfg::False; + x |= word_cfg("test3"); + assert_eq!(x, word_cfg("test3")); - x |= word_cfg("test4"); - assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")])); + x |= word_cfg("test4"); + assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")])); - x |= word_cfg("test5"); - assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")])); + x |= word_cfg("test5"); + assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")])); - x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]); - assert_eq!(x, Cfg::Any(vec![ - word_cfg("test3"), - word_cfg("test4"), - word_cfg("test5"), - word_cfg("test6"), - word_cfg("test7"), - ])); + x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]); + assert_eq!(x, Cfg::Any(vec![ + word_cfg("test3"), + word_cfg("test4"), + word_cfg("test5"), + word_cfg("test6"), + word_cfg("test7"), + ])); - let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]); - y |= x; - assert_eq!(y, Cfg::Any(vec![ - word_cfg("test3"), - word_cfg("test4"), - word_cfg("test5"), - word_cfg("test6"), - word_cfg("test7"), - Cfg::All(vec![word_cfg("a"), word_cfg("b")]), - ])); + let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]); + y |= x; + assert_eq!(y, Cfg::Any(vec![ + word_cfg("test3"), + word_cfg("test4"), + word_cfg("test5"), + word_cfg("test6"), + word_cfg("test7"), + Cfg::All(vec![word_cfg("a"), word_cfg("b")]), + ])); - assert_eq!( - word_cfg("a") | word_cfg("b") | word_cfg("c"), - Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")]) - ); + assert_eq!( + word_cfg("a") | word_cfg("b") | word_cfg("c"), + Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")]) + ); + }) } #[test] fn test_parse_ok() { - let mi = MetaItem { - name: Symbol::intern("all"), - node: MetaItemKind::Word, - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); + with_globals(|| { + let mi = MetaItem { + name: Symbol::intern("all"), + node: MetaItemKind::Word, + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); - let mi = MetaItem { - name: Symbol::intern("all"), - node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str( - Symbol::intern("done"), - StrStyle::Cooked, - ))), - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); + let mi = MetaItem { + name: Symbol::intern("all"), + node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str( + Symbol::intern("done"), + StrStyle::Cooked, + ))), + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); - let mi = MetaItem { - name: Symbol::intern("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b"))); + let mi = MetaItem { + name: Symbol::intern("all"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("b"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b"))); - let mi = MetaItem { - name: Symbol::intern("any"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b"))); + let mi = MetaItem { + name: Symbol::intern("any"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("b"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b"))); - let mi = MetaItem { - name: Symbol::intern("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a"))); + let mi = MetaItem { + name: Symbol::intern("not"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a"))); - let mi = MetaItem { - name: Symbol::intern("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("any"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("c"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c"))))); + let mi = MetaItem { + name: Symbol::intern("not"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("any"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("all"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("b"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("c"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c"))))); - let mi = MetaItem { - name: Symbol::intern("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("c"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c"))); + let mi = MetaItem { + name: Symbol::intern("all"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("b"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("c"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c"))); + }) } #[test] fn test_parse_err() { - let mi = MetaItem { - name: Symbol::intern("foo"), - node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + with_globals(|| { + let mi = MetaItem { + name: Symbol::intern("foo"), + node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - name: Symbol::intern("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + let mi = MetaItem { + name: Symbol::intern("not"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("b"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - name: Symbol::intern("not"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + let mi = MetaItem { + name: Symbol::intern("not"), + node: MetaItemKind::List(vec![]), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - name: Symbol::intern("foo"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + let mi = MetaItem { + name: Symbol::intern("foo"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - name: Symbol::intern("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("foo"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + let mi = MetaItem { + name: Symbol::intern("all"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("foo"), + node: MetaItemKind::List(vec![]), + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("b"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - name: Symbol::intern("any"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("foo"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + let mi = MetaItem { + name: Symbol::intern("any"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("a"), + node: MetaItemKind::Word, + span: DUMMY_SP, + })), + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("foo"), + node: MetaItemKind::List(vec![]), + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - name: Symbol::intern("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - name: Symbol::intern("foo"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; - assert!(Cfg::parse(&mi).is_err()); + let mi = MetaItem { + name: Symbol::intern("not"), + node: MetaItemKind::List(vec![ + dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { + name: Symbol::intern("foo"), + node: MetaItemKind::List(vec![]), + span: DUMMY_SP, + })), + ]), + span: DUMMY_SP, + }; + assert!(Cfg::parse(&mi).is_err()); + }) } #[test] fn test_render_short_html() { - assert_eq!( - word_cfg("unix").render_short_html(), - "Unix" - ); - assert_eq!( - name_value_cfg("target_os", "macos").render_short_html(), - "macOS" - ); - assert_eq!( - name_value_cfg("target_pointer_width", "16").render_short_html(), - "16-bit" - ); - assert_eq!( - name_value_cfg("target_endian", "little").render_short_html(), - "Little-endian" - ); - assert_eq!( - (!word_cfg("windows")).render_short_html(), - "Non-Windows" - ); - assert_eq!( - (word_cfg("unix") & word_cfg("windows")).render_short_html(), - "Unix and Windows" - ); - assert_eq!( - (word_cfg("unix") | word_cfg("windows")).render_short_html(), - "Unix or Windows" - ); - assert_eq!( - ( - word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions") - ).render_short_html(), - "Unix and Windows and debug-assertions enabled" - ); - assert_eq!( - ( - word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions") - ).render_short_html(), - "Unix or Windows or debug-assertions enabled" - ); - assert_eq!( - ( - !(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")) - ).render_short_html(), - "Neither Unix nor Windows nor debug-assertions enabled" - ); - assert_eq!( - ( - (word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) | - (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")) - ).render_short_html(), - "Unix and x86-64, or Windows and 64-bit" - ); - assert_eq!( - (!(word_cfg("unix") & word_cfg("windows"))).render_short_html(), - "Not (Unix and Windows)" - ); - assert_eq!( - ( - (word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix") - ).render_short_html(), - "(Debug-assertions enabled or Windows) and Unix" - ); + with_globals(|| { + assert_eq!( + word_cfg("unix").render_short_html(), + "Unix" + ); + assert_eq!( + name_value_cfg("target_os", "macos").render_short_html(), + "macOS" + ); + assert_eq!( + name_value_cfg("target_pointer_width", "16").render_short_html(), + "16-bit" + ); + assert_eq!( + name_value_cfg("target_endian", "little").render_short_html(), + "Little-endian" + ); + assert_eq!( + (!word_cfg("windows")).render_short_html(), + "Non-Windows" + ); + assert_eq!( + (word_cfg("unix") & word_cfg("windows")).render_short_html(), + "Unix and Windows" + ); + assert_eq!( + (word_cfg("unix") | word_cfg("windows")).render_short_html(), + "Unix or Windows" + ); + assert_eq!( + ( + word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions") + ).render_short_html(), + "Unix and Windows and debug-assertions enabled" + ); + assert_eq!( + ( + word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions") + ).render_short_html(), + "Unix or Windows or debug-assertions enabled" + ); + assert_eq!( + ( + !(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")) + ).render_short_html(), + "Neither Unix nor Windows nor debug-assertions enabled" + ); + assert_eq!( + ( + (word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) | + (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")) + ).render_short_html(), + "Unix and x86-64, or Windows and 64-bit" + ); + assert_eq!( + (!(word_cfg("unix") & word_cfg("windows"))).render_short_html(), + "Not (Unix and Windows)" + ); + assert_eq!( + ( + (word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix") + ).render_short_html(), + "(Debug-assertions enabled or Windows) and Unix" + ); + assert_eq!( + name_value_cfg("target_feature", "sse2").render_short_html(), + "sse2" + ); + }) } #[test] fn test_render_long_html() { - assert_eq!( - word_cfg("unix").render_long_html(), - "This is supported on Unix only." - ); - assert_eq!( - name_value_cfg("target_os", "macos").render_long_html(), - "This is supported on macOS only." - ); - assert_eq!( - name_value_cfg("target_pointer_width", "16").render_long_html(), - "This is supported on 16-bit only." - ); - assert_eq!( - name_value_cfg("target_endian", "little").render_long_html(), - "This is supported on little-endian only." - ); - assert_eq!( - (!word_cfg("windows")).render_long_html(), - "This is supported on non-Windows only." - ); - assert_eq!( - (word_cfg("unix") & word_cfg("windows")).render_long_html(), - "This is supported on Unix and Windows only." - ); - assert_eq!( - (word_cfg("unix") | word_cfg("windows")).render_long_html(), - "This is supported on Unix or Windows only." - ); - assert_eq!( - ( - word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions") - ).render_long_html(), - "This is supported on Unix and Windows and debug-assertions enabled \ - only." - ); - assert_eq!( - ( - word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions") - ).render_long_html(), - "This is supported on Unix or Windows or debug-assertions enabled \ - only." - ); - assert_eq!( - ( - !(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")) - ).render_long_html(), - "This is supported on neither Unix nor Windows nor debug-assertions \ - enabled." - ); - assert_eq!( - ( - (word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) | - (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")) - ).render_long_html(), - "This is supported on Unix and x86-64, or Windows and 64-bit only." - ); - assert_eq!( - (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(), - "This is supported on not (Unix and Windows)." - ); - assert_eq!( - ( - (word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix") - ).render_long_html(), - "This is supported on (debug-assertions enabled or Windows) and Unix \ - only." - ); + with_globals(|| { + assert_eq!( + word_cfg("unix").render_long_html(), + "This is supported on Unix only." + ); + assert_eq!( + name_value_cfg("target_os", "macos").render_long_html(), + "This is supported on macOS only." + ); + assert_eq!( + name_value_cfg("target_pointer_width", "16").render_long_html(), + "This is supported on 16-bit only." + ); + assert_eq!( + name_value_cfg("target_endian", "little").render_long_html(), + "This is supported on little-endian only." + ); + assert_eq!( + (!word_cfg("windows")).render_long_html(), + "This is supported on non-Windows only." + ); + assert_eq!( + (word_cfg("unix") & word_cfg("windows")).render_long_html(), + "This is supported on Unix and Windows only." + ); + assert_eq!( + (word_cfg("unix") | word_cfg("windows")).render_long_html(), + "This is supported on Unix or Windows only." + ); + assert_eq!( + ( + word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions") + ).render_long_html(), + "This is supported on Unix and Windows and debug-assertions enabled\ + only." + ); + assert_eq!( + ( + word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions") + ).render_long_html(), + "This is supported on Unix or Windows or debug-assertions enabled\ + only." + ); + assert_eq!( + ( + !(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")) + ).render_long_html(), + "This is supported on neither Unix nor Windows nor debug-assertions \ + enabled." + ); + assert_eq!( + ( + (word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) | + (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")) + ).render_long_html(), + "This is supported on Unix and x86-64, or Windows and 64-bit \ + only." + ); + assert_eq!( + (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(), + "This is supported on not (Unix and Windows)." + ); + assert_eq!( + ( + (word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix") + ).render_long_html(), + "This is supported on (debug-assertions enabled or Windows) and Unix\ + only." + ); + assert_eq!( + name_value_cfg("target_feature", "sse2").render_long_html(), + "This is supported with target feature sse2 only." + ); + }) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5d4addce2c43..6ada4ccfbddc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -19,6 +19,7 @@ pub use self::SelfTy::*; pub use self::FunctionRetTy::*; pub use self::Visibility::*; +use syntax; use syntax::abi::Abi; use syntax::ast::{self, AttrStyle}; use syntax::attr; @@ -64,6 +65,7 @@ use std::u32; use core::{self, DocContext}; use doctree; use visit_ast; +use html::render::{cache, ExternalLocation}; use html::item_type::ItemType; use html::markdown::markdown_links; @@ -346,7 +348,7 @@ impl Item { } pub fn links(&self) -> Vec<(String, String)> { - self.attrs.links() + self.attrs.links(&self.def_id.krate) } pub fn is_crate(&self) -> bool { @@ -602,6 +604,11 @@ impl<'a> Iterator for ListAttributesIter<'a> { None } + + fn size_hint(&self) -> (usize, Option) { + let lower = self.current_list.len(); + (lower, None) + } } pub trait AttributesExt { @@ -697,7 +704,7 @@ pub struct Attributes { pub cfg: Option>, pub span: Option, /// map from Rust paths to resolved defs and potential URL fragments - pub links: Vec<(String, DefId, Option)>, + pub links: Vec<(String, Option, Option)>, } impl Attributes { @@ -828,6 +835,19 @@ impl Attributes { }) }).collect(); + // treat #[target_feature(enable = "feat")] attributes as if they were + // #[doc(cfg(target_feature = "feat"))] attributes as well + for attr in attrs.lists("target_feature") { + if attr.check_name("enable") { + if let Some(feat) = attr.value_str() { + let meta = attr::mk_name_value_item_str("target_feature".into(), feat); + if let Ok(feat_cfg) = Cfg::parse(&meta) { + cfg &= feat_cfg; + } + } + } + } + Attributes { doc_strings, other_attrs, @@ -856,17 +876,41 @@ impl Attributes { /// Get links as a vector /// /// Cache must be populated before call - pub fn links(&self) -> Vec<(String, String)> { + pub fn links(&self, krate: &CrateNum) -> Vec<(String, String)> { use html::format::href; self.links.iter().filter_map(|&(ref s, did, ref fragment)| { - if let Some((mut href, ..)) = href(did) { - if let Some(ref fragment) = *fragment { - href.push_str("#"); - href.push_str(fragment); + match did { + Some(did) => { + if let Some((mut href, ..)) = href(did) { + if let Some(ref fragment) = *fragment { + href.push_str("#"); + href.push_str(fragment); + } + Some((s.clone(), href)) + } else { + None + } + } + None => { + if let Some(ref fragment) = *fragment { + let cache = cache(); + let url = match cache.extern_locations.get(krate) { + Some(&(_, ref src, ExternalLocation::Local)) => + src.to_str().expect("invalid file path"), + Some(&(_, _, ExternalLocation::Remote(ref s))) => s, + Some(&(_, _, ExternalLocation::Unknown)) | None => + "https://doc.rust-lang.org/nightly", + }; + // This is a primitive so the url is done "by hand". + Some((s.clone(), + format!("{}{}std/primitive.{}.html", + url, + if !url.ends_with('/') { "/" } else { "" }, + fragment))) + } else { + panic!("This isn't a primitive?!"); + } } - Some((s.clone(), href)) - } else { - None } }).collect() } @@ -929,7 +973,7 @@ fn ambiguity_error(cx: &DocContext, attrs: &Attributes, select the {}", disambig1, kind1, disambig2, kind2)) - .emit(); + .emit(); } /// Given an enum variant's def, return the def of its enum and the associated fragment @@ -946,6 +990,34 @@ fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option), () Ok((parent_def, Some(format!("{}.v", variant.name)))) } +const PRIMITIVES: &[(&str, Def)] = &[ + ("u8", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U8))), + ("u16", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U16))), + ("u32", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U32))), + ("u64", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U64))), + ("u128", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::U128))), + ("usize", Def::PrimTy(hir::PrimTy::TyUint(syntax::ast::UintTy::Usize))), + ("i8", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I8))), + ("i16", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I16))), + ("i32", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I32))), + ("i64", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I64))), + ("i128", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::I128))), + ("isize", Def::PrimTy(hir::PrimTy::TyInt(syntax::ast::IntTy::Isize))), + ("f32", Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F32))), + ("f64", Def::PrimTy(hir::PrimTy::TyFloat(syntax::ast::FloatTy::F64))), + ("str", Def::PrimTy(hir::PrimTy::TyStr)), + ("bool", Def::PrimTy(hir::PrimTy::TyBool)), + ("char", Def::PrimTy(hir::PrimTy::TyChar)), +]; + +fn is_primitive(path_str: &str, is_val: bool) -> Option { + if is_val { + None + } else { + PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1) + } +} + /// Resolve a given string as a path, along with whether or not it is /// in the value namespace. Also returns an optional URL fragment in the case /// of variants and methods @@ -974,6 +1046,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option if value != is_val { return Err(()) } + } else if let Some(prim) = is_primitive(path_str, is_val) { + return Ok((prim, Some(path_str.to_owned()))) } else { // If resolution failed, it may still be a method // because methods are not handled by the resolver @@ -1000,8 +1074,7 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option let ty = cx.resolver.borrow_mut() .with_scope(*id, |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, - &path, false) + resolver.resolve_str_path_error(DUMMY_SP, &path, false) })?; match ty.def { Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => { @@ -1009,13 +1082,34 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option .flat_map(|imp| cx.tcx.associated_items(*imp)) .find(|item| item.name == item_name); if let Some(item) = item { - if item.kind == ty::AssociatedKind::Method && is_val { - Ok((ty.def, Some(format!("method.{}", item_name)))) + let out = match item.kind { + ty::AssociatedKind::Method if is_val => "method", + ty::AssociatedKind::Const if is_val => "associatedconstant", + _ => return Err(()) + }; + Ok((ty.def, Some(format!("{}.{}", out, item_name)))) + } else { + let is_enum = match ty.def { + Def::Enum(_) => true, + _ => false, + }; + let elem = if is_enum { + cx.tcx.adt_def(did).all_fields().find(|item| item.name == item_name) + } else { + cx.tcx.adt_def(did) + .non_enum_variant() + .fields + .iter() + .find(|item| item.name == item_name) + }; + if let Some(item) = elem { + Ok((ty.def, + Some(format!("{}.{}", + if is_enum { "variant" } else { "structfield" }, + item.name)))) } else { Err(()) } - } else { - Err(()) } } Def::Trait(did) => { @@ -1026,7 +1120,13 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option let kind = match item.kind { ty::AssociatedKind::Const if is_val => "associatedconstant", ty::AssociatedKind::Type if !is_val => "associatedtype", - ty::AssociatedKind::Method if is_val => "tymethod", + ty::AssociatedKind::Method if is_val => { + if item.defaultness.has_value() { + "method" + } else { + "tymethod" + } + } _ => return Err(()) }; @@ -1037,7 +1137,6 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option } _ => Err(()) } - } else { Err(()) } @@ -1074,6 +1173,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { } } +#[derive(Debug)] enum PathKind { /// can be either value or type, not a macro Unknown, @@ -1082,7 +1182,7 @@ enum PathKind { /// values, functions, consts, statics, everything in the value namespace Value, /// types, traits, everything in the type namespace - Type + Type, } impl Clean for [ast::Attribute] { @@ -1091,12 +1191,13 @@ impl Clean for [ast::Attribute] { if UnstableFeatures::from_environment().is_nightly_build() { let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new); - for link in markdown_links(&dox) { + for ori_link in markdown_links(&dox) { // bail early for real links - if link.contains('/') { + if ori_link.contains('/') { continue; } - let (def, fragment) = { + let link = ori_link.replace("`", ""); + let (def, fragment) = { let mut kind = PathKind::Unknown; let path_str = if let Some(prefix) = ["struct@", "enum@", "type@", @@ -1124,15 +1225,11 @@ impl Clean for [ast::Attribute] { &link[..] }.trim(); - // avoid resolving things (i.e. regular links) which aren't like paths - // FIXME(Manishearth) given that most links have slashes in them might be worth - // doing a check for slashes first if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ch == ':' || ch == '_')) { continue; } - match kind { PathKind::Value => { if let Ok(def) = resolve(cx, path_str, true) { @@ -1206,9 +1303,12 @@ impl Clean for [ast::Attribute] { } }; - - let id = register_def(cx, def); - attrs.links.push((link, id, fragment)); + if let Def::PrimTy(_) = def { + attrs.links.push((ori_link, None, fragment)); + } else { + let id = register_def(cx, def); + attrs.links.push((ori_link, Some(id), fragment)); + } } cx.sess().abort_if_errors(); @@ -1224,6 +1324,7 @@ pub struct TyParam { pub did: DefId, pub bounds: Vec, pub default: Option, + pub synthetic: Option, } impl Clean for hir::TyParam { @@ -1233,6 +1334,7 @@ impl Clean for hir::TyParam { did: cx.tcx.hir.local_def_id(self.id), bounds: self.bounds.clean(cx), default: self.default.clean(cx), + synthetic: self.synthetic, } } } @@ -1248,7 +1350,8 @@ impl<'tcx> Clean for ty::TypeParameterDef { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None - } + }, + synthetic: None, } } } @@ -1322,7 +1425,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => { assert_eq!(types.len(), 1); let inputs = match types[0].sty { - ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(), + ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { return PathParameters::AngleBracketed { lifetimes, @@ -1334,7 +1437,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo let output = None; // FIXME(#20299) return type comes from a projection now // match types[1].sty { - // ty::TyTuple(ref v, _) if v.is_empty() => None, // -> () + // ty::TyTuple(ref v) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; PathParameters::Parenthesized { @@ -1366,18 +1469,19 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self } } -impl<'tcx> Clean for ty::TraitRef<'tcx> { +impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec) { fn clean(&self, cx: &DocContext) -> TyParamBound { - inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); - let path = external_path(cx, &cx.tcx.item_name(self.def_id), - Some(self.def_id), true, vec![], self.substs); + let (trait_ref, ref bounds) = *self; + inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); + let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id), + Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs); - debug!("ty::TraitRef\n subst: {:?}\n", self.substs); + debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); // collect any late bound regions let mut late_bounds = vec![]; - for ty_s in self.input_types().skip(1) { - if let ty::TyTuple(ts, _) = ty_s.sty { + for ty_s in trait_ref.input_types().skip(1) { + if let ty::TyTuple(ts) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { if let &ty::RegionKind::ReLateBound(..) = *reg { @@ -1396,7 +1500,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { trait_: ResolvedPath { path, typarams: None, - did: self.def_id, + did: trait_ref.def_id, is_generic: false, }, generic_params: late_bounds, @@ -1406,6 +1510,12 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { } } +impl<'tcx> Clean for ty::TraitRef<'tcx> { + fn clean(&self, cx: &DocContext) -> TyParamBound { + (self, vec![]).clean(cx) + } +} + impl<'tcx> Clean>> for Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); @@ -1490,6 +1600,7 @@ impl Clean> for ty::RegionKind { ty::ReSkolemized(..) | ty::ReEmpty | ty::ReClosureBound(_) | + ty::ReCanonical(_) | ty::ReErased => None } } @@ -1615,6 +1726,16 @@ pub enum GenericParam { Type(TyParam), } +impl GenericParam { + pub fn is_synthetic_type_param(&self) -> bool { + if let GenericParam::Type(ref t) = *self { + t.synthetic.is_some() + } else { + false + } + } +} + impl Clean for hir::GenericParam { fn clean(&self, cx: &DocContext) -> GenericParam { match *self { @@ -1747,11 +1868,12 @@ pub struct Method { impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { fn clean(&self, cx: &DocContext) -> Method { + let generics = self.1.clean(cx); Method { - generics: self.1.clean(cx), + decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)), + generics, unsafety: self.0.unsafety, constness: self.0.constness, - decl: (&*self.0.decl, self.2).clean(cx), abi: self.0.abi } } @@ -1776,6 +1898,8 @@ pub struct Function { impl Clean for doctree::Function { fn clean(&self, cx: &DocContext) -> Item { + let generics = self.generics.clean(cx); + let decl = enter_impl_trait(cx, &generics.params, || (&self.decl, self.body).clean(cx)); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -1785,8 +1909,8 @@ impl Clean for doctree::Function { deprecation: self.depr.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), inner: FunctionItem(Function { - decl: (&self.decl, self.body).clean(cx), - generics: self.generics.clean(cx), + decl, + generics, unsafety: self.unsafety, constness: self.constness, abi: self.abi, @@ -1871,7 +1995,8 @@ impl<'a, 'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { vec![].into_iter() } else { cx.tcx.fn_arg_names(did).into_iter() - }.peekable(); + }; + FnDecl { output: Return(sig.skip_binder().output().clean(cx)), attrs: Attributes::default(), @@ -2013,10 +2138,13 @@ impl Clean for hir::TraitItem { MethodItem((sig, &self.generics, body).clean(cx)) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { + let generics = self.generics.clean(cx); TyMethodItem(TyMethod { unsafety: sig.unsafety.clone(), - decl: (&*sig.decl, &names[..]).clean(cx), - generics: self.generics.clean(cx), + decl: enter_impl_trait(cx, &generics.params, || { + (&*sig.decl, &names[..]).clean(cx) + }), + generics, abi: sig.abi }) } @@ -2520,6 +2648,12 @@ impl Clean for hir::Ty { return new_ty; } + if let Def::TyParam(did) = path.def { + if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) { + return ImplTrait(bounds); + } + } + let mut alias = None; if let Def::TyAlias(def_id) = path.def { // Substitute private type aliases @@ -2730,7 +2864,7 @@ impl<'tcx> Clean for Ty<'tcx> { Never } } - ty::TyTuple(ref t, _) => Tuple(t.clean(cx)), + ty::TyTuple(ref t) => Tuple(t.clean(cx)), ty::TyProjection(ref data) => data.clean(cx), @@ -2742,9 +2876,51 @@ impl<'tcx> Clean for Ty<'tcx> { let predicates_of = cx.tcx.predicates_of(def_id); let substs = cx.tcx.lift(&substs).unwrap(); let bounds = predicates_of.instantiate(cx.tcx, substs); - ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| { - predicate.to_opt_poly_trait_ref().clean(cx) - }).collect()) + let mut regions = vec![]; + let mut has_sized = false; + let mut bounds = bounds.predicates.iter().filter_map(|predicate| { + let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() { + tr + } else if let ty::Predicate::TypeOutlives(pred) = *predicate { + // these should turn up at the end + pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r))); + return None; + } else { + return None; + }; + + if let Some(sized) = cx.tcx.lang_items().sized_trait() { + if trait_ref.def_id() == sized { + has_sized = true; + return None; + } + } + + + let bounds = bounds.predicates.iter().filter_map(|pred| + if let ty::Predicate::Projection(proj) = *pred { + let proj = proj.skip_binder(); + if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() { + Some(TypeBinding { + name: cx.tcx.associated_item(proj.projection_ty.item_def_id) + .name.clean(cx), + ty: proj.ty.clean(cx), + }) + } else { + None + } + } else { + None + } + ).collect(); + + Some((trait_ref.skip_binder(), bounds).clean(cx)) + }).collect::>(); + bounds.extend(regions); + if !has_sized && !bounds.is_empty() { + bounds.insert(0, TyParamBound::maybe_sized(cx)); + } + ImplTrait(bounds) } ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton) @@ -3232,10 +3408,13 @@ pub struct BareFunctionDecl { impl Clean for hir::BareFnTy { fn clean(&self, cx: &DocContext) -> BareFunctionDecl { + let generic_params = self.generic_params.clean(cx); BareFunctionDecl { unsafety: self.unsafety, - generic_params: self.generic_params.clean(cx), - decl: (&*self.decl, &self.arg_names[..]).clean(cx), + decl: enter_impl_trait(cx, &generic_params, || { + (&*self.decl, &self.arg_names[..]).clean(cx) + }), + generic_params, abi: self.abi, } } @@ -3536,9 +3715,12 @@ impl Clean for hir::ForeignItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { hir::ForeignItemFn(ref decl, ref names, ref generics) => { + let generics = generics.clean(cx); ForeignFunctionItem(Function { - decl: (&**decl, &names[..]).clean(cx), - generics: generics.clean(cx), + decl: enter_impl_trait(cx, &generics.params, || { + (&**decl, &names[..]).clean(cx) + }), + generics, unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, constness: hir::Constness::NotConst, @@ -3840,6 +4022,29 @@ pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option) -> Vec< once(crate_name).chain(relative).collect() } +pub fn enter_impl_trait(cx: &DocContext, gps: &[GenericParam], f: F) -> R +where + F: FnOnce() -> R, +{ + let bounds = gps.iter() + .filter_map(|p| { + if let GenericParam::Type(ref tp) = *p { + if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { + return Some((tp.did, tp.bounds.clone())); + } + } + + None + }) + .collect::>>(); + + let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), bounds); + let r = f(); + assert!(cx.impl_trait_bounds.borrow().is_empty()); + *cx.impl_trait_bounds.borrow_mut() = old_bounds; + r +} + // Start of code copied from rust-clippy pub fn get_trait_def_id(tcx: &TyCtxt, path: &[&str], use_local: bool) -> Option { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1e0fafc8d9df..6e2be2610cec 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -22,9 +22,11 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_resolve as resolve; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; +use rustc_back::target::TargetTriple; use syntax::ast::NodeId; use syntax::codemap; +use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; use errors; use errors::emitter::ColorConfig; @@ -72,6 +74,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { pub ty_substs: RefCell>, /// Table node id of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell>, + /// Table DefId of `impl Trait` in argument position -> bounds + pub impl_trait_bounds: RefCell>>, pub send_trait: Option, pub fake_def_ids: RefCell>, pub all_fake_def_ids: RefCell>, @@ -116,11 +120,12 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: config::Externs, input: Input, - triple: Option, + triple: Option, maybe_sysroot: Option, allow_warnings: bool, crate_name: Option, - force_unstable_if_unmarked: bool) -> (clean::Crate, RenderInfo) + force_unstable_if_unmarked: bool, + edition: Edition) -> (clean::Crate, RenderInfo) { // Parse, resolve, and typecheck the given crate. @@ -131,6 +136,7 @@ pub fn run_core(search_paths: SearchPaths, let warning_lint = lint::builtin::WARNINGS.name_lower(); + let host_triple = TargetTriple::from_triple(config::host_triple()); let sessopts = config::Options { maybe_sysroot, search_paths, @@ -138,12 +144,13 @@ pub fn run_core(search_paths: SearchPaths, lint_opts: if !allow_warnings { vec![(warning_lint, lint::Allow)] } else { vec![] }, lint_cap: Some(lint::Allow), externs, - target_triple: triple.unwrap_or(config::host_triple().to_string()), + target_triple: triple.unwrap_or(host_triple), // Ensure that rustdoc works even if rustc is feature-staged unstable_features: UnstableFeatures::Allow, actually_rustdoc: true, debugging_opts: config::DebuggingOptions { force_unstable_if_unmarked, + edition, ..config::basic_debugging_options() }, ..config::basic_options().clone() @@ -261,6 +268,7 @@ pub fn run_core(search_paths: SearchPaths, renderinfo: Default::default(), ty_substs: Default::default(), lt_substs: Default::default(), + impl_trait_bounds: Default::default(), mod_ids: Default::default(), send_trait: send_trait, fake_def_ids: RefCell::new(FxHashMap()), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 2913ea6a78ec..0a7e19fc643f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -148,11 +148,17 @@ impl fmt::Display for clean::GenericParam { impl fmt::Display for clean::Generics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.params.is_empty() { return Ok(()) } + let real_params = self.params + .iter() + .filter(|p| !p.is_synthetic_type_param()) + .collect::>(); + if real_params.is_empty() { + return Ok(()); + } if f.alternate() { - write!(f, "<{:#}>", CommaSep(&self.params)) + write!(f, "<{:#}>", CommaSep(&real_params)) } else { - write!(f, "<{}>", CommaSep(&self.params)) + write!(f, "<{}>", CommaSep(&real_params)) } } } @@ -575,7 +581,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - fmt::Display::fmt(&CommaSep(&many), f)?; + fmt::Display::fmt(&CommaSep(many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } } @@ -661,18 +667,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } } clean::ImplTrait(ref bounds) => { - write!(f, "impl ")?; - for (i, bound) in bounds.iter().enumerate() { - if i != 0 { - write!(f, " + ")?; - } - if f.alternate() { - write!(f, "{:#}", *bound)?; - } else { - write!(f, "{}", *bound)?; - } - } - Ok(()) + write!(f, "impl {}", TyParamBounds(bounds)) } clean::QPath { ref name, ref self_type, ref trait_ } => { let should_show_cast = match *trait_ { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index ef01c3e6bdb0..cfa3f5a4e0b4 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -323,12 +323,12 @@ impl<'a> Classifier<'a> { } // Keywords are also included in the identifier set. - token::Ident(ident) => { + token::Ident(ident, is_raw) => { match &*ident.name.as_str() { - "ref" | "mut" => Class::RefKeyWord, + "ref" | "mut" if !is_raw => Class::RefKeyWord, - "self" |"Self" => Class::Self_, - "false" | "true" => Class::Bool, + "self" | "Self" => Class::Self_, + "false" | "true" if !is_raw => Class::Bool, "Option" | "Result" => Class::PreludeTy, "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, @@ -352,7 +352,7 @@ impl<'a> Classifier<'a> { token::Lifetime(..) => Class::Lifetime, - token::Underscore | token::Eof | token::Interpolated(..) | + token::Eof | token::Interpolated(..) | token::Tilde | token::At | token::DotEq => Class::None, }; diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 0151a8c3ab71..aac5d0d2601d 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -53,7 +53,7 @@ r##" id="mainThemeStyle"> {themes} - + {css_extension} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ae28e5a0923e..c09bd4cc84ae 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -21,12 +21,13 @@ //! use rustdoc::html::markdown::Markdown; //! //! let s = "My *markdown* _text_"; -//! let html = format!("{}", Markdown(s)); +//! let html = format!("{}", Markdown(s, &[])); //! // ... something using html //! ``` #![allow(non_camel_case_types)] +use rustc::session; use std::cell::RefCell; use std::collections::{HashMap, VecDeque}; use std::default::Default; @@ -232,14 +233,14 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { /// Make headings links with anchor ids and build up TOC. struct LinkReplacer<'a, 'b, I: Iterator>> { inner: I, - links: &'b [(String, String)] + links: &'b [(String, String)], } impl<'a, 'b, I: Iterator>> LinkReplacer<'a, 'b, I> { fn new(iter: I, links: &'b [(String, String)]) -> Self { LinkReplacer { inner: iter, - links + links, } } } @@ -434,7 +435,8 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { } } -pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) { +pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span, + sess: Option<&session::Session>) { tests.set_position(position); let mut parser = Parser::new(doc); @@ -484,6 +486,9 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp line, filename, block_info.allow_fail); prev_offset = offset; } else { + if let Some(ref sess) = sess { + sess.span_warn(position, "invalid start of a new code block"); + } break; } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3750faec801a..8e6dcf8caf48 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -129,8 +129,8 @@ pub struct SharedContext { pub sort_modules_alphabetically: bool, /// Additional themes to be added to the generated docs. pub themes: Vec, - /// Suffix to be added on resource files (if suffix is "-v2" then "main.css" becomes - /// "main-v2.css"). + /// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes + /// "light-v2.css"). pub resource_suffix: String, } @@ -743,7 +743,7 @@ fn write_shared(cx: &Context, write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)), include_bytes!("static/rustdoc.css"))?; - // To avoid "main.css" to be overwritten, we'll first run over the received themes and only + // To avoid "light.css" to be overwritten, we'll first run over the received themes and only // then we'll run over the "official" styles. let mut themes: HashSet = HashSet::new(); @@ -761,9 +761,9 @@ fn write_shared(cx: &Context, write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)), include_bytes!("static/brush.svg"))?; - write(cx.dst.join(&format!("main{}.css", cx.shared.resource_suffix)), - include_bytes!("static/themes/main.css"))?; - themes.insert("main".to_owned()); + write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)), + include_bytes!("static/themes/light.css"))?; + themes.insert("light".to_owned()); write(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)), include_bytes!("static/themes/dark.css"))?; themes.insert("dark".to_owned()); @@ -1067,7 +1067,7 @@ impl<'a> SourceCollector<'a> { return Ok(()); } - let contents = fs::read_string(&p)?; + let contents = fs::read_to_string(&p)?; // Remove the utf-8 BOM if any let contents = if contents.starts_with("\u{feff}") { @@ -1675,11 +1675,19 @@ impl<'a> Item<'a> { } } +fn wrap_into_docblock(w: &mut fmt::Formatter, + f: F) -> fmt::Result +where F: Fn(&mut fmt::Formatter) -> fmt::Result { + write!(w, "
")?; + f(w)?; + write!(w, "
") +} + impl<'a> fmt::Display for Item<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { debug_assert!(!self.item.is_stripped()); // Write the breadcrumb trail header for the top - write!(fmt, "\n

")?; + write!(fmt, "

")?; match self.item.inner { clean::ModuleItem(ref m) => if m.is_crate { write!(fmt, "Crate ")?; @@ -1741,14 +1749,11 @@ impl<'a> fmt::Display for Item<'a> { } } - write!(fmt, "")?; // out-of-band - - write!(fmt, "

\n")?; + write!(fmt, "

")?; // out-of-band match self.item.inner { - clean::ModuleItem(ref m) => { - item_module(fmt, self.cx, self.item, &m.items) - } + clean::ModuleItem(ref m) => + item_module(fmt, self.cx, self.item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => item_function(fmt, self.cx, self.item, f), clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), @@ -2108,9 +2113,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -2160,7 +2171,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -2243,14 +2262,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> Result<(), fmt::Error> { - write!(w, "
  • ")?; - if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() { - write!(w, "
    ")?; - write!(w, "[src]", - l, "goto source code")?; - write!(w, "
    ")?; - } - write!(w, "")?; + write!(w, "
  • ")?; // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` let use_absolute = match implementor.inner_impl().for_ { @@ -2269,7 +2281,14 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter, write!(w, ";")?; } } - writeln!(w, "")?; + write!(w, "")?; + if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() { + write!(w, "
    ")?; + write!(w, "[src]", + l, "goto source code")?; + write!(w, "
    ")?; + } + writeln!(w, "
  • ")?; Ok(()) } @@ -2306,79 +2325,81 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } } - // Output the trait definition - write!(w, "
    ")?;
    -    render_attributes(w, it)?;
    -    write!(w, "{}{}{}trait {}{}{}",
    -           VisSpace(&it.visibility),
    -           UnsafetySpace(t.unsafety),
    -           if t.is_auto { "auto " } else { "" },
    -           it.name.as_ref().unwrap(),
    -           t.generics,
    -           bounds)?;
    -
    -    if !t.generics.where_predicates.is_empty() {
    -        write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true })?;
    -    } else {
    -        write!(w, " ")?;
    -    }
    -
         let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>();
         let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>();
         let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>();
         let provided = t.items.iter().filter(|m| m.is_method()).collect::>();
     
    -    if t.items.is_empty() {
    -        write!(w, "{{ }}")?;
    -    } else {
    -        // FIXME: we should be using a derived_id for the Anchors here
    -        write!(w, "{{\n")?;
    -        for t in &types {
    -            write!(w, "    ")?;
    -            render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -            write!(w, ";\n")?;
    -        }
    -        if !types.is_empty() && !consts.is_empty() {
    -            w.write_str("\n")?;
    -        }
    -        for t in &consts {
    -            write!(w, "    ")?;
    -            render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -            write!(w, ";\n")?;
    -        }
    -        if !consts.is_empty() && !required.is_empty() {
    -            w.write_str("\n")?;
    -        }
    -        for (pos, m) in required.iter().enumerate() {
    -            write!(w, "    ")?;
    -            render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
    -            write!(w, ";\n")?;
    +    // Output the trait definition
    +    wrap_into_docblock(w, |w| {
    +        write!(w, "
    ")?;
    +        render_attributes(w, it)?;
    +        write!(w, "{}{}{}trait {}{}{}",
    +               VisSpace(&it.visibility),
    +               UnsafetySpace(t.unsafety),
    +               if t.is_auto { "auto " } else { "" },
    +               it.name.as_ref().unwrap(),
    +               t.generics,
    +               bounds)?;
     
    -            if pos < required.len() - 1 {
    -               write!(w, "
    ")?; - } + if !t.generics.where_predicates.is_empty() { + write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true })?; + } else { + write!(w, " ")?; } - if !required.is_empty() && !provided.is_empty() { - w.write_str("\n")?; - } - for (pos, m) in provided.iter().enumerate() { - write!(w, " ")?; - render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; - match m.inner { - clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => { - write!(w, ",\n {{ ... }}\n")?; - }, - _ => { - write!(w, " {{ ... }}\n")?; - }, + + if t.items.is_empty() { + write!(w, "{{ }}")?; + } else { + // FIXME: we should be using a derived_id for the Anchors here + write!(w, "{{\n")?; + for t in &types { + write!(w, " ")?; + render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?; + write!(w, ";\n")?; } - if pos < provided.len() - 1 { - write!(w, "
    ")?; + if !types.is_empty() && !consts.is_empty() { + w.write_str("\n")?; } + for t in &consts { + write!(w, " ")?; + render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?; + write!(w, ";\n")?; + } + if !consts.is_empty() && !required.is_empty() { + w.write_str("\n")?; + } + for (pos, m) in required.iter().enumerate() { + write!(w, " ")?; + render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; + write!(w, ";\n")?; + + if pos < required.len() - 1 { + write!(w, "
    ")?; + } + } + if !required.is_empty() && !provided.is_empty() { + w.write_str("\n")?; + } + for (pos, m) in provided.iter().enumerate() { + write!(w, " ")?; + render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?; + match m.inner { + clean::MethodItem(ref inner) if !inner.generics.where_predicates.is_empty() => { + write!(w, ",\n {{ ... }}\n")?; + }, + _ => { + write!(w, " {{ ... }}\n")?; + }, + } + if pos < provided.len() - 1 { + write!(w, "
    ")?; + } + } + write!(w, "}}")?; } - write!(w, "}}")?; - } - write!(w, "
    ")?; + write!(w, "
    ") + })?; // Trait documentation document(w, cx, it)?; @@ -2717,16 +2738,18 @@ fn render_assoc_item(w: &mut fmt::Formatter, fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Struct) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it)?;
    -    render_struct(w,
    -                  it,
    -                  Some(&s.generics),
    -                  s.struct_type,
    -                  &s.fields,
    -                  "",
    -                  true)?;
    -    write!(w, "
    ")?; + wrap_into_docblock(w, |w| { + write!(w, "
    ")?;
    +        render_attributes(w, it)?;
    +        render_struct(w,
    +                      it,
    +                      Some(&s.generics),
    +                      s.struct_type,
    +                      &s.fields,
    +                      "",
    +                      true)?;
    +        write!(w, "
    ") + })?; document(w, cx, it)?; let mut fields = s.fields.iter().filter_map(|f| { @@ -2769,15 +2792,17 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Union) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it)?;
    -    render_union(w,
    -                 it,
    -                 Some(&s.generics),
    -                 &s.fields,
    -                 "",
    -                 true)?;
    -    write!(w, "
    ")?; + wrap_into_docblock(w, |w| { + write!(w, "
    ")?;
    +        render_attributes(w, it)?;
    +        render_union(w,
    +                     it,
    +                     Some(&s.generics),
    +                     &s.fields,
    +                     "",
    +                     true)?;
    +        write!(w, "
    ") + })?; document(w, cx, it)?; let mut fields = s.fields.iter().filter_map(|f| { @@ -2790,10 +2815,15 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, "

    Fields

    ")?; for (field, ty) in fields { - write!(w, "{name}: {ty} + let name = field.name.as_ref().expect("union field name"); + let id = format!("{}.{}", ItemType::StructField, name); + write!(w, "\ + \ + \ ", + id = id, + name = name, shortty = ItemType::StructField, - name = field.name.as_ref().unwrap(), ty = ty)?; if let Some(stability_class) = field.stability_class() { write!(w, "", @@ -2807,56 +2837,58 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, e: &clean::Enum) -> fmt::Result { - write!(w, "
    ")?;
    -    render_attributes(w, it)?;
    -    write!(w, "{}enum {}{}{}",
    -           VisSpace(&it.visibility),
    -           it.name.as_ref().unwrap(),
    -           e.generics,
    -           WhereClause { gens: &e.generics, indent: 0, end_newline: true })?;
    -    if e.variants.is_empty() && !e.variants_stripped {
    -        write!(w, " {{}}")?;
    -    } else {
    -        write!(w, " {{\n")?;
    -        for v in &e.variants {
    -            write!(w, "    ")?;
    -            let name = v.name.as_ref().unwrap();
    -            match v.inner {
    -                clean::VariantItem(ref var) => {
    -                    match var.kind {
    -                        clean::VariantKind::CLike => write!(w, "{}", name)?,
    -                        clean::VariantKind::Tuple(ref tys) => {
    -                            write!(w, "{}(", name)?;
    -                            for (i, ty) in tys.iter().enumerate() {
    -                                if i > 0 {
    -                                    write!(w, ", ")?
    +    wrap_into_docblock(w, |w| {
    +        write!(w, "
    ")?;
    +        render_attributes(w, it)?;
    +        write!(w, "{}enum {}{}{}",
    +               VisSpace(&it.visibility),
    +               it.name.as_ref().unwrap(),
    +               e.generics,
    +               WhereClause { gens: &e.generics, indent: 0, end_newline: true })?;
    +        if e.variants.is_empty() && !e.variants_stripped {
    +            write!(w, " {{}}")?;
    +        } else {
    +            write!(w, " {{\n")?;
    +            for v in &e.variants {
    +                write!(w, "    ")?;
    +                let name = v.name.as_ref().unwrap();
    +                match v.inner {
    +                    clean::VariantItem(ref var) => {
    +                        match var.kind {
    +                            clean::VariantKind::CLike => write!(w, "{}", name)?,
    +                            clean::VariantKind::Tuple(ref tys) => {
    +                                write!(w, "{}(", name)?;
    +                                for (i, ty) in tys.iter().enumerate() {
    +                                    if i > 0 {
    +                                        write!(w, ", ")?
    +                                    }
    +                                    write!(w, "{}", *ty)?;
                                     }
    -                                write!(w, "{}", *ty)?;
    +                                write!(w, ")")?;
    +                            }
    +                            clean::VariantKind::Struct(ref s) => {
    +                                render_struct(w,
    +                                              v,
    +                                              None,
    +                                              s.struct_type,
    +                                              &s.fields,
    +                                              "    ",
    +                                              false)?;
                                 }
    -                            write!(w, ")")?;
    -                        }
    -                        clean::VariantKind::Struct(ref s) => {
    -                            render_struct(w,
    -                                          v,
    -                                          None,
    -                                          s.struct_type,
    -                                          &s.fields,
    -                                          "    ",
    -                                          false)?;
                             }
                         }
    +                    _ => unreachable!()
                     }
    -                _ => unreachable!()
    +                write!(w, ",\n")?;
                 }
    -            write!(w, ",\n")?;
    -        }
     
    -        if e.variants_stripped {
    -            write!(w, "    // some variants omitted\n")?;
    +            if e.variants_stripped {
    +                write!(w, "    // some variants omitted\n")?;
    +            }
    +            write!(w, "}}")?;
             }
    -        write!(w, "}}")?;
    -    }
    -    write!(w, "
    ")?; + write!(w, "
    ") + })?; document(w, cx, it)?; if !e.variants.is_empty() { @@ -3181,14 +3213,16 @@ fn render_assoc_items(w: &mut fmt::Formatter, render_impls(cx, w, concrete, containing_item)?; write!(w, "")?; - write!(w, " -

    - Auto Trait Implementations -

    -
    - ")?; - render_impls(cx, w, synthetic, containing_item)?; - write!(w, "
    ")?; + if !synthetic.is_empty() { + write!(w, " +

    + Auto Trait Implementations +

    +
    + ")?; + render_impls(cx, w, synthetic, containing_item)?; + write!(w, "
    ")?; + } } Ok(()) } @@ -3312,10 +3346,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi Some(ref t) => format!("impl-{}", small_url_encode(&format!("{:#}", t))), None => "impl".to_string(), }); - write!(w, "

    {}", + write!(w, "

    \ +
    {}", id, i.inner_impl())?; write!(w, "", id)?; - write!(w, "")?; + write!(w, "")?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() { write!(w, "
    ")?; @@ -3325,8 +3360,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } else { render_stability_since_raw(w, since, outer_version)?; } - write!(w, "
    ")?; - write!(w, "\n")?; + write!(w, "

    ")?; if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { write!(w, "
    {}
    ", Markdown(&*dox, &i.impl_item.links()))?; @@ -3355,19 +3389,20 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "

    ", id, item_type)?; write!(w, "{}", spotlight_decl(decl)?)?; write!(w, "

    ")?; } } clean::TypedefItem(ref tydef, _) => { @@ -4041,11 +4076,13 @@ impl<'a> fmt::Display for Source<'a> { fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Macro) -> fmt::Result { - w.write_str(&highlight::render_with_highlighting(&t.source, - Some("macro"), - None, - None, - None))?; + wrap_into_docblock(w, |w| { + w.write_str(&highlight::render_with_highlighting(&t.source, + Some("macro"), + None, + None, + None)) + })?; document(w, cx, it) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index f1c9c58a4ebc..3c115e2b8bac 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -49,6 +49,13 @@ var themesWidth = null; + if (!String.prototype.startsWith) { + String.prototype.startsWith = function(searchString, position) { + position = position || 0; + return this.indexOf(searchString, position) === position; + }; + } + function hasClass(elem, className) { if (elem && className && elem.className) { var elemClass = elem.className; @@ -239,52 +246,59 @@ } } - function handleShortcut(ev) { - if (document.activeElement.tagName === "INPUT" && - hasClass(document.getElementById('main'), "hidden")) { - return; + function handleEscape(ev, help) { + hideModal(); + var search = document.getElementById("search"); + if (!hasClass(help, "hidden")) { + displayHelp(false, ev); + } else if (!hasClass(search, "hidden")) { + ev.preventDefault(); + addClass(search, "hidden"); + removeClass(document.getElementById("main"), "hidden"); } + defocusSearchBar(); + } + function handleShortcut(ev) { // Don't interfere with browser shortcuts if (ev.ctrlKey || ev.altKey || ev.metaKey) { return; } var help = document.getElementById("help"); - switch (getVirtualKey(ev)) { - case "Escape": - hideModal(); - var search = document.getElementById("search"); - if (!hasClass(help, "hidden")) { + if (document.activeElement.tagName === "INPUT") { + switch (getVirtualKey(ev)) { + case "Escape": + handleEscape(ev, help); + break; + } + } else { + switch (getVirtualKey(ev)) { + case "Escape": + handleEscape(ev, help); + break; + + case "s": + case "S": displayHelp(false, ev); - } else if (!hasClass(search, "hidden")) { - ev.preventDefault(); - addClass(search, "hidden"); - removeClass(document.getElementById("main"), "hidden"); - } - defocusSearchBar(); - break; - - case "s": - case "S": - displayHelp(false, ev); - hideModal(); - ev.preventDefault(); - focusSearchBar(); - break; - - case "+": - case "-": - ev.preventDefault(); - toggleAllDocs(); - break; - - case "?": - if (ev.shiftKey) { hideModal(); - displayHelp(true, ev); + ev.preventDefault(); + focusSearchBar(); + break; + + case "+": + case "-": + ev.preventDefault(); + toggleAllDocs(); + break; + + case "?": + if (ev.shiftKey) { + hideModal(); + displayHelp(true, ev); + } + break; } - break; } } @@ -1157,6 +1171,10 @@ return h1.innerHTML; } + function pathSplitter(path) { + return '' + path.replace(/::/g, '::'); + } + function addTab(array, query, display) { var extraStyle = ''; if (display === false) { @@ -1211,7 +1229,7 @@ output += '' + '' + - displayPath + '' + + pathSplitter(displayPath) + '' + name + '' + '' + '' + escape(item.desc) + @@ -1628,6 +1646,7 @@ function toggleAllDocs() { var toggle = document.getElementById("toggle-all-docs"); if (hasClass(toggle, "will-expand")) { + updateLocalStorage("rustdoc-collapse", "false"); removeClass(toggle, "will-expand"); onEveryMatchingChild(toggle, "inner", function(e) { e.innerHTML = labelForToggleButton(false); @@ -1637,6 +1656,7 @@ collapseDocs(e, "show"); }); } else { + updateLocalStorage("rustdoc-collapse", "true"); addClass(toggle, "will-expand"); onEveryMatchingChild(toggle, "inner", function(e) { e.innerHTML = labelForToggleButton(true); @@ -1697,19 +1717,20 @@ // we are collapsing the impl block function implHider(addOrRemove) { return function(n) { - if (hasClass(n, "method")) { - if (addOrRemove) { - addClass(n, "hidden-by-impl-hider"); - } else { - removeClass(n, "hidden-by-impl-hider"); + var is_method = hasClass(n, "method"); + if (is_method || hasClass(n, "type")) { + if (is_method === true) { + if (addOrRemove) { + addClass(n, "hidden-by-impl-hider"); + } else { + removeClass(n, "hidden-by-impl-hider"); + } } var ns = n.nextElementSibling; while (true) { if (ns && ( hasClass(ns, "docblock") || - hasClass(ns, "stability") || - false - )) { + hasClass(ns, "stability"))) { if (addOrRemove) { addClass(ns, "hidden-by-impl-hider"); } else { @@ -1725,12 +1746,13 @@ } var relatedDoc = toggle.parentNode; + var docblock = relatedDoc.nextElementSibling; while (!hasClass(relatedDoc, "impl-items")) { relatedDoc = relatedDoc.nextElementSibling; } - if (!relatedDoc) { + if (!relatedDoc && !hasClass(docblock, "docblock")) { return; } @@ -1738,7 +1760,8 @@ var action = mode; if (action === "toggle") { - if (hasClass(relatedDoc, "fns-now-collapsed")) { + if (hasClass(relatedDoc, "fns-now-collapsed") || + hasClass(docblock, "hidden-by-impl-hider")) { action = "show"; } else { action = "hide"; @@ -1747,10 +1770,12 @@ if (action === "show") { removeClass(relatedDoc, "fns-now-collapsed"); + removeClass(docblock, "hidden-by-usual-hider"); onEach(toggle.childNodes, adjustToggle(false)); onEach(relatedDoc.childNodes, implHider(false)); } else if (action === "hide") { addClass(relatedDoc, "fns-now-collapsed"); + addClass(docblock, "hidden-by-usual-hider"); onEach(toggle.childNodes, adjustToggle(true)); onEach(relatedDoc.childNodes, implHider(true)); } @@ -1800,6 +1825,9 @@ var func = function(e) { var next = e.nextElementSibling; + if (hasClass(e, 'impl') && next && hasClass(next, 'docblock')) { + next = next.nextElementSibling; + } if (!next) { return; } @@ -1817,11 +1845,16 @@ onEach(e.getElementsByClassName('associatedconstant'), func); }); - function createToggle() { + function createToggle(otherMessage) { var span = document.createElement('span'); span.className = 'toggle-label'; span.style.display = 'none'; - span.innerHTML = ' Expand description'; + if (!otherMessage) { + span.innerHTML = ' Expand description'; + } else { + span.innerHTML = otherMessage; + span.style.fontSize = '20px'; + } var mainToggle = toggle.cloneNode(true); mainToggle.appendChild(span); @@ -1834,7 +1867,14 @@ onEach(document.getElementById('main').getElementsByClassName('docblock'), function(e) { if (e.parentNode.id === "main") { - e.parentNode.insertBefore(createToggle(), e); + var otherMessage; + if (hasClass(e, "type-decl")) { + otherMessage = ' Show type declaration'; + } + e.parentNode.insertBefore(createToggle(otherMessage), e); + if (otherMessage) { + collapseDocs(e.previousSibling.childNodes[0], "toggle"); + } } }); @@ -1988,6 +2028,10 @@ window.onresize = function() { hideSidebar(); }; + + if (getCurrentValue("rustdoc-collapse") === "true") { + toggleAllDocs(); + } }()); // Sets the focus on the search bar at the top of the page diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 9b899dd4517e..31a501d24e7d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -109,7 +109,6 @@ h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant { position: relative; } h3.impl, h3.method, h3.type { - margin-top: 15px; padding-left: 15px; } @@ -296,6 +295,11 @@ nav.sub { overflow: auto; } +#results > table { + width: 100%; + table-layout: fixed; +} + .content pre.line-numbers { float: left; border: none; @@ -387,8 +391,6 @@ h4 > code, h3 > code, .invisible > code { .content .in-band { margin: 0px; padding: 0px; - display: inline-block; - max-width: calc(100% - 43px); } .in-band > code { @@ -403,7 +405,7 @@ h4 > code, h3 > code, .invisible > code { font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } -.content table { +.content table:not(.table-display) { border-spacing: 0 5px; border-collapse: separate; } @@ -467,10 +469,12 @@ h4 > code, h3 > code, .invisible > code { font-size: 0.8em; } -.content .methods > div:not(.important-traits) { margin-left: 40px; } +.content .methods > div:not(.important-traits) { + margin-left: 40px; + margin-bottom: 15px; +} .content .impl-items .docblock, .content .impl-items .stability { - margin-left: 40px; margin-bottom: .6em; } .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant { @@ -577,8 +581,16 @@ a { display: block; } -.content .search-results td:first-child { padding-right: 0; } -.content .search-results td:first-child a { padding-right: 10px; } +.content .search-results td:first-child { + padding-right: 0; + width: 75%; +} +.content .search-results td:first-child a { + padding-right: 10px; +} +.content .search-results td:first-child a span { + float: left; +} tr.result span.primitive::after { content: ' (primitive type)'; @@ -1254,3 +1266,28 @@ kbd { /* important because of conflicting rule for small screens */ display: none !important; } + +#implementations-list > h3 > span.in-band { + width: 100%; +} + +.table-display { + width: 100%; + border: 0; + border-collapse: collapse; + border-spacing: 0; + font-size: 16px; +} + +.table-display tr td:first-child { + padding-right: 0; +} + +.table-display tr td:last-child { + float: right; +} +.table-display .out-of-band { + position: relative; + font-size: 19px; + display: block; +} diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index 7e9cfbd67634..2f4e203ebc5c 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -44,8 +44,12 @@ function switchTheme(styleElem, mainStyleElem, newTheme) { var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; var fullNewTheme = newTheme + resourcesSuffix + ".css"; var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); - var found = false; + if (styleElem.href === newHref) { + return; + } + + var found = false; if (savedHref.length === 0) { onEach(document.getElementsByTagName("link"), function(el) { savedHref.push(el.href); @@ -63,4 +67,4 @@ function switchTheme(styleElem, mainStyleElem, newTheme) { } } -switchTheme(currentTheme, mainTheme, getCurrentValue('rustdoc-theme') || 'main'); +switchTheme(currentTheme, mainTheme, getCurrentValue('rustdoc-theme') || 'light'); diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 2d0fe55f70d2..09776569f80b 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -239,7 +239,7 @@ a.test-arrow:hover{ } :target > code { - background: #FDFFD3; + background-color: #494a3d; } pre.compile_fail { diff --git a/src/librustdoc/html/static/themes/main.css b/src/librustdoc/html/static/themes/light.css similarity index 100% rename from src/librustdoc/html/static/themes/main.css rename to src/librustdoc/html/static/themes/light.css diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 702031cfaca3..e31390f59e29 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -20,7 +20,7 @@ #![feature(box_syntax)] #![feature(fs_read_write)] #![feature(set_stdio)] -#![feature(slice_patterns)] +#![cfg_attr(stage0, feature(slice_patterns))] #![feature(test)] #![feature(unicode)] #![feature(vec_remove_item)] @@ -61,9 +61,11 @@ use std::path::{Path, PathBuf}; use std::process; use std::sync::mpsc::channel; +use syntax::edition::Edition; use externalfiles::ExternalHtml; use rustc::session::search_paths::SearchPaths; use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options, Externs}; +use rustc_back::target::TargetTriple; #[macro_use] pub mod externalfiles; @@ -102,7 +104,9 @@ pub fn main() { const STACK_SIZE: usize = 32_000_000; // 32MB env_logger::init(); let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || { - get_args().map(|args| main_args(&args)).unwrap_or(1) + syntax::with_globals(move || { + get_args().map(|args| main_args(&args)).unwrap_or(1) + }) }).unwrap().join().unwrap_or(101); process::exit(res as i32); } @@ -264,10 +268,15 @@ pub fn opts() -> Vec { unstable("resource-suffix", |o| { o.optopt("", "resource-suffix", - "suffix to add to CSS and JavaScript files, e.g. \"main.css\" will become \ - \"main-suffix.css\"", + "suffix to add to CSS and JavaScript files, e.g. \"light.css\" will become \ + \"light-suffix.css\"", "PATH") }), + unstable("edition", |o| { + o.optopt("", "edition", + "edition to use when compiling rust code (default: 2015)", + "EDITION") + }), ] } @@ -319,7 +328,7 @@ pub fn main_args(args: &[String]) -> isize { let to_check = matches.opt_strs("theme-checker"); if !to_check.is_empty() { - let paths = theme::load_css_paths(include_bytes!("html/static/themes/main.css")); + let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css")); let mut errors = 0; println!("rustdoc: [theme-checker] Starting tests!"); @@ -390,7 +399,7 @@ pub fn main_args(args: &[String]) -> isize { let mut themes = Vec::new(); if matches.opt_present("themes") { - let paths = theme::load_css_paths(include_bytes!("html/static/themes/main.css")); + let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css")); for (theme_file, theme_s) in matches.opt_strs("themes") .iter() @@ -426,14 +435,23 @@ pub fn main_args(args: &[String]) -> isize { let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance"); let resource_suffix = matches.opt_str("resource-suffix"); + let edition = matches.opt_str("edition").unwrap_or("2015".to_string()); + let edition = match edition.parse() { + Ok(e) => e, + Err(_) => { + print_error("could not parse edition"); + return 1; + } + }; + match (should_test, markdown_input) { (true, true) => { return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot, - display_warnings, linker) + display_warnings, linker, edition) } (true, false) => { return test::run(Path::new(input), cfgs, libs, externs, test_args, crate_name, - maybe_sysroot, display_warnings, linker) + maybe_sysroot, display_warnings, linker, edition) } (false, true) => return markdown::render(Path::new(input), output.unwrap_or(PathBuf::from("doc")), @@ -443,7 +461,7 @@ pub fn main_args(args: &[String]) -> isize { } let output_format = matches.opt_str("w"); - let res = acquire_input(PathBuf::from(input), externs, &matches, move |out| { + let res = acquire_input(PathBuf::from(input), externs, edition, &matches, move |out| { let Output { krate, passes, renderinfo } = out; info!("going to format"); match output_format.as_ref().map(|s| &**s) { @@ -484,14 +502,15 @@ fn print_error(error_message: T) where T: Display { /// and files and then generates the necessary rustdoc output for formatting. fn acquire_input(input: PathBuf, externs: Externs, + edition: Edition, matches: &getopts::Matches, f: F) -> Result where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { match matches.opt_str("r").as_ref().map(|s| &**s) { - Some("rust") => Ok(rust_input(input, externs, matches, f)), + Some("rust") => Ok(rust_input(input, externs, edition, matches, f)), Some(s) => Err(format!("unknown input format: {}", s)), - None => Ok(rust_input(input, externs, matches, f)) + None => Ok(rust_input(input, externs, edition, matches, f)) } } @@ -517,8 +536,14 @@ fn parse_externs(matches: &getopts::Matches) -> Result { /// generated from the cleaned AST of the crate. /// /// This form of input will run all of the plug/cleaning passes -fn rust_input(cratefile: PathBuf, externs: Externs, matches: &getopts::Matches, f: F) -> R -where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { +fn rust_input(cratefile: PathBuf, + externs: Externs, + edition: Edition, + matches: &getopts::Matches, + f: F) -> R +where R: 'static + Send, + F: 'static + Send + FnOnce(Output) -> R +{ let mut default_passes = !matches.opt_present("no-defaults"); let mut passes = matches.opt_strs("passes"); let mut plugins = matches.opt_strs("plugins"); @@ -540,7 +565,13 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { paths.add_path(s, ErrorOutputType::default()); } let cfgs = matches.opt_strs("cfg"); - let triple = matches.opt_str("target"); + let triple = matches.opt_str("target").map(|target| { + if target.ends_with(".json") { + TargetTriple::TargetPath(PathBuf::from(target)) + } else { + TargetTriple::TargetTriple(target) + } + }); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let crate_name = matches.opt_str("crate-name"); let crate_version = matches.opt_str("crate-version"); @@ -554,13 +585,14 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { }); let (tx, rx) = channel(); - rustc_driver::monitor(move || { + + rustc_driver::monitor(move || syntax::with_globals(move || { use rustc::session::config::Input; let (mut krate, renderinfo) = core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot, display_warnings, crate_name.clone(), - force_unstable_if_unmarked); + force_unstable_if_unmarked, edition); info!("finished with rustc"); @@ -623,7 +655,7 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { let krate = pm.run_plugins(krate); tx.send(f(Output { krate: krate, renderinfo: renderinfo, passes: passes })).unwrap(); - }); + })); rx.recv().unwrap() } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 0f107457d2bf..daa8966b104e 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -18,6 +18,7 @@ use testing; use rustc::session::search_paths::SearchPaths; use rustc::session::config::Externs; use syntax::codemap::DUMMY_SP; +use syntax::edition::Edition; use externalfiles::{ExternalHtml, LoadStringError, load_string}; @@ -139,7 +140,7 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, /// Run any tests/code examples in the markdown file `input`. pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, mut test_args: Vec, maybe_sysroot: Option, - display_warnings: bool, linker: Option) -> isize { + display_warnings: bool, linker: Option, edition: Edition) -> isize { let input_str = match load_string(input) { Ok(s) => s, Err(LoadStringError::ReadFail) => return 1, @@ -151,8 +152,8 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, let mut collector = Collector::new(input.to_owned(), cfgs, libs, externs, true, opts, maybe_sysroot, None, Some(PathBuf::from(input)), - linker); - find_testable_code(&input_str, &mut collector, DUMMY_SP); + linker, edition); + find_testable_code(&input_str, &mut collector, DUMMY_SP, None); test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests, testing::Options::new().display_output(display_warnings)); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e4477bee5c0e..ab11b0d62e9f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -34,7 +34,9 @@ use rustc_metadata::cstore::CStore; use rustc_resolve::MakeGlobMap; use syntax::ast; use syntax::codemap::CodeMap; +use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; +use syntax::with_globals; use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName}; use errors; use errors::emitter::ColorConfig; @@ -56,7 +58,8 @@ pub fn run(input_path: &Path, crate_name: Option, maybe_sysroot: Option, display_warnings: bool, - linker: Option) + linker: Option, + edition: Edition) -> isize { let input = config::Input::File(input_path.to_owned()); @@ -69,6 +72,10 @@ pub fn run(input_path: &Path, unstable_features: UnstableFeatures::from_environment(), lint_cap: Some(::rustc::lint::Level::Allow), actually_rustdoc: true, + debugging_opts: config::DebuggingOptions { + edition, + ..config::basic_debugging_options() + }, ..config::basic_options().clone() }; @@ -116,7 +123,8 @@ pub fn run(input_path: &Path, maybe_sysroot, Some(codemap), None, - linker); + linker, + edition); { let map = hir::map::map_crate(&sess, &cstore, &mut hir_forest, &defs); @@ -176,8 +184,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, externs: Externs, should_panic: bool, no_run: bool, as_test_harness: bool, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option, - linker: Option) { + maybe_sysroot: Option, linker: Option, edition: Edition) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts); @@ -203,6 +210,10 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, }, test: as_test_harness, unstable_features: UnstableFeatures::from_environment(), + debugging_opts: config::DebuggingOptions { + edition, + ..config::basic_debugging_options() + }, ..config::basic_options().clone() }; @@ -405,8 +416,6 @@ pub fn make_test(s: &str, // FIXME(aburka): use a real parser to deal with multiline attributes fn partition_source(s: &str) -> (String, String) { - use std_unicode::str::UnicodeStr; - let mut after_header = false; let mut before = String::new(); let mut after = String::new(); @@ -415,6 +424,7 @@ fn partition_source(s: &str) -> (String, String) { let trimline = line.trim(); let header = trimline.is_whitespace() || trimline.starts_with("#![") || + trimline.starts_with("#[macro_use] extern crate") || trimline.starts_with("extern crate"); if !header || after_header { after_header = true; @@ -465,13 +475,14 @@ pub struct Collector { codemap: Option>, filename: Option, linker: Option, + edition: Edition, } impl Collector { pub fn new(cratename: String, cfgs: Vec, libs: SearchPaths, externs: Externs, use_headers: bool, opts: TestOptions, maybe_sysroot: Option, codemap: Option>, filename: Option, - linker: Option) -> Collector { + linker: Option, edition: Edition) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), @@ -486,6 +497,7 @@ impl Collector { codemap, filename, linker, + edition, } } @@ -505,6 +517,7 @@ impl Collector { let opts = self.opts.clone(); let maybe_sysroot = self.maybe_sysroot.clone(); let linker = self.linker.clone(); + let edition = self.edition; debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { @@ -518,7 +531,7 @@ impl Collector { let panic = io::set_panic(None); let print = io::set_print(None); match { - rustc_driver::in_rustc_thread(move || { + rustc_driver::in_rustc_thread(move || with_globals(move || { io::set_panic(panic); io::set_print(print); run_test(&test, @@ -535,8 +548,9 @@ impl Collector { error_codes, &opts, maybe_sysroot, - linker) - }) + linker, + edition) + })) } { Ok(()) => (), Err(err) => panic::resume_unwind(err), @@ -644,8 +658,10 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with // anything else, this will combine them for us if let Some(doc) = attrs.collapsed_doc_value() { - markdown::find_testable_code(&doc, self.collector, - attrs.span.unwrap_or(DUMMY_SP)); + markdown::find_testable_code(&doc, + self.collector, + attrs.span.unwrap_or(DUMMY_SP), + Some(self.sess)); } nested(self); @@ -824,6 +840,24 @@ assert_eq!(2+2, 4); assert_eq!(output, (expected, 2)); } + #[test] + fn make_test_manual_extern_crate_with_macro_use() { + let opts = TestOptions::default(); + let input = +"#[macro_use] extern crate asdf; +use asdf::qwop; +assert_eq!(2+2, 4);"; + let expected = +"#![allow(unused)] +#[macro_use] extern crate asdf; +fn main() { +use asdf::qwop; +assert_eq!(2+2, 4); +}".to_string(); + let output = make_test(input, Some("asdf"), false, &opts); + assert_eq!(output, (expected, 2)); + } + #[test] fn make_test_opts_attrs() { //if you supplied some doctest attributes with #![doc(test(attr(...)))], it will use those diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index f692e05d6a25..f45a5b030db2 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -406,13 +406,13 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { // If we're inlining, skip private items. _ if self.inlining && item.vis != hir::Public => {} hir::ItemGlobalAsm(..) => {} - hir::ItemExternCrate(ref p) => { + hir::ItemExternCrate(orig_name) => { let def_id = self.cx.tcx.hir.local_def_id(item.id); om.extern_crates.push(ExternCrate { cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id) .unwrap_or(LOCAL_CRATE), name, - path: p.map(|x|x.to_string()), + path: orig_name.map(|x|x.to_string()), vis: item.vis.clone(), attrs: item.attrs.clone(), whence: item.span, diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 2e354252c157..ee9525234622 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -23,7 +23,7 @@ Core encoding and decoding interfaces. #![feature(box_syntax)] #![feature(core_intrinsics)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(specialization)] #![cfg_attr(test, feature(test))] diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index c1fe4a89d6ac..120175988533 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -26,7 +26,7 @@ std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } [dev-dependencies] -rand = "0.3" +rand = "0.4" [target.x86_64-apple-darwin.dependencies] rustc_asan = { path = "../librustc_asan" } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index d5bf9e9bb2f6..6472edb0aa7d 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -26,9 +26,8 @@ #![stable(feature = "rust1", since = "1.0.0")] -use fmt; -use ops::Range; -use iter::FusedIterator; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::ascii::{EscapeDefault, escape_default}; /// Extension methods for ASCII-subset only operations. /// @@ -53,6 +52,7 @@ use iter::FusedIterator; /// /// [combining character]: https://en.wikipedia.org/wiki/Combining_character #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] pub trait AsciiExt { /// Container type for copied ASCII characters. #[stable(feature = "rust1", since = "1.0.0")] @@ -85,6 +85,7 @@ pub trait AsciiExt { /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_uppercase(&self) -> Self::Owned; /// Makes a copy of the value in its ASCII lower case equivalent. @@ -105,6 +106,7 @@ pub trait AsciiExt { /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_lowercase(&self) -> Self::Owned; /// Checks that two values are an ASCII case-insensitive match. @@ -163,6 +165,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII uppercase character: @@ -175,6 +178,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_uppercase(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII lowercase character: @@ -187,6 +191,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_lowercase(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII alphanumeric character: @@ -200,6 +205,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII decimal digit: @@ -212,6 +218,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_digit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII hexadecimal digit: @@ -225,6 +232,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII punctuation character: @@ -242,6 +250,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_punctuation(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII graphic character: @@ -254,6 +263,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_graphic(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII whitespace character: @@ -283,6 +293,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_whitespace(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII control character: @@ -295,6 +306,7 @@ pub trait AsciiExt { /// This method will be deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[unstable(feature = "ascii_ctype", issue = "39658")] + #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] fn is_ascii_control(&self) -> bool { unimplemented!(); } } @@ -355,6 +367,7 @@ macro_rules! delegating_ascii_ctype_methods { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for u8 { type Owned = u8; @@ -363,6 +376,7 @@ impl AsciiExt for u8 { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for char { type Owned = char; @@ -371,6 +385,7 @@ impl AsciiExt for char { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for [u8] { type Owned = Vec; @@ -428,6 +443,7 @@ impl AsciiExt for [u8] { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for str { type Owned = String; @@ -483,477 +499,3 @@ impl AsciiExt for str { self.bytes().all(|b| b.is_ascii_control()) } } - -/// An iterator over the escaped version of a byte. -/// -/// This `struct` is created by the [`escape_default`] function. See its -/// documentation for more. -/// -/// [`escape_default`]: fn.escape_default.html -#[stable(feature = "rust1", since = "1.0.0")] -pub struct EscapeDefault { - range: Range, - data: [u8; 4], -} - -/// Returns an iterator that produces an escaped version of a `u8`. -/// -/// The default is chosen with a bias toward producing literals that are -/// legal in a variety of languages, including C++11 and similar C-family -/// languages. The exact rules are: -/// -/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively. -/// - Single-quote, double-quote and backslash chars are backslash-escaped. -/// - Any other chars in the range [0x20,0x7e] are not escaped. -/// - Any other chars are given hex escapes of the form '\xNN'. -/// - Unicode escapes are never generated by this function. -/// -/// # Examples -/// -/// ``` -/// use std::ascii; -/// -/// let escaped = ascii::escape_default(b'0').next().unwrap(); -/// assert_eq!(b'0', escaped); -/// -/// let mut escaped = ascii::escape_default(b'\t'); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b't', escaped.next().unwrap()); -/// -/// let mut escaped = ascii::escape_default(b'\r'); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b'r', escaped.next().unwrap()); -/// -/// let mut escaped = ascii::escape_default(b'\n'); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b'n', escaped.next().unwrap()); -/// -/// let mut escaped = ascii::escape_default(b'\''); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b'\'', escaped.next().unwrap()); -/// -/// let mut escaped = ascii::escape_default(b'"'); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b'"', escaped.next().unwrap()); -/// -/// let mut escaped = ascii::escape_default(b'\\'); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// -/// let mut escaped = ascii::escape_default(b'\x9d'); -/// -/// assert_eq!(b'\\', escaped.next().unwrap()); -/// assert_eq!(b'x', escaped.next().unwrap()); -/// assert_eq!(b'9', escaped.next().unwrap()); -/// assert_eq!(b'd', escaped.next().unwrap()); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -pub fn escape_default(c: u8) -> EscapeDefault { - let (data, len) = match c { - b'\t' => ([b'\\', b't', 0, 0], 2), - b'\r' => ([b'\\', b'r', 0, 0], 2), - b'\n' => ([b'\\', b'n', 0, 0], 2), - b'\\' => ([b'\\', b'\\', 0, 0], 2), - b'\'' => ([b'\\', b'\'', 0, 0], 2), - b'"' => ([b'\\', b'"', 0, 0], 2), - b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1), - _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), - }; - - return EscapeDefault { range: (0.. len), data: data }; - - fn hexify(b: u8) -> u8 { - match b { - 0 ... 9 => b'0' + b, - _ => b'a' + b - 10, - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for EscapeDefault { - type Item = u8; - fn next(&mut self) -> Option { self.range.next().map(|i| self.data[i]) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for EscapeDefault { - fn next_back(&mut self) -> Option { - self.range.next_back().map(|i| self.data[i]) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for EscapeDefault {} -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for EscapeDefault {} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for EscapeDefault { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("EscapeDefault { .. }") - } -} - - -#[cfg(test)] -mod tests { - //! Note that most of these tests are not testing `AsciiExt` methods, but - //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is - //! just using those methods, though. - use super::AsciiExt; - use char::from_u32; - - #[test] - fn test_is_ascii() { - assert!(b"".is_ascii()); - assert!(b"banana\0\x7F".is_ascii()); - assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii())); - assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii()); - assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii())); - assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii())); - - assert!("".is_ascii()); - assert!("banana\0\u{7F}".is_ascii()); - assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii())); - assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii())); - assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii())); - } - - #[test] - fn test_to_ascii_uppercase() { - assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL"); - assert_eq!("hıKß".to_ascii_uppercase(), "HıKß"); - - for i in 0..501 { - let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } - else { i }; - assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(), - (from_u32(upper).unwrap()).to_string()); - } - } - - #[test] - fn test_to_ascii_lowercase() { - assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl"); - // Dotted capital I, Kelvin sign, Sharp S. - assert_eq!("HİKß".to_ascii_lowercase(), "hİKß"); - - for i in 0..501 { - let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } - else { i }; - assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(), - (from_u32(lower).unwrap()).to_string()); - } - } - - #[test] - fn test_make_ascii_lower_case() { - macro_rules! test { - ($from: expr, $to: expr) => { - { - let mut x = $from; - x.make_ascii_lowercase(); - assert_eq!(x, $to); - } - } - } - test!(b'A', b'a'); - test!(b'a', b'a'); - test!(b'!', b'!'); - test!('A', 'a'); - test!('À', 'À'); - test!('a', 'a'); - test!('!', '!'); - test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89"); - test!("HİKß".to_string(), "hİKß"); - } - - - #[test] - fn test_make_ascii_upper_case() { - macro_rules! test { - ($from: expr, $to: expr) => { - { - let mut x = $from; - x.make_ascii_uppercase(); - assert_eq!(x, $to); - } - } - } - test!(b'a', b'A'); - test!(b'A', b'A'); - test!(b'!', b'!'); - test!('a', 'A'); - test!('à', 'à'); - test!('A', 'A'); - test!('!', '!'); - test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9"); - test!("hıKß".to_string(), "HıKß"); - - let mut x = "Hello".to_string(); - x[..3].make_ascii_uppercase(); // Test IndexMut on String. - assert_eq!(x, "HELlo") - } - - #[test] - fn test_eq_ignore_ascii_case() { - assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl")); - assert!(!"Ürl".eq_ignore_ascii_case("ürl")); - // Dotted capital I, Kelvin sign, Sharp S. - assert!("HİKß".eq_ignore_ascii_case("hİKß")); - assert!(!"İ".eq_ignore_ascii_case("i")); - assert!(!"K".eq_ignore_ascii_case("k")); - assert!(!"ß".eq_ignore_ascii_case("s")); - - for i in 0..501 { - let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } - else { i }; - assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case( - &from_u32(lower).unwrap().to_string())); - } - } - - #[test] - fn inference_works() { - let x = "a".to_string(); - x.eq_ignore_ascii_case("A"); - } - - // Shorthands used by the is_ascii_* tests. - macro_rules! assert_all { - ($what:ident, $($str:tt),+) => {{ - $( - for b in $str.chars() { - if !b.$what() { - panic!("expected {}({}) but it isn't", - stringify!($what), b); - } - } - for b in $str.as_bytes().iter() { - if !b.$what() { - panic!("expected {}(0x{:02x})) but it isn't", - stringify!($what), b); - } - } - assert!($str.$what()); - assert!($str.as_bytes().$what()); - )+ - }}; - ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+)) - } - macro_rules! assert_none { - ($what:ident, $($str:tt),+) => {{ - $( - for b in $str.chars() { - if b.$what() { - panic!("expected not-{}({}) but it is", - stringify!($what), b); - } - } - for b in $str.as_bytes().iter() { - if b.$what() { - panic!("expected not-{}(0x{:02x})) but it is", - stringify!($what), b); - } - } - )* - }}; - ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+)) - } - - #[test] - fn test_is_ascii_alphabetic() { - assert_all!(is_ascii_alphabetic, - "", - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - ); - assert_none!(is_ascii_alphabetic, - "0123456789", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_uppercase() { - assert_all!(is_ascii_uppercase, - "", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - ); - assert_none!(is_ascii_uppercase, - "abcdefghijklmnopqrstuvwxyz", - "0123456789", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_lowercase() { - assert_all!(is_ascii_lowercase, - "abcdefghijklmnopqrstuvwxyz", - ); - assert_none!(is_ascii_lowercase, - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "0123456789", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_alphanumeric() { - assert_all!(is_ascii_alphanumeric, - "", - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "0123456789", - ); - assert_none!(is_ascii_alphanumeric, - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_digit() { - assert_all!(is_ascii_digit, - "", - "0123456789", - ); - assert_none!(is_ascii_digit, - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_hexdigit() { - assert_all!(is_ascii_hexdigit, - "", - "0123456789", - "abcdefABCDEF", - ); - assert_none!(is_ascii_hexdigit, - "ghijklmnopqrstuvwxyz", - "GHIJKLMNOQPRSTUVWXYZ", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_punctuation() { - assert_all!(is_ascii_punctuation, - "", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - ); - assert_none!(is_ascii_punctuation, - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "0123456789", - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_graphic() { - assert_all!(is_ascii_graphic, - "", - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "0123456789", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - ); - assert_none!(is_ascii_graphic, - " \t\n\x0c\r", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_whitespace() { - assert_all!(is_ascii_whitespace, - "", - " \t\n\x0c\r", - ); - assert_none!(is_ascii_whitespace, - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "0123456789", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x0b\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - } - - #[test] - fn test_is_ascii_control() { - assert_all!(is_ascii_control, - "", - "\x00\x01\x02\x03\x04\x05\x06\x07", - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17", - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x7f", - ); - assert_none!(is_ascii_control, - "abcdefghijklmnopqrstuvwxyz", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - "0123456789", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - " ", - ); - } -} diff --git a/src/libstd/build.rs b/src/libstd/build.rs index a41c155f3fb5..6652ff98201a 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -86,6 +86,7 @@ fn main() { fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> { let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?; + let cflags = env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden -O2"; run(Command::new("sh") .current_dir(&native.out_dir) @@ -98,7 +99,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> { .arg("--disable-host-shared") .arg(format!("--host={}", build_helper::gnu_target(target))) .arg(format!("--build={}", build_helper::gnu_target(host))) - .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden")); + .env("CFLAGS", cflags)); run(Command::new(build_helper::make(host)) .current_dir(&native.out_dir) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 6f4528a0e243..e0b48e565d02 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,7 +11,10 @@ use self::Entry::*; use self::VacantEntryState::*; +use alloc::heap::Heap; +use alloc::allocator::CollectionAllocErr; use cell::Cell; +use core::heap::Alloc; use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; @@ -19,8 +22,7 @@ use fmt::{self, Debug}; use hash::{Hash, Hasher, BuildHasher, SipHasher13}; use iter::{FromIterator, FusedIterator}; use mem::{self, replace}; -use ops::{Deref, Index, InPlace, Place, Placer}; -use ptr; +use ops::{Deref, Index}; use sys; use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash}; @@ -42,21 +44,28 @@ impl DefaultResizePolicy { /// provide that capacity, accounting for maximum loading. The raw capacity /// is always zero or a power of two. #[inline] - fn raw_capacity(&self, len: usize) -> usize { + fn try_raw_capacity(&self, len: usize) -> Result { if len == 0 { - 0 + Ok(0) } else { // 1. Account for loading: `raw_capacity >= len * 1.1`. // 2. Ensure it is a power of two. // 3. Ensure it is at least the minimum size. - let mut raw_cap = len * 11 / 10; - assert!(raw_cap >= len, "raw_cap overflow"); - raw_cap = raw_cap.checked_next_power_of_two().expect("raw_capacity overflow"); + let mut raw_cap = len.checked_mul(11) + .map(|l| l / 10) + .and_then(|l| l.checked_next_power_of_two()) + .ok_or(CollectionAllocErr::CapacityOverflow)?; + raw_cap = max(MIN_NONZERO_RAW_CAPACITY, raw_cap); - raw_cap + Ok(raw_cap) } } + #[inline] + fn raw_capacity(&self, len: usize) -> usize { + self.try_raw_capacity(len).expect("raw_capacity overflow") + } + /// The capacity of the given raw capacity. #[inline] fn capacity(&self, raw_cap: usize) -> usize { @@ -775,17 +784,45 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { + match self.try_reserve(additional) { + Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), + Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e), + Ok(()) => { /* yay */ } + } + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `HashMap`. The collection may reserve more space to avoid + /// frequent reallocations. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::HashMap; + /// let mut map: HashMap<&str, isize> = HashMap::new(); + /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { let remaining = self.capacity() - self.len(); // this can't overflow if remaining < additional { - let min_cap = self.len().checked_add(additional).expect("reserve overflow"); - let raw_cap = self.resize_policy.raw_capacity(min_cap); - self.resize(raw_cap); + let min_cap = self.len().checked_add(additional) + .ok_or(CollectionAllocErr::CapacityOverflow)?; + let raw_cap = self.resize_policy.try_raw_capacity(min_cap)?; + self.try_resize(raw_cap)?; } else if self.table.tag() && remaining <= self.len() { // Probe sequence is too long and table is half full, // resize early to reduce probing length. let new_capacity = self.table.capacity() * 2; - self.resize(new_capacity); + self.try_resize(new_capacity)?; } + Ok(()) } /// Resizes the internal vectors to a new capacity. It's your @@ -795,15 +832,15 @@ impl HashMap /// 2) Ensure `new_raw_cap` is a power of two or zero. #[inline(never)] #[cold] - fn resize(&mut self, new_raw_cap: usize) { + fn try_resize(&mut self, new_raw_cap: usize) -> Result<(), CollectionAllocErr> { assert!(self.table.size() <= new_raw_cap); assert!(new_raw_cap.is_power_of_two() || new_raw_cap == 0); - let mut old_table = replace(&mut self.table, RawTable::new(new_raw_cap)); + let mut old_table = replace(&mut self.table, RawTable::try_new(new_raw_cap)?); let old_size = old_table.size(); if old_table.size() == 0 { - return; + return Ok(()); } let mut bucket = Bucket::head_bucket(&mut old_table); @@ -838,6 +875,7 @@ impl HashMap } assert_eq!(self.table.size(), old_size); + Ok(()) } /// Shrinks the capacity of the map as much as possible. It will drop @@ -872,6 +910,46 @@ impl HashMap } } + /// Shrinks the capacity of the map with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = HashMap::with_capacity(100); + /// map.insert(1, 2); + /// map.insert(3, 4); + /// assert!(map.capacity() >= 100); + /// map.shrink_to(10); + /// assert!(map.capacity() >= 10); + /// map.shrink_to(0); + /// assert!(map.capacity() >= 2); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + + let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity)); + if self.raw_capacity() != new_raw_cap { + let old_table = replace(&mut self.table, RawTable::new(new_raw_cap)); + let old_size = old_table.size(); + + // Shrink the table. Naive algorithm for resizing: + for (h, k, v) in old_table.into_iter() { + self.insert_hashed_nocheck(h, k, v); + } + + debug_assert_eq!(self.table.size(), old_size); + } + } + /// Insert a pre-hashed key-value pair, without first checking /// that there's enough room in the buckets. Returns a reference to the /// newly insert value. @@ -1146,6 +1224,34 @@ impl HashMap self.search(k).map(|bucket| bucket.into_refs().1) } + /// Returns the key-value pair corresponding to the supplied key. + /// + /// The supplied key may be any borrowed form of the map's key type, but + /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for + /// the key type. + /// + /// [`Eq`]: ../../std/cmp/trait.Eq.html + /// [`Hash`]: ../../std/hash/trait.Hash.html + /// + /// # Examples + /// + /// ``` + /// #![feature(map_get_key_value)] + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); + /// assert_eq!(map.get_key_value(&2), None); + /// ``` + #[unstable(feature = "map_get_key_value", issue = "49347")] + pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> + where K: Borrow, + Q: Hash + Eq + { + self.search(k).map(|bucket| bucket.into_refs()) + } + /// Returns true if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but @@ -1936,80 +2042,6 @@ impl<'a, K, V> fmt::Debug for Drain<'a, K, V> } } -/// A place for insertion to a `Entry`. -/// -/// See [`HashMap::entry`](struct.HashMap.html#method.entry) for details. -#[must_use = "places do nothing unless written to with `<-` syntax"] -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol is subject to change", - issue = "30172")] -pub struct EntryPlace<'a, K: 'a, V: 'a> { - bucket: FullBucketMut<'a, K, V>, -} - -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol is subject to change", - issue = "30172")] -impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for EntryPlace<'a, K, V> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("EntryPlace") - .field("key", self.bucket.read().0) - .field("value", self.bucket.read().1) - .finish() - } -} - -#[unstable(feature = "collection_placement", - reason = "struct name and placement protocol is subject to change", - issue = "30172")] -impl<'a, K, V> Drop for EntryPlace<'a, K, V> { - fn drop(&mut self) { - // Inplacement insertion failed. Only key need to drop. - // The value is failed to insert into map. - unsafe { self.bucket.remove_key() }; - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, K, V> Placer for Entry<'a, K, V> { - type Place = EntryPlace<'a, K, V>; - - fn make_place(self) -> EntryPlace<'a, K, V> { - let b = match self { - Occupied(mut o) => { - unsafe { ptr::drop_in_place(o.elem.read_mut().1); } - o.elem - } - Vacant(v) => { - unsafe { v.insert_key() } - } - }; - EntryPlace { bucket: b } - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -unsafe impl<'a, K, V> Place for EntryPlace<'a, K, V> { - fn pointer(&mut self) -> *mut V { - self.bucket.read_mut().1 - } -} - -#[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] -impl<'a, K, V> InPlace for EntryPlace<'a, K, V> { - type Owner = (); - - unsafe fn finalize(self) { - mem::forget(self); - } -} - impl<'a, K, V> Entry<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns @@ -2432,26 +2464,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { }; b.into_mut_refs().1 } - - // Only used for InPlacement insert. Avoid unnecessary value copy. - // The value remains uninitialized. - unsafe fn insert_key(self) -> FullBucketMut<'a, K, V> { - match self.elem { - NeqElem(mut bucket, disp) => { - if disp >= DISPLACEMENT_THRESHOLD { - bucket.table_mut().set_tag(true); - } - let uninit = mem::uninitialized(); - robin_hood(bucket, disp, self.hash, self.key, uninit) - }, - NoElem(mut bucket, disp) => { - if disp >= DISPLACEMENT_THRESHOLD { - bucket.table_mut().set_tag(true); - } - bucket.put_key(self.hash, self.key) - }, - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2716,7 +2728,9 @@ mod test_map { use super::RandomState; use cell::RefCell; use rand::{thread_rng, Rng}; - use panic; + use realstd::collections::CollectionAllocErr::*; + use realstd::mem::size_of; + use realstd::usize; #[test] fn test_zero_capacities() { @@ -3600,55 +3614,31 @@ mod test_map { } #[test] - fn test_placement_in() { - let mut map = HashMap::new(); - map.extend((0..10).map(|i| (i, i))); + fn test_try_reserve() { - map.entry(100) <- 100; - assert_eq!(map[&100], 100); + let mut empty_bytes: HashMap = HashMap::new(); - map.entry(0) <- 10; - assert_eq!(map[&0], 10); + const MAX_USIZE: usize = usize::MAX; - assert_eq!(map.len(), 11); - } + // HashMap and RawTables use complicated size calculations + // hashes_size is sizeof(HashUint) * capacity; + // pairs_size is sizeof((K. V)) * capacity; + // alignment_hashes_size is 8 + // alignment_pairs size is 4 + let size_of_multiplier = (size_of::() + size_of::<(u8, u8)>()).next_power_of_two(); + // The following formula is used to calculate the new capacity + let max_no_ovf = ((MAX_USIZE / 11) * 10) / size_of_multiplier - 1; - #[test] - fn test_placement_panic() { - let mut map = HashMap::new(); - map.extend((0..10).map(|i| (i, i))); + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { + } else { panic!("usize::MAX should trigger an overflow!"); } - fn mkpanic() -> usize { panic!() } - - // modify existing key - // when panic happens, previous key is removed. - let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); })); - assert_eq!(map.len(), 9); - assert!(!map.contains_key(&0)); - - // add new key - let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); })); - assert_eq!(map.len(), 9); - assert!(!map.contains_key(&100)); - } - - #[test] - fn test_placement_drop() { - // correctly drop - struct TestV<'a>(&'a mut bool); - impl<'a> Drop for TestV<'a> { - fn drop(&mut self) { - if !*self.0 { panic!("value double drop!"); } // no double drop - *self.0 = false; - } + if size_of::() < 8 { + if let Err(CapacityOverflow) = empty_bytes.try_reserve(max_no_ovf) { + } else { panic!("isize::MAX + 1 should trigger a CapacityOverflow!") } + } else { + if let Err(AllocErr(_)) = empty_bytes.try_reserve(max_no_ovf) { + } else { panic!("isize::MAX + 1 should trigger an OOM!") } } - - fn makepanic<'a>() -> TestV<'a> { panic!() } - - let mut can_drop = true; - let mut hm = HashMap::new(); - hm.insert(0, TestV(&mut can_drop)); - let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); })); - assert_eq!(hm.len(), 0); } + } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 9e63ba2717a6..855563a5cb8d 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -292,6 +292,34 @@ impl HashSet self.map.shrink_to_fit() } + /// Shrinks the capacity of the set with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::with_capacity(100); + /// set.insert(1); + /// set.insert(2); + /// assert!(set.capacity() >= 100); + /// set.shrink_to(10); + /// assert!(set.capacity() >= 10); + /// set.shrink_to(0); + /// assert!(set.capacity() >= 2); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.map.shrink_to(min_capacity) + } + /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. /// diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 73bd5747c105..fa6053d3f6d8 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::heap::{Heap, Alloc, Layout}; +use alloc::heap::Heap; +use core::heap::{Alloc, Layout}; use cmp; use hash::{BuildHasher, Hash, Hasher}; @@ -17,6 +18,7 @@ use mem::{align_of, size_of, needs_drop}; use mem; use ops::{Deref, DerefMut}; use ptr::{self, Unique, NonNull}; +use alloc::allocator::CollectionAllocErr; use self::BucketState::*; @@ -484,21 +486,6 @@ impl EmptyBucket table: self.table, } } - - /// Puts given key, remain value uninitialized. - /// It is only used for inplacement insertion. - pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket { - *self.raw.hash() = hash.inspect(); - let pair_ptr = self.raw.pair(); - ptr::write(&mut (*pair_ptr).0, key); - - self.table.borrow_table_mut().size += 1; - - FullBucket { - raw: self.raw, - table: self.table, - } - } } impl>> FullBucket { @@ -574,17 +561,6 @@ impl<'t, K, V> FullBucket> { v) } } - - /// Remove this bucket's `key` from the hashtable. - /// Only used for inplacement insertion. - /// NOTE: `Value` is uninitialized when this function is called, don't try to drop the `Value`. - pub unsafe fn remove_key(&mut self) { - self.table.size -= 1; - - *self.raw.hash() = EMPTY_BUCKET; - let pair_ptr = self.raw.pair(); - ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key - } } // This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases @@ -741,14 +717,15 @@ fn test_offset_calculation() { impl RawTable { /// Does not initialize the buckets. The caller should ensure they, /// at the very least, set every hash to EMPTY_BUCKET. - unsafe fn new_uninitialized(capacity: usize) -> RawTable { + /// Returns an error if it cannot allocate or capacity overflows. + unsafe fn try_new_uninitialized(capacity: usize) -> Result, CollectionAllocErr> { if capacity == 0 { - return RawTable { + return Ok(RawTable { size: 0, capacity_mask: capacity.wrapping_sub(1), hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint), marker: marker::PhantomData, - }; + }); } // No need for `checked_mul` before a more restrictive check performed @@ -768,25 +745,38 @@ impl RawTable { align_of::(), pairs_size, align_of::<(K, V)>()); - assert!(!oflo, "capacity overflow"); + if oflo { + return Err(CollectionAllocErr::CapacityOverflow); + } // One check for overflow that covers calculation and rounding of size. - let size_of_bucket = size_of::().checked_add(size_of::<(K, V)>()).unwrap(); - assert!(size >= - capacity.checked_mul(size_of_bucket) - .expect("capacity overflow"), - "capacity overflow"); + let size_of_bucket = size_of::().checked_add(size_of::<(K, V)>()) + .ok_or(CollectionAllocErr::CapacityOverflow)?; + let capacity_mul_size_of_bucket = capacity.checked_mul(size_of_bucket); + if capacity_mul_size_of_bucket.is_none() || size < capacity_mul_size_of_bucket.unwrap() { + return Err(CollectionAllocErr::CapacityOverflow); + } - let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap()) - .unwrap_or_else(|e| Heap.oom(e)); + let buffer = Heap.alloc(Layout::from_size_align(size, alignment) + .ok_or(CollectionAllocErr::CapacityOverflow)?)?; let hashes = buffer as *mut HashUint; - RawTable { + Ok(RawTable { capacity_mask: capacity.wrapping_sub(1), size: 0, hashes: TaggedHashUintPtr::new(hashes), marker: marker::PhantomData, + }) + } + + /// Does not initialize the buckets. The caller should ensure they, + /// at the very least, set every hash to EMPTY_BUCKET. + unsafe fn new_uninitialized(capacity: usize) -> RawTable { + match Self::try_new_uninitialized(capacity) { + Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), + Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e), + Ok(table) => { table } } } @@ -809,13 +799,23 @@ impl RawTable { } } + /// Tries to create a new raw table from a given capacity. If it cannot allocate, + /// it returns with AllocErr. + pub fn try_new(capacity: usize) -> Result, CollectionAllocErr> { + unsafe { + let ret = RawTable::try_new_uninitialized(capacity)?; + ptr::write_bytes(ret.hashes.ptr(), 0, capacity); + Ok(ret) + } + } + /// Creates a new raw table from a given capacity. All buckets are /// initially empty. pub fn new(capacity: usize) -> RawTable { - unsafe { - let ret = RawTable::new_uninitialized(capacity); - ptr::write_bytes(ret.hashes.ptr(), 0, capacity); - ret + match Self::try_new(capacity) { + Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), + Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e), + Ok(table) => { table } } } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index e9a150f34a51..c7ad27d8d267 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -420,7 +420,9 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::Bound; +#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")] +#[doc(hidden)] +pub use ops::Bound; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc::{BinaryHeap, BTreeMap, BTreeSet}; #[stable(feature = "rust1", since = "1.0.0")] @@ -435,8 +437,16 @@ pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_set::HashSet; -#[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::range; +#[unstable(feature = "collections_range", issue = "30877")] +#[rustc_deprecated(reason = "renamed and moved to `std::ops::RangeBounds`", since = "1.26.0")] +#[doc(hidden)] +/// Range syntax +pub mod range { + pub use ops::RangeBounds as RangeArgument; +} + +#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] +pub use alloc::allocator::CollectionAllocErr; mod hash; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c4946b6b2824..320a9f935d45 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -552,17 +552,17 @@ pub fn home_dir() -> Option { /// /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx /// -/// ``` +/// ```no_run /// use std::env; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut dir = env::temp_dir(); -/// dir.push("foo.txt"); +/// fn main() -> std::io::Result<()> { +/// let mut dir = env::temp_dir(); +/// dir.push("foo.txt"); /// -/// let f = File::create(dir)?; -/// # Ok(()) -/// # } +/// let f = File::create(dir)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index eb5022ad5776..3d0c96585b55 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -56,7 +56,6 @@ use any::TypeId; use borrow::Cow; use cell; use char; -use convert; use core::array; use fmt::{self, Debug, Display}; use mem::transmute; @@ -234,7 +233,7 @@ impl<'a> From> for Box { } } -#[unstable(feature = "never_type", issue = "35121")] +#[stable(feature = "never_type", since = "1.26.0")] impl Error for ! { fn description(&self) -> &str { *self } } @@ -276,14 +275,14 @@ impl Error for num::ParseIntError { } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl Error for num::TryFromIntError { fn description(&self) -> &str { self.__description() } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl Error for array::TryFromSliceError { fn description(&self) -> &str { self.__description() @@ -357,7 +356,7 @@ impl Error for cell::BorrowMutError { } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl Error for char::CharTryFromError { fn description(&self) -> &str { "converted integer out of range for `char`" @@ -371,14 +370,6 @@ impl Error for char::ParseCharError { } } -#[unstable(feature = "try_from", issue = "33417")] -impl Error for convert::Infallible { - fn description(&self) -> &str { - match *self { - } - } -} - // copied from any.rs impl Error + 'static { /// Returns true if the boxed type is the same as `T` diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index a760922115ae..ceb019bc95b4 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -780,7 +780,7 @@ impl f32 { unsafe { cmath::atanf(self) } } - /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. /// /// * `x = 0`, `y = 0`: `0` /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` @@ -791,12 +791,13 @@ impl f32 { /// use std::f32; /// /// let pi = f32::consts::PI; - /// // All angles from horizontal right (+x) - /// // 45 deg counter-clockwise + /// // Positive angles measured counter-clockwise + /// // from positive x axis + /// // -pi/4 radians (45 deg clockwise) /// let x1 = 3.0f32; /// let y1 = -3.0f32; /// - /// // 135 deg clockwise + /// // 3pi/4 radians (135 deg counter-clockwise) /// let x2 = -3.0f32; /// let y2 = 3.0f32; /// diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 6f34f176a971..97adf108b73b 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -716,7 +716,7 @@ impl f64 { unsafe { cmath::atan(self) } } - /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. /// /// * `x = 0`, `y = 0`: `0` /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` @@ -727,12 +727,13 @@ impl f64 { /// use std::f64; /// /// let pi = f64::consts::PI; - /// // All angles from horizontal right (+x) - /// // 45 deg counter-clockwise + /// // Positive angles measured counter-clockwise + /// // from positive x axis + /// // -pi/4 radians (45 deg clockwise) /// let x1 = 3.0_f64; /// let y1 = -3.0_f64; /// - /// // 135 deg clockwise + /// // 3pi/4 radians (135 deg counter-clockwise) /// let x2 = -3.0_f64; /// let y2 = 3.0_f64; /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 3959e8533be5..7520121a8c29 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -295,6 +295,36 @@ impl OsString { self.inner.shrink_to_fit() } + /// Shrinks the capacity of the `OsString` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + /// Converts this `OsString` into a boxed [`OsStr`]. /// /// [`OsStr`]: struct.OsStr.html diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 292a78278ab0..7bd1adc411ae 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -41,11 +41,11 @@ use time::SystemTime; /// use std::fs::File; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut file = File::create("foo.txt")?; -/// file.write_all(b"Hello, world!")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut file = File::create("foo.txt")?; +/// file.write_all(b"Hello, world!")?; +/// Ok(()) +/// } /// ``` /// /// Read the contents of a file into a [`String`]: @@ -54,13 +54,13 @@ use time::SystemTime; /// use std::fs::File; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut file = File::open("foo.txt")?; -/// let mut contents = String::new(); -/// file.read_to_string(&mut contents)?; -/// assert_eq!(contents, "Hello, world!"); -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut file = File::open("foo.txt")?; +/// let mut contents = String::new(); +/// file.read_to_string(&mut contents)?; +/// assert_eq!(contents, "Hello, world!"); +/// Ok(()) +/// } /// ``` /// /// It can be more efficient to read the contents of a file with a buffered @@ -71,14 +71,14 @@ use time::SystemTime; /// use std::io::BufReader; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let file = File::open("foo.txt")?; -/// let mut buf_reader = BufReader::new(file); -/// let mut contents = String::new(); -/// buf_reader.read_to_string(&mut contents)?; -/// assert_eq!(contents, "Hello, world!"); -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let file = File::open("foo.txt")?; +/// let mut buf_reader = BufReader::new(file); +/// let mut contents = String::new(); +/// buf_reader.read_to_string(&mut contents)?; +/// assert_eq!(contents, "Hello, world!"); +/// Ok(()) +/// } /// ``` /// /// Note that, although read and write methods require a `&mut File`, because @@ -231,7 +231,9 @@ fn initial_buffer_size(file: &File) -> usize { /// Read the entire contents of a file into a bytes vector. /// /// This is a convenience function for using [`File::open`] and [`read_to_end`] -/// with fewer imports and without an intermediate variable. +/// with fewer imports and without an intermediate variable. It pre-allocates a +/// buffer based on the file size when available, so it is generally faster than +/// reading into a vector created with `Vec::new()`. /// /// [`File::open`]: struct.File.html#method.open /// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end @@ -251,17 +253,15 @@ fn initial_buffer_size(file: &File) -> usize { /// # Examples /// /// ```no_run -/// #![feature(fs_read_write)] -/// /// use std::fs; /// use std::net::SocketAddr; /// -/// # fn foo() -> Result<(), Box> { -/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; -/// # Ok(()) -/// # } +/// fn main() -> Result<(), Box> { +/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// Ok(()) +/// } /// ``` -#[unstable(feature = "fs_read_write", issue = "46588")] +#[stable(feature = "fs_read_write_bytes", since = "1.26.0")] pub fn read>(path: P) -> io::Result> { let mut file = File::open(path)?; let mut bytes = Vec::with_capacity(initial_buffer_size(&file)); @@ -272,7 +272,9 @@ pub fn read>(path: P) -> io::Result> { /// Read the entire contents of a file into a string. /// /// This is a convenience function for using [`File::open`] and [`read_to_string`] -/// with fewer imports and without an intermediate variable. +/// with fewer imports and without an intermediate variable. It pre-allocates a +/// buffer based on the file size when available, so it is generally faster than +/// reading into a string created with `String::new()`. /// /// [`File::open`]: struct.File.html#method.open /// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string @@ -298,13 +300,13 @@ pub fn read>(path: P) -> io::Result> { /// use std::fs; /// use std::net::SocketAddr; /// -/// # fn foo() -> Result<(), Box> { -/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; -/// # Ok(()) -/// # } +/// fn main() -> Result<(), Box> { +/// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; +/// Ok(()) +/// } /// ``` -#[unstable(feature = "fs_read_write", issue = "46588")] -pub fn read_string>(path: P) -> io::Result { +#[stable(feature = "fs_read_write", since = "1.26.0")] +pub fn read_to_string>(path: P) -> io::Result { let mut file = File::open(path)?; let mut string = String::with_capacity(initial_buffer_size(&file)); file.read_to_string(&mut string)?; @@ -325,16 +327,14 @@ pub fn read_string>(path: P) -> io::Result { /// # Examples /// /// ```no_run -/// #![feature(fs_read_write)] -/// /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::write("foo.txt", b"Lorem ipsum")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::write("foo.txt", b"Lorem ipsum")?; +/// Ok(()) +/// } /// ``` -#[unstable(feature = "fs_read_write", issue = "46588")] +#[stable(feature = "fs_read_write_bytes", since = "1.26.0")] pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { File::create(path)?.write_all(contents.as_ref()) } @@ -356,7 +356,7 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { + /// fn main() -> std::io::Result<()> { /// let mut f = File::open("foo.txt")?; /// # Ok(()) /// # } @@ -380,10 +380,10 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create>(path: P) -> io::Result { @@ -401,13 +401,13 @@ impl File { /// use std::fs::File; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.write_all(b"Hello, world!")?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.write_all(b"Hello, world!")?; /// - /// f.sync_all()?; - /// # Ok(()) - /// # } + /// f.sync_all()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_all(&self) -> io::Result<()> { @@ -432,13 +432,13 @@ impl File { /// use std::fs::File; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.write_all(b"Hello, world!")?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.write_all(b"Hello, world!")?; /// - /// f.sync_data()?; - /// # Ok(()) - /// # } + /// f.sync_data()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_data(&self) -> io::Result<()> { @@ -453,6 +453,10 @@ impl File { /// will be extended to `size` and have all of the intermediate data filled /// in with 0s. /// + /// The file's cursor isn't changed. In particular, if the cursor was at the + /// end and the file is shrunk using this operation, the cursor will now be + /// past the end. + /// /// # Errors /// /// This function will return an error if the file is not opened for writing. @@ -462,11 +466,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.set_len(10)?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.set_len(10)?; + /// Ok(()) + /// } /// ``` /// /// Note that this method alters the content of the underlying file, even @@ -483,11 +487,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let metadata = f.metadata()?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let metadata = f.metadata()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata(&self) -> io::Result { @@ -505,11 +509,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let file_copy = file.try_clone()?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let file_copy = file.try_clone()?; + /// Ok(()) + /// } /// ``` /// /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create @@ -521,17 +525,17 @@ impl File { /// use std::io::SeekFrom; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut file_copy = file.try_clone()?; + /// fn main() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut file_copy = file.try_clone()?; /// - /// file.seek(SeekFrom::Start(3))?; + /// file.seek(SeekFrom::Start(3))?; /// - /// let mut contents = vec![]; - /// file_copy.read_to_end(&mut contents)?; - /// assert_eq!(contents, b"def\n"); - /// # Ok(()) - /// # } + /// let mut contents = vec![]; + /// file_copy.read_to_end(&mut contents)?; + /// assert_eq!(contents, b"def\n"); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_try_clone", since = "1.9.0")] pub fn try_clone(&self) -> io::Result { @@ -558,16 +562,16 @@ impl File { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs::File; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs::File; /// - /// let file = File::open("foo.txt")?; - /// let mut perms = file.metadata()?.permissions(); - /// perms.set_readonly(true); - /// file.set_permissions(perms)?; - /// # Ok(()) - /// # } + /// let file = File::open("foo.txt")?; + /// let mut perms = file.metadata()?.permissions(); + /// perms.set_readonly(true); + /// file.set_permissions(perms)?; + /// Ok(()) + /// } /// ``` /// /// Note that this method alters the permissions of the underlying file, @@ -887,51 +891,63 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// let metadata = fs::metadata("foo.txt")?; /// - /// println!("{:?}", metadata.file_type()); - /// # Ok(()) - /// # } + /// println!("{:?}", metadata.file_type()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn file_type(&self) -> FileType { FileType(self.0.file_type()) } - /// Returns whether this metadata is for a directory. + /// Returns whether this metadata is for a directory. The + /// result is mutually exclusive to the result of + /// [`is_file`], and will be false for symlink metadata + /// obtained from [`symlink_metadata`]. + /// + /// [`is_file`]: struct.Metadata.html#method.is_file + /// [`symlink_metadata`]: fn.symlink_metadata.html /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(!metadata.is_dir()); - /// # Ok(()) - /// # } + /// assert!(!metadata.is_dir()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() } - /// Returns whether this metadata is for a regular file. + /// Returns whether this metadata is for a regular file. The + /// result is mutually exclusive to the result of + /// [`is_dir`], and will be false for symlink metadata + /// obtained from [`symlink_metadata`]. + /// + /// [`is_dir`]: struct.Metadata.html#method.is_dir + /// [`symlink_metadata`]: fn.symlink_metadata.html /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(metadata.is_file()); - /// # Ok(()) - /// # } + /// assert!(metadata.is_file()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.file_type().is_file() } @@ -940,15 +956,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert_eq!(0, metadata.len()); - /// # Ok(()) - /// # } + /// assert_eq!(0, metadata.len()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> u64 { self.0.size() } @@ -957,15 +973,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(!metadata.permissions().readonly()); - /// # Ok(()) - /// # } + /// assert!(!metadata.permissions().readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn permissions(&self) -> Permissions { @@ -984,19 +1000,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.modified() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.modified() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn modified(&self) -> io::Result { @@ -1019,19 +1035,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.accessed() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.accessed() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn accessed(&self) -> io::Result { @@ -1050,19 +1066,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.created() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.created() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn created(&self) -> io::Result { @@ -1094,16 +1110,16 @@ impl Permissions { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; /// - /// assert_eq!(false, metadata.permissions().readonly()); - /// # Ok(()) - /// # } + /// assert_eq!(false, metadata.permissions().readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() } @@ -1119,23 +1135,23 @@ impl Permissions { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_readonly(true); + /// permissions.set_readonly(true); /// - /// // filesystem doesn't change - /// assert_eq!(false, metadata.permissions().readonly()); + /// // filesystem doesn't change + /// assert_eq!(false, metadata.permissions().readonly()); /// - /// // just this particular `permissions`. - /// assert_eq!(true, permissions.readonly()); - /// # Ok(()) - /// # } + /// // just this particular `permissions`. + /// assert_eq!(true, permissions.readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_readonly(&mut self, readonly: bool) { @@ -1144,43 +1160,58 @@ impl Permissions { } impl FileType { - /// Test whether this file type represents a directory. + /// Test whether this file type represents a directory. The + /// result is mutually exclusive to the results of + /// [`is_file`] and [`is_symlink`]; only zero or one of these + /// tests may pass. + /// + /// [`is_file`]: struct.FileType.html#method.is_file + /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// let metadata = fs::metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_dir(), false); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_dir(), false); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() } /// Test whether this file type represents a regular file. + /// The result is mutually exclusive to the results of + /// [`is_dir`] and [`is_symlink`]; only zero or one of these + /// tests may pass. + /// + /// [`is_dir`]: struct.FileType.html#method.is_dir + /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// let metadata = fs::metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_file(), true); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_file(), true); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_file(&self) -> bool { self.0.is_file() } /// Test whether this file type represents a symbolic link. + /// The result is mutually exclusive to the results of + /// [`is_dir`] and [`is_file`]; only zero or one of these + /// tests may pass. /// /// The underlying [`Metadata`] struct needs to be retrieved /// with the [`fs::symlink_metadata`] function and not the @@ -1191,20 +1222,22 @@ impl FileType { /// [`Metadata`]: struct.Metadata.html /// [`fs::metadata`]: fn.metadata.html /// [`fs::symlink_metadata`]: fn.symlink_metadata.html + /// [`is_dir`]: struct.FileType.html#method.is_dir + /// [`is_file`]: struct.FileType.html#method.is_file /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::symlink_metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::symlink_metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_symlink(), false); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_symlink(), false); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_symlink(&self) -> bool { self.0.is_symlink() } @@ -1241,15 +1274,16 @@ impl DirEntry { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; - /// # fn foo() -> std::io::Result<()> { - /// for entry in fs::read_dir(".")? { - /// let dir = entry?; - /// println!("{:?}", dir.path()); + /// + /// fn main() -> std::io::Result<()> { + /// for entry in fs::read_dir(".")? { + /// let dir = entry?; + /// println!("{:?}", dir.path()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` /// /// This prints output like: @@ -1394,13 +1428,13 @@ impl AsInner for DirEntry { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_file("a.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_file("a.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { @@ -1431,14 +1465,14 @@ pub fn remove_file>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ```rust -/// # fn foo() -> std::io::Result<()> { +/// ```rust,no_run /// use std::fs; /// -/// let attr = fs::metadata("/some/file/path.txt")?; -/// // inspect attr ... -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let attr = fs::metadata("/some/file/path.txt")?; +/// // inspect attr ... +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata>(path: P) -> io::Result { @@ -1465,14 +1499,14 @@ pub fn metadata>(path: P) -> io::Result { /// /// # Examples /// -/// ```rust -/// # fn foo() -> std::io::Result<()> { +/// ```rust,no_run /// use std::fs; /// -/// let attr = fs::symlink_metadata("/some/file/path.txt")?; -/// // inspect attr ... -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let attr = fs::symlink_metadata("/some/file/path.txt")?; +/// // inspect attr ... +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata>(path: P) -> io::Result { @@ -1509,13 +1543,13 @@ pub fn symlink_metadata>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { @@ -1560,9 +1594,10 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt -/// # Ok(()) } +/// fn main() -> std::io::Result<()> { +/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { @@ -1591,13 +1626,13 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { @@ -1614,13 +1649,13 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::soft_link("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::soft_link("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.1.0", @@ -1651,13 +1686,13 @@ pub fn soft_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// let path = fs::read_link("a.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let path = fs::read_link("a.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link>(path: P) -> io::Result { @@ -1685,13 +1720,13 @@ pub fn read_link>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// let path = fs::canonicalize("../a/../foo.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let path = fs::canonicalize("../a/../foo.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "fs_canonicalize", since = "1.5.0")] pub fn canonicalize>(path: P) -> io::Result { @@ -1718,13 +1753,13 @@ pub fn canonicalize>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::create_dir("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::create_dir("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir>(path: P) -> io::Result<()> { @@ -1760,13 +1795,13 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::create_dir_all("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::create_dir_all("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir_all>(path: P) -> io::Result<()> { @@ -1793,13 +1828,13 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_dir("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_dir("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { @@ -1827,13 +1862,13 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_dir_all("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_dir_all("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir_all>(path: P) -> io::Result<()> { @@ -1913,15 +1948,15 @@ pub fn read_dir>(path: P) -> io::Result { /// /// # Examples /// -/// ``` -/// # fn foo() -> std::io::Result<()> { +/// ```no_run /// use std::fs; /// -/// let mut perms = fs::metadata("foo.txt")?.permissions(); -/// perms.set_readonly(true); -/// fs::set_permissions("foo.txt", perms)?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut perms = fs::metadata("foo.txt")?.permissions(); +/// perms.set_readonly(true); +/// fs::set_permissions("foo.txt", perms)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions>(path: P, perm: Permissions) @@ -3091,12 +3126,12 @@ mod tests { assert!(v == &bytes[..]); check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF])); - error_contains!(fs::read_string(&tmpdir.join("not-utf8")), + error_contains!(fs::read_to_string(&tmpdir.join("not-utf8")), "stream did not contain valid UTF-8"); let s = "𐁁𐀓𐀠𐀴𐀍"; check!(fs::write(&tmpdir.join("utf8"), s.as_bytes())); - let string = check!(fs::read_string(&tmpdir.join("utf8"))); + let string = check!(fs::read_to_string(&tmpdir.join("utf8"))); assert_eq!(string, s); } diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs index 4d5e4df6f95b..4a391372c3a1 100644 --- a/src/libstd/heap.rs +++ b/src/libstd/heap.rs @@ -12,8 +12,9 @@ #![unstable(issue = "32838", feature = "allocator_api")] -pub use alloc::heap::{Heap, Alloc, Layout, Excess, CannotReallocInPlace, AllocErr}; +pub use alloc::heap::Heap; pub use alloc_system::System; +pub use core::heap::*; #[cfg(not(test))] #[doc(hidden)] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 9250c1c437b2..d6eac7483348 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -25,26 +25,32 @@ use memchr; /// results in a system call. A `BufReader` performs large, infrequent reads on /// the underlying [`Read`] and maintains an in-memory buffer of the results. /// +/// `BufReader` can improve the speed of programs that make *small* and +/// *repeated* read calls to the same file or network socket. It does not +/// help when reading very large amounts at once, or reading just one or a few +/// times. It also provides no advantage when reading from a source that is +/// already in memory, like a `Vec`. +/// /// [`Read`]: ../../std/io/trait.Read.html /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read /// [`TcpStream`]: ../../std/net/struct.TcpStream.html /// /// # Examples /// -/// ``` +/// ```no_run /// use std::io::prelude::*; /// use std::io::BufReader; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let f = File::open("log.txt")?; -/// let mut reader = BufReader::new(f); +/// fn main() -> std::io::Result<()> { +/// let f = File::open("log.txt")?; +/// let mut reader = BufReader::new(f); /// -/// let mut line = String::new(); -/// let len = reader.read_line(&mut line)?; -/// println!("First line is {} bytes long", len); -/// # Ok(()) -/// # } +/// let mut line = String::new(); +/// let len = reader.read_line(&mut line)?; +/// println!("First line is {} bytes long", len); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct BufReader { @@ -59,15 +65,15 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let reader = BufReader::new(f); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::new(f); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: R) -> BufReader { @@ -80,15 +86,15 @@ impl BufReader { /// /// Creating a buffer with ten bytes of capacity: /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let reader = BufReader::with_capacity(10, f); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::with_capacity(10, f); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: R) -> BufReader { @@ -111,17 +117,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); /// - /// let f2 = reader.get_ref(); - /// # Ok(()) - /// # } + /// let f2 = reader.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &R { &self.inner } @@ -132,17 +138,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let mut reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let mut reader = BufReader::new(f1); /// - /// let f2 = reader.get_mut(); - /// # Ok(()) - /// # } + /// let f2 = reader.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut R { &mut self.inner } @@ -150,26 +156,55 @@ impl BufReader { /// Returns `true` if there are no bytes in the internal buffer. /// /// # Examples - /// ``` + // + /// ```no_run /// # #![feature(bufreader_is_empty)] /// use std::io::BufReader; /// use std::io::BufRead; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let mut reader = BufReader::new(f1); - /// assert!(reader.is_empty()); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let mut reader = BufReader::new(f1); + /// assert!(reader.is_empty()); /// - /// if reader.fill_buf()?.len() > 0 { - /// assert!(!reader.is_empty()); + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.is_empty()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")] + #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")] pub fn is_empty(&self) -> bool { - self.pos == self.cap + self.buffer().is_empty() + } + + /// Returns a reference to the internally buffered data. + /// + /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty. + /// + /// # Examples + /// + /// ```no_run + /// # #![feature(bufreader_buffer)] + /// use std::io::{BufReader, BufRead}; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let mut reader = BufReader::new(f); + /// assert!(reader.buffer().is_empty()); + /// + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.buffer().is_empty()); + /// } + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "bufreader_buffer", issue = "45323")] + pub fn buffer(&self) -> &[u8] { + &self.buf[self.pos..self.cap] } /// Unwraps this `BufReader`, returning the underlying reader. @@ -178,17 +213,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); /// - /// let f2 = reader.into_inner(); - /// # Ok(()) - /// # } + /// let f2 = reader.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> R { self.inner } @@ -330,6 +365,12 @@ impl Seek for BufReader { /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// +/// `BufWriter` can improve the speed of programs that make *small* and +/// *repeated* write calls to the same file or network socket. It does not +/// help when writing very large amounts at once, or writing just one or a few +/// times. It also provides no advantage when writing to a destination that is +/// in memory, like a `Vec`. +/// /// When the `BufWriter` is dropped, the contents of its buffer will be written /// out. However, any errors that happen in the process of flushing the buffer /// when the writer is dropped will be ignored. Code that wishes to handle such @@ -696,34 +737,34 @@ impl fmt::Display for IntoInnerError { /// We can use `LineWriter` to write one line at a time, significantly /// reducing the number of actual writes to the file. /// -/// ``` +/// ```no_run /// use std::fs::File; /// use std::io::prelude::*; /// use std::io::LineWriter; /// -/// # fn foo() -> std::io::Result<()> { -/// let road_not_taken = b"I shall be telling this with a sigh +/// fn main() -> std::io::Result<()> { +/// let road_not_taken = b"I shall be telling this with a sigh /// Somewhere ages and ages hence: /// Two roads diverged in a wood, and I - /// I took the one less traveled by, /// And that has made all the difference."; /// -/// let file = File::create("poem.txt")?; -/// let mut file = LineWriter::new(file); +/// let file = File::create("poem.txt")?; +/// let mut file = LineWriter::new(file); /// -/// for &byte in road_not_taken.iter() { -/// file.write(&[byte]).unwrap(); +/// for &byte in road_not_taken.iter() { +/// file.write(&[byte]).unwrap(); +/// } +/// +/// // let's check we did the right thing. +/// let mut file = File::open("poem.txt")?; +/// let mut contents = String::new(); +/// +/// file.read_to_string(&mut contents)?; +/// +/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); +/// Ok(()) /// } -/// -/// // let's check we did the right thing. -/// let mut file = File::open("poem.txt")?; -/// let mut contents = String::new(); -/// -/// file.read_to_string(&mut contents)?; -/// -/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); -/// # Ok(()) -/// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct LineWriter { @@ -736,15 +777,15 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> LineWriter { @@ -757,15 +798,15 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::with_capacity(100, file); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::with_capacity(100, file); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> LineWriter { @@ -779,17 +820,17 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); /// - /// let reference = file.get_ref(); - /// # Ok(()) - /// # } + /// let reference = file.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.get_ref() } @@ -801,18 +842,18 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let mut file = LineWriter::new(file); + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let mut file = LineWriter::new(file); /// - /// // we can use reference just like file - /// let reference = file.get_mut(); - /// # Ok(()) - /// # } + /// // we can use reference just like file + /// let reference = file.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } @@ -827,18 +868,18 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; /// - /// let writer: LineWriter = LineWriter::new(file); + /// let writer: LineWriter = LineWriter::new(file); /// - /// let file: File = writer.into_inner()?; - /// # Ok(()) - /// # } + /// let file: File = writer.into_inner()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result>> { diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 76bcb5fedc94..2673f3ccfa3a 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -10,7 +10,6 @@ use io::prelude::*; -use core::convert::TryInto; use cmp; use io::{self, Initializer, SeekFrom, Error, ErrorKind}; @@ -260,9 +259,26 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result Result { + if n <= (::max_value() as u64) { + Ok(n as usize) + } else { + Err(()) + } +} + +#[cfg(any(target_pointer_width = "64"))] +fn try_into(n: u64) -> Result { + Ok(n as usize) +} + // Resizing write implementation fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result { - let pos: usize = (*pos_mut).try_into().map_err(|_| { + let pos: usize = try_into(*pos_mut).map_err(|_| { Error::new(ErrorKind::InvalidInput, "cursor position exceeds maximum possible vector length") })?; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d403bf6bfe53..3b8c42ddb39d 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -24,21 +24,21 @@ //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on //! [`File`]s: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let mut f = File::open("foo.txt")?; -//! let mut buffer = [0; 10]; +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; //! -//! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! // read up to 10 bytes +//! f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); -//! # Ok(()) -//! # } +//! println!("The bytes: {:?}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`Read`] and [`Write`] are so important, implementors of the two traits have a @@ -52,25 +52,25 @@ //! how the reading happens. [`Seek`] lets you control where the next byte is //! coming from: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::SeekFrom; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let mut f = File::open("foo.txt")?; -//! let mut buffer = [0; 10]; +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; //! -//! // skip to the last 10 bytes of the file -//! f.seek(SeekFrom::End(-10))?; +//! // skip to the last 10 bytes of the file +//! f.seek(SeekFrom::End(-10))?; //! -//! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! // read up to 10 bytes +//! f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); -//! # Ok(()) -//! # } +//! println!("The bytes: {:?}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but @@ -87,70 +87,70 @@ //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra //! methods to any reader: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufReader; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::open("foo.txt")?; -//! let mut reader = BufReader::new(f); -//! let mut buffer = String::new(); +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let mut reader = BufReader::new(f); +//! let mut buffer = String::new(); //! -//! // read a line into buffer -//! reader.read_line(&mut buffer)?; +//! // read a line into buffer +//! reader.read_line(&mut buffer)?; //! -//! println!("{}", buffer); -//! # Ok(()) -//! # } +//! println!("{}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call //! to [`write`][`Write::write`]: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufWriter; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::create("foo.txt")?; -//! { -//! let mut writer = BufWriter::new(f); +//! fn main() -> io::Result<()> { +//! let f = File::create("foo.txt")?; +//! { +//! let mut writer = BufWriter::new(f); //! -//! // write a byte to the buffer -//! writer.write(&[42])?; +//! // write a byte to the buffer +//! writer.write(&[42])?; //! -//! } // the buffer is flushed once writer goes out of scope +//! } // the buffer is flushed once writer goes out of scope //! -//! # Ok(()) -//! # } +//! Ok(()) +//! } //! ``` //! //! ## Standard input and output //! //! A very common source of input is standard input: //! -//! ``` +//! ```no_run //! use std::io; //! -//! # fn foo() -> io::Result<()> { -//! let mut input = String::new(); +//! fn main() -> io::Result<()> { +//! let mut input = String::new(); //! -//! io::stdin().read_line(&mut input)?; +//! io::stdin().read_line(&mut input)?; //! -//! println!("You typed: {}", input.trim()); -//! # Ok(()) -//! # } +//! println!("You typed: {}", input.trim()); +//! Ok(()) +//! } //! ``` //! //! Note that you cannot use the [`?` operator] in functions that do not return //! a [`Result`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`] //! or `match` on the return value to catch any possible errors: //! -//! ``` +//! ```no_run //! use std::io; //! //! let mut input = String::new(); @@ -160,14 +160,14 @@ //! //! And a very common source of output is standard output: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! -//! # fn foo() -> io::Result<()> { -//! io::stdout().write(&[42])?; -//! # Ok(()) -//! # } +//! fn main() -> io::Result<()> { +//! io::stdout().write(&[42])?; +//! Ok(()) +//! } //! ``` //! //! Of course, using [`io::stdout`] directly is less common than something like @@ -179,22 +179,21 @@ //! ways of iterating over I/O. For example, [`Lines`] is used to split over //! lines: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufReader; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::open("foo.txt")?; -//! let reader = BufReader::new(f); +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let reader = BufReader::new(f); //! -//! for line in reader.lines() { -//! println!("{}", line?); +//! for line in reader.lines() { +//! println!("{}", line?); +//! } +//! Ok(()) //! } -//! -//! # Ok(()) -//! # } //! ``` //! //! ## Functions @@ -203,13 +202,13 @@ //! features. For example, we can use three of these functions to copy everything //! from standard input to standard output: //! -//! ``` +//! ```no_run //! use std::io; //! -//! # fn foo() -> io::Result<()> { -//! io::copy(&mut io::stdin(), &mut io::stdout())?; -//! # Ok(()) -//! # } +//! fn main() -> io::Result<()> { +//! io::copy(&mut io::stdin(), &mut io::stdout())?; +//! Ok(()) +//! } //! ``` //! //! [functions-list]: #functions-1 @@ -416,47 +415,47 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result /// /// [`File`]s implement `Read`: /// -/// ``` -/// # use std::io; +/// ```no_run +/// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> io::Result<()> { -/// let mut f = File::open("foo.txt")?; -/// let mut buffer = [0; 10]; +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; +/// let mut buffer = [0; 10]; /// -/// // read up to 10 bytes -/// f.read(&mut buffer)?; +/// // read up to 10 bytes +/// f.read(&mut buffer)?; /// -/// let mut buffer = vec![0; 10]; -/// // read the whole file -/// f.read_to_end(&mut buffer)?; +/// let mut buffer = vec![0; 10]; +/// // read the whole file +/// f.read_to_end(&mut buffer)?; /// -/// // read into a String, so that you don't need to do the conversion. -/// let mut buffer = String::new(); -/// f.read_to_string(&mut buffer)?; +/// // read into a String, so that you don't need to do the conversion. +/// let mut buffer = String::new(); +/// f.read_to_string(&mut buffer)?; /// -/// // and more! See the other methods for more details. -/// # Ok(()) -/// # } +/// // and more! See the other methods for more details. +/// Ok(()) +/// } /// ``` /// /// Read from [`&str`] because [`&[u8]`][slice] implements `Read`: /// -/// ``` +/// ```no_run /// # use std::io; /// use std::io::prelude::*; /// -/// # fn foo() -> io::Result<()> { -/// let mut b = "This string will be read".as_bytes(); -/// let mut buffer = [0; 10]; +/// fn main() -> io::Result<()> { +/// let mut b = "This string will be read".as_bytes(); +/// let mut buffer = [0; 10]; /// -/// // read up to 10 bytes -/// b.read(&mut buffer)?; +/// // read up to 10 bytes +/// b.read(&mut buffer)?; /// -/// // etc... it works exactly as a File does! -/// # Ok(()) -/// # } +/// // etc... it works exactly as a File does! +/// Ok(()) +/// } /// ``` /// /// [`read()`]: trait.Read.html#tymethod.read @@ -509,19 +508,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`File`]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // read up to 10 bytes - /// f.read(&mut buffer[..])?; - /// # Ok(()) - /// # } + /// // read up to 10 bytes + /// f.read(&mut buffer[..])?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result; @@ -582,20 +581,25 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`File`]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = Vec::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); /// - /// // read the whole file - /// f.read_to_end(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read the whole file + /// f.read_to_end(&mut buffer)?; + /// Ok(()) + /// } /// ``` + /// + /// (See also the [`std::fs::read`] convenience function for reading from a + /// file.) + /// + /// [`std::fs::read`]: ../fs/fn.read.html #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { read_to_end(self, buf) @@ -621,19 +625,24 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = String::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = String::new(); /// - /// f.read_to_string(&mut buffer)?; - /// # Ok(()) - /// # } + /// f.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` + /// + /// (See also the [`std::fs::read_to_string`] convenience function for + /// reading from a file.) + /// + /// [`std::fs::read_to_string`]: ../fs/fn.read_to_string.html #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result { // Note that we do *not* call `.read_to_end()` here. We are passing @@ -683,19 +692,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // read exactly 10 bytes - /// f.read_exact(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read exactly 10 bytes + /// f.read_exact(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "read_exact", since = "1.6.0")] fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { @@ -726,28 +735,28 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::Read; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = Vec::new(); - /// let mut other_buffer = Vec::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); + /// let mut other_buffer = Vec::new(); /// - /// { - /// let reference = f.by_ref(); + /// { + /// let reference = f.by_ref(); /// - /// // read at most 5 bytes - /// reference.take(5).read_to_end(&mut buffer)?; + /// // read at most 5 bytes + /// reference.take(5).read_to_end(&mut buffer)?; /// - /// } // drop our &mut reference so we can use f again + /// } // drop our &mut reference so we can use f again /// - /// // original file still usable, read the rest - /// f.read_to_end(&mut other_buffer)?; - /// # Ok(()) - /// # } + /// // original file still usable, read the rest + /// f.read_to_end(&mut other_buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } @@ -772,19 +781,19 @@ pub trait Read { /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`None`]: ../../std/option/enum.Option.html#variant.None /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; /// - /// for byte in f.bytes() { - /// println!("{}", byte.unwrap()); + /// for byte in f.bytes() { + /// println!("{}", byte.unwrap()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn bytes(self) -> Bytes where Self: Sized { @@ -812,20 +821,20 @@ pub trait Read { /// [`char`]: ../../std/primitive.char.html /// [`None`]: ../../std/option/enum.Option.html#variant.None /// - /// ``` + /// ```no_run /// #![feature(io)] /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; /// - /// for c in f.chars() { - /// println!("{}", c.unwrap()); + /// for c in f.chars() { + /// println!("{}", c.unwrap()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "io", reason = "the semantics of a partial read/write \ of where errors happen is currently \ @@ -847,23 +856,23 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f1 = File::open("foo.txt")?; - /// let mut f2 = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f1 = File::open("foo.txt")?; + /// let mut f2 = File::open("bar.txt")?; /// - /// let mut handle = f1.chain(f2); - /// let mut buffer = String::new(); + /// let mut handle = f1.chain(f2); + /// let mut buffer = String::new(); /// - /// // read the value into a String. We could use any Read method here, - /// // this is just one example. - /// handle.read_to_string(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read the value into a String. We could use any Read method here, + /// // this is just one example. + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn chain(self, next: R) -> Chain where Self: Sized { @@ -885,21 +894,21 @@ pub trait Read { /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok /// [`read()`]: trait.Read.html#tymethod.read /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 5]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 5]; /// - /// // read at most five bytes - /// let mut handle = f.take(5); + /// // read at most five bytes + /// let mut handle = f.take(5); /// - /// handle.read(&mut buffer)?; - /// # Ok(()) - /// # } + /// handle.read(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn take(self, limit: u64) -> Take where Self: Sized { @@ -974,16 +983,16 @@ impl Initializer { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut buffer = File::create("foo.txt")?; +/// fn main() -> std::io::Result<()> { +/// let mut buffer = File::create("foo.txt")?; /// -/// buffer.write(b"some bytes")?; -/// # Ok(()) -/// # } +/// buffer.write(b"some bytes")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[doc(spotlight)] @@ -1022,17 +1031,17 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // Writes some prefix of the byte string, not necessarily all of it. - /// buffer.write(b"some bytes")?; - /// # Ok(()) - /// # } + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, buf: &[u8]) -> Result; @@ -1047,18 +1056,18 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::io::BufWriter; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = BufWriter::new(File::create("foo.txt")?); + /// fn main() -> std::io::Result<()> { + /// let mut buffer = BufWriter::new(File::create("foo.txt")?); /// - /// buffer.write(b"some bytes")?; - /// buffer.flush()?; - /// # Ok(()) - /// # } + /// buffer.write(b"some bytes")?; + /// buffer.flush()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn flush(&mut self) -> Result<()>; @@ -1082,16 +1091,16 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// buffer.write_all(b"some bytes")?; - /// # Ok(()) - /// # } + /// buffer.write_all(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { @@ -1131,19 +1140,19 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // this call - /// write!(buffer, "{:.*}", 2, 1.234567)?; - /// // turns into this: - /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; - /// # Ok(()) - /// # } + /// // this call + /// write!(buffer, "{:.*}", 2, 1.234567)?; + /// // turns into this: + /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { @@ -1187,19 +1196,19 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::Write; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// let reference = buffer.by_ref(); + /// let reference = buffer.by_ref(); /// - /// // we can use reference just like our original buffer - /// reference.write_all(b"some bytes")?; - /// # Ok(()) - /// # } + /// // we can use reference just like our original buffer + /// reference.write_all(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } @@ -1217,19 +1226,19 @@ pub trait Write { /// /// [file]: ../fs/struct.File.html /// -/// ``` +/// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// use std::io::SeekFrom; /// -/// # fn foo() -> io::Result<()> { -/// let mut f = File::open("foo.txt")?; +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; /// -/// // move the cursor 42 bytes from the start of the file -/// f.seek(SeekFrom::Start(42))?; -/// # Ok(()) -/// # } +/// // move the cursor 42 bytes from the start of the file +/// f.seek(SeekFrom::Start(42))?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Seek { @@ -1320,7 +1329,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// A locked standard input implements `BufRead`: /// -/// ``` +/// ```no_run /// use std::io; /// use std::io::prelude::*; /// @@ -1342,21 +1351,21 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// [`lines`]: #method.lines /// [`Read`]: trait.Read.html /// -/// ``` +/// ```no_run /// use std::io::{self, BufReader}; /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> io::Result<()> { -/// let f = File::open("foo.txt")?; -/// let f = BufReader::new(f); +/// fn main() -> io::Result<()> { +/// let f = File::open("foo.txt")?; +/// let f = BufReader::new(f); /// -/// for line in f.lines() { -/// println!("{}", line.unwrap()); +/// for line in f.lines() { +/// println!("{}", line.unwrap()); +/// } +/// +/// Ok(()) /// } -/// -/// # Ok(()) -/// # } /// ``` /// #[stable(feature = "rust1", since = "1.0.0")] @@ -1383,7 +1392,7 @@ pub trait BufRead: Read { /// /// A locked standard input implements `BufRead`: /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// @@ -1645,19 +1654,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.into_inner(); - /// # Ok(()) - /// # } + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn into_inner(self) -> (T, U) { @@ -1668,19 +1677,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_ref(); - /// # Ok(()) - /// # } + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> (&T, &U) { @@ -1695,19 +1704,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let mut chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_mut(); - /// # Ok(()) - /// # } + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> (&mut T, &mut U) { @@ -1794,20 +1803,20 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; /// - /// // read at most five bytes - /// let handle = f.take(5); + /// // read at most five bytes + /// let handle = f.take(5); /// - /// println!("limit: {}", handle.limit()); - /// # Ok(()) - /// # } + /// println!("limit: {}", handle.limit()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } @@ -1819,22 +1828,22 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// #![feature(take_set_limit)] /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; /// - /// // read at most five bytes - /// let mut handle = f.take(5); - /// handle.set_limit(10); + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); /// - /// assert_eq!(handle.limit(), 10); - /// # Ok(()) - /// # } + /// assert_eq!(handle.limit(), 10); + /// Ok(()) + /// } /// ``` #[unstable(feature = "take_set_limit", issue = "42781")] pub fn set_limit(&mut self, limit: u64) { @@ -1845,21 +1854,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.into_inner(); - /// # Ok(()) - /// # } + /// let file = handle.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "io_take_into_inner", since = "1.15.0")] pub fn into_inner(self) -> T { @@ -1870,21 +1879,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.get_ref(); - /// # Ok(()) - /// # } + /// let file = handle.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> &T { @@ -1899,21 +1908,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.get_mut(); - /// # Ok(()) - /// # } + /// let file = handle.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> &mut T { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1f73054e3bee..2472bed5ba43 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -171,29 +171,29 @@ pub struct StdinLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Read}; /// -/// # fn foo() -> io::Result { -/// let mut buffer = String::new(); -/// io::stdin().read_to_string(&mut buffer)?; -/// # Ok(buffer) -/// # } +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// io::stdin().read_to_string(&mut buffer)?; +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Read}; /// -/// # fn foo() -> io::Result { -/// let mut buffer = String::new(); -/// let stdin = io::stdin(); -/// let mut handle = stdin.lock(); +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// let stdin = io::stdin(); +/// let mut handle = stdin.lock(); /// -/// handle.read_to_string(&mut buffer)?; -/// # Ok(buffer) -/// # } +/// handle.read_to_string(&mut buffer)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { @@ -225,17 +225,17 @@ impl Stdin { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::{self, Read}; /// - /// # fn foo() -> io::Result { - /// let mut buffer = String::new(); - /// let stdin = io::stdin(); - /// let mut handle = stdin.lock(); + /// fn main() -> io::Result<()> { + /// let mut buffer = String::new(); + /// let stdin = io::stdin(); + /// let mut handle = stdin.lock(); /// - /// handle.read_to_string(&mut buffer)?; - /// # Ok(buffer) - /// # } + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock { @@ -369,29 +369,29 @@ pub struct StdoutLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// io::stdout().write(b"hello world")?; +/// fn main() -> io::Result<()> { +/// io::stdout().write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// let stdout = io::stdout(); -/// let mut handle = stdout.lock(); +/// fn main() -> io::Result<()> { +/// let stdout = io::stdout(); +/// let mut handle = stdout.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { @@ -419,17 +419,17 @@ impl Stdout { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::{self, Write}; /// - /// # fn foo() -> io::Result<()> { - /// let stdout = io::stdout(); - /// let mut handle = stdout.lock(); + /// fn main() -> io::Result<()> { + /// let stdout = io::stdout(); + /// let mut handle = stdout.lock(); /// - /// handle.write(b"hello world")?; + /// handle.write(b"hello world")?; /// - /// # Ok(()) - /// # } + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock { @@ -505,29 +505,29 @@ pub struct StderrLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// io::stderr().write(b"hello world")?; +/// fn main() -> io::Result<()> { +/// io::stderr().write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// let stderr = io::stderr(); -/// let mut handle = stderr.lock(); +/// fn main() -> io::Result<()> { +/// let stderr = io::stderr(); +/// let mut handle = stderr.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 45d281ee34ac..195310a26fed 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -34,16 +34,15 @@ use mem; /// ``` /// use std::io; /// -/// # fn foo() -> io::Result<()> { -/// let mut reader: &[u8] = b"hello"; -/// let mut writer: Vec = vec![]; +/// fn main() -> io::Result<()> { +/// let mut reader: &[u8] = b"hello"; +/// let mut writer: Vec = vec![]; /// -/// io::copy(&mut reader, &mut writer)?; +/// io::copy(&mut reader, &mut writer)?; /// -/// assert_eq!(&b"hello"[..], &writer[..]); -/// # Ok(()) -/// # } -/// # foo().unwrap(); +/// assert_eq!(&b"hello"[..], &writer[..]); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy(reader: &mut R, writer: &mut W) -> io::Result diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index da15941374d8..3f1fec4c3177 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -266,12 +266,10 @@ #![feature(float_from_str_radix)] #![feature(fn_traits)] #![feature(fnbox)] -#![feature(generic_param_attrs)] -#![feature(hashmap_hasher)] +#![cfg_attr(stage0, feature(generic_param_attrs))] +#![feature(hashmap_internals)] #![feature(heap_api)] -#![feature(i128)] -#![feature(i128_type)] -#![feature(inclusive_range)] +#![cfg_attr(stage0, feature(i128_type, i128))] #![feature(int_error_internals)] #![feature(integer_atomics)] #![feature(into_cow)] @@ -282,7 +280,8 @@ #![feature(macro_reexport)] #![feature(macro_vis_matcher)] #![feature(needs_panic_runtime)] -#![feature(never_type)] +#![feature(exhaustive_patterns)] +#![feature(nonzero)] #![feature(num_bits_bytes)] #![feature(old_wrapping)] #![feature(on_unimplemented)] @@ -291,7 +290,6 @@ #![feature(panic_internals)] #![feature(panic_unwind)] #![feature(peek)] -#![feature(placement_in_syntax)] #![feature(placement_new_protocol)] #![feature(prelude_import)] #![feature(ptr_internals)] @@ -299,7 +297,7 @@ #![feature(raw)] #![feature(rustc_attrs)] #![feature(stdsimd)] -#![feature(sip_hash_13)] +#![feature(shrink_to)] #![feature(slice_bytes)] #![feature(slice_concat_ext)] #![feature(slice_internals)] @@ -309,11 +307,10 @@ #![feature(str_char)] #![feature(str_internals)] #![feature(str_utf16)] -#![feature(termination_trait)] #![feature(test, rustc_private)] #![feature(thread_local)] #![feature(toowned_clone_into)] -#![feature(try_from)] +#![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(untagged_unions)] @@ -324,6 +321,8 @@ #![feature(doc_spotlight)] #![cfg_attr(test, feature(update_panic_count))] #![cfg_attr(windows, feature(used))] +#![cfg_attr(stage0, feature(never_type))] +#![cfg_attr(stage0, feature(termination_trait))] #![default_lib_allocator] @@ -354,8 +353,9 @@ use prelude::v1::*; // We want to re-export a few macros from core but libcore has already been // imported by the compiler (via our #[no_std] attribute) In this case we just // add a new crate name so we can attach the re-exports to it. -#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, +#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, unreachable, unimplemented, write, writeln, try)] +#[cfg_attr(stage0, macro_reexport(assert))] extern crate core as __core; #[macro_use] @@ -433,7 +433,7 @@ pub use core::i16; pub use core::i32; #[stable(feature = "rust1", since = "1.0.0")] pub use core::i64; -#[unstable(feature = "i128", issue = "35118")] +#[stable(feature = "i128", since = "1.26.0")] pub use core::i128; #[stable(feature = "rust1", since = "1.0.0")] pub use core::usize; @@ -463,7 +463,7 @@ pub use alloc::string; pub use alloc::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use std_unicode::char; -#[unstable(feature = "i128", issue = "35118")] +#[stable(feature = "i128", since = "1.26.0")] pub use core::u128; pub mod f32; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index b804cf7cd902..5ef7c1596550 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -335,6 +335,18 @@ pub mod builtin { /// proxied through this one. `format_args!`, unlike its derived macros, avoids /// heap allocations. /// + /// You can use the [`fmt::Arguments`] value that `format_args!` returns + /// in `Debug` and `Display` contexts as seen below. The example also shows + /// that `Debug` and `Display` format to the same thing: the interpolated + /// format string in `format_args!`. + /// + /// ```rust + /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); + /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); + /// assert_eq!("1 foo 2", display); + /// assert_eq!(display, debug); + /// ``` + /// /// For more information, see the documentation in [`std::fmt`]. /// /// [`Display`]: ../std/fmt/trait.Display.html @@ -719,6 +731,60 @@ pub mod builtin { ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }); } + + /// Ensure that a boolean expression is `true` at runtime. + /// + /// This will invoke the [`panic!`] macro if the provided expression cannot be + /// evaluated to `true` at runtime. + /// + /// # Uses + /// + /// Assertions are always checked in both debug and release builds, and cannot + /// be disabled. See [`debug_assert!`] for assertions that are not enabled in + /// release builds by default. + /// + /// Unsafe code relies on `assert!` to enforce run-time invariants that, if + /// violated could lead to unsafety. + /// + /// Other use-cases of `assert!` include [testing] and enforcing run-time + /// invariants in safe code (whose violation cannot result in unsafety). + /// + /// # Custom Messages + /// + /// This macro has a second form, where a custom panic message can + /// be provided with or without arguments for formatting. See [`std::fmt`] + /// for syntax for this form. + /// + /// [`panic!`]: macro.panic.html + /// [`debug_assert!`]: macro.debug_assert.html + /// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro + /// [`std::fmt`]: ../std/fmt/index.html + /// + /// # Examples + /// + /// ``` + /// // the panic message for these assertions is the stringified value of the + /// // expression given. + /// assert!(true); + /// + /// fn some_computation() -> bool { true } // a very simple function + /// + /// assert!(some_computation()); + /// + /// // assert with a custom message + /// let x = true; + /// assert!(x, "x wasn't true!"); + /// + /// let a = 3; let b = 27; + /// assert!(a + b == 30, "a = {}, b = {}", a, b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[macro_export] + macro_rules! assert { + ($cond:expr) => ({ /* compiler built-in */ }); + ($cond:expr,) => ({ /* compiler built-in */ }); + ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }); + } } /// A macro for defining #[cfg] if-else statements. diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index fa430939f058..bc2c9f522d3b 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -28,6 +28,9 @@ use slice; /// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and /// [`SocketAddrV6`]'s respective documentation for more details. /// +/// The size of a `SocketAddr` instance may vary depending on the target operating +/// system. +/// /// [IP address]: ../../std/net/enum.IpAddr.html /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html @@ -61,6 +64,9 @@ pub enum SocketAddr { /// /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. /// +/// The size of a `SocketAddrV4` struct may vary depending on the target operating +/// system. +/// /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html @@ -88,6 +94,9 @@ pub struct SocketAddrV4 { inner: c::sockaddr_in } /// /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. /// +/// The size of a `SocketAddrV6` struct may vary depending on the target operating +/// system. +/// /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 0d73a6f4fd7f..fcec8d06853f 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -26,6 +26,9 @@ use sys_common::{AsInner, FromInner}; /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their /// respective documentation for more details. /// +/// The size of an `IpAddr` instance may vary depending on the target operating +/// system. +/// /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html /// @@ -61,6 +64,9 @@ pub enum IpAddr { /// /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. /// +/// The size of an `Ipv4Addr` struct may vary depending on the target operating +/// system. +/// /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html /// @@ -93,6 +99,9 @@ pub struct Ipv4Addr { /// /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. /// +/// The size of an `Ipv6Addr` struct may vary depending on the target operating +/// system. +/// /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html /// @@ -769,7 +778,16 @@ impl FromInner for Ipv4Addr { #[stable(feature = "ip_u32", since = "1.1.0")] impl From for u32 { - /// It performs the conversion in network order (big-endian). + /// Convert an `Ipv4Addr` into a host byte order `u32`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(13, 12, 11, 10); + /// assert_eq!(0x0d0c0b0au32, u32::from(addr)); + /// ``` fn from(ip: Ipv4Addr) -> u32 { let ip = ip.octets(); ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32) @@ -778,7 +796,16 @@ impl From for u32 { #[stable(feature = "ip_u32", since = "1.1.0")] impl From for Ipv4Addr { - /// It performs the conversion in network order (big-endian). + /// Convert a host byte order `u32` into an `Ipv4Addr`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from(0x0d0c0b0au32); + /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); + /// ``` fn from(ip: u32) -> Ipv4Addr { Ipv4Addr::new((ip >> 24) as u8, (ip >> 16) as u8, (ip >> 8) as u8, ip as u8) } @@ -786,6 +813,14 @@ impl From for Ipv4Addr { #[stable(feature = "from_slice_v4", since = "1.9.0")] impl From<[u8; 4]> for Ipv4Addr { + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); + /// ``` fn from(octets: [u8; 4]) -> Ipv4Addr { Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]) } @@ -793,6 +828,16 @@ impl From<[u8; 4]> for Ipv4Addr { #[stable(feature = "ip_from_slice", since = "1.17.0")] impl From<[u8; 4]> for IpAddr { + /// Create an `IpAddr::V4` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr}; + /// + /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr); + /// ``` fn from(octets: [u8; 4]) -> IpAddr { IpAddr::V4(Ipv4Addr::from(octets)) } @@ -1346,7 +1391,7 @@ impl FromInner for Ipv6Addr { } } -#[unstable(feature = "i128", issue = "35118")] +#[stable(feature = "i128", since = "1.26.0")] impl From for u128 { fn from(ip: Ipv6Addr) -> u128 { let ip = ip.segments(); @@ -1355,7 +1400,7 @@ impl From for u128 { ((ip[6] as u128) << 16) + (ip[7] as u128) } } -#[unstable(feature = "i128", issue = "35118")] +#[stable(feature = "i128", since = "1.26.0")] impl From for Ipv6Addr { fn from(ip: u128) -> Ipv6Addr { Ipv6Addr::new( @@ -1386,6 +1431,27 @@ impl From<[u16; 8]> for Ipv6Addr { #[stable(feature = "ip_from_slice", since = "1.17.0")] impl From<[u8; 16]> for IpAddr { + /// Create an `IpAddr::V6` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = IpAddr::from([ + /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, + /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// ]); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new( + /// 0x1918, 0x1716, + /// 0x1514, 0x1312, + /// 0x1110, 0x0f0e, + /// 0x0d0c, 0x0b0a + /// )), + /// addr + /// ); + /// ``` fn from(octets: [u8; 16]) -> IpAddr { IpAddr::V6(Ipv6Addr::from(octets)) } @@ -1393,6 +1459,27 @@ impl From<[u8; 16]> for IpAddr { #[stable(feature = "ip_from_slice", since = "1.17.0")] impl From<[u16; 8]> for IpAddr { + /// Create an `IpAddr::V6` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = IpAddr::from([ + /// 525u16, 524u16, 523u16, 522u16, + /// 521u16, 520u16, 519u16, 518u16, + /// ]); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new( + /// 0x20d, 0x20c, + /// 0x20b, 0x20a, + /// 0x209, 0x208, + /// 0x207, 0x206 + /// )), + /// addr + /// ); + /// ``` fn from(segments: [u16; 8]) -> IpAddr { IpAddr::V6(Ipv6Addr::from(segments)) } diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index eef043683b02..b0d5e563cb9e 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -175,12 +175,12 @@ impl fmt::Debug for LookupHost { /// /// use std::net; /// -/// # fn foo() -> std::io::Result<()> { -/// for host in net::lookup_host("rust-lang.org")? { -/// println!("found address: {}", host); +/// fn main() -> std::io::Result<()> { +/// for host in net::lookup_host("rust-lang.org")? { +/// println!("found address: {}", host); +/// } +/// Ok(()) /// } -/// # Ok(()) -/// # } /// ``` #[unstable(feature = "lookup_host", reason = "unsure about the returned \ iterator and returning socket \ diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index 261d44eebaa2..ae5037cc44e8 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -372,6 +372,25 @@ impl FromStr for SocketAddr { /// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and /// [`SocketAddrV6`]. /// +/// # Potential causes +/// +/// `AddrParseError` may be thrown because the provided string does not parse as the given type, +/// often because it includes information only handled by a different address type. +/// +/// ```should_panic +/// use std::net::IpAddr; +/// let _foo: IpAddr = "127.0.0.1:8080".parse().expect("Cannot handle the socket port"); +/// ``` +/// +/// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead. +/// +/// ``` +/// use std::net::SocketAddr; +/// +/// // No problem, the `panic!` message has disappeared. +/// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic"); +/// ``` +/// /// [`FromStr`]: ../../std/str/trait.FromStr.html /// [`IpAddr`]: ../../std/net/enum.IpAddr.html /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index e28ccdb766ae..0f60b5b3ee4b 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -72,7 +72,7 @@ pub struct TcpStream(net_imp::TcpStream); /// /// # Examples /// -/// ``` +/// ```no_run /// # use std::io; /// use std::net::{TcpListener, TcpStream}; /// @@ -80,15 +80,15 @@ pub struct TcpStream(net_imp::TcpStream); /// // ... /// } /// -/// # fn process() -> io::Result<()> { -/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); +/// fn main() -> io::Result<()> { +/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); /// -/// // accept connections and process them serially -/// for stream in listener.incoming() { -/// handle_client(stream?); +/// // accept connections and process them serially +/// for stream in listener.incoming() { +/// handle_client(stream?); +/// } +/// Ok(()) /// } -/// # Ok(()) -/// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 8e56954bea43..d25e29999cb6 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -44,22 +44,22 @@ use time::Duration; /// ```no_run /// use std::net::UdpSocket; /// -/// # fn foo() -> std::io::Result<()> { -/// { -/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?; +/// fn main() -> std::io::Result<()> { +/// { +/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?; /// -/// // Receives a single datagram message on the socket. If `buf` is too small to hold -/// // the message, it will be cut off. -/// let mut buf = [0; 10]; -/// let (amt, src) = socket.recv_from(&mut buf)?; +/// // Receives a single datagram message on the socket. If `buf` is too small to hold +/// // the message, it will be cut off. +/// let mut buf = [0; 10]; +/// let (amt, src) = socket.recv_from(&mut buf)?; /// -/// // Redeclare `buf` as slice of the received data and send reverse data back to origin. -/// let buf = &mut buf[..amt]; -/// buf.reverse(); -/// socket.send_to(buf, &src)?; -/// # Ok(()) -/// } // the socket is closed here -/// # } +/// // Redeclare `buf` as slice of the received data and send reverse data back to origin. +/// let buf = &mut buf[..amt]; +/// buf.reverse(); +/// socket.send_to(buf, &src)?; +/// } // the socket is closed here +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct UdpSocket(net_imp::UdpSocket); diff --git a/src/libstd/num.rs b/src/libstd/num.rs index a2c133954a32..4b975dd912a1 100644 --- a/src/libstd/num.rs +++ b/src/libstd/num.rs @@ -21,6 +21,13 @@ pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError} #[stable(feature = "rust1", since = "1.0.0")] pub use core::num::Wrapping; +#[unstable(feature = "nonzero", issue = "49137")] +#[allow(deprecated)] +pub use core::num::{ + NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, + NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize, +}; + #[cfg(test)] use fmt; #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem}; @@ -169,7 +176,6 @@ mod tests { macro_rules! test_checked_next_power_of_two { ($test_name:ident, $T:ident) => ( - #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119) fn $test_name() { #![test] assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 5d37d970e89b..2be2fbcb2dbf 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -32,16 +32,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let stat = meta.as_raw_stat(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let stat = meta.as_raw_stat(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] #[rustc_deprecated(since = "1.8.0", @@ -54,16 +54,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_dev()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_dev(&self) -> u64; @@ -71,16 +71,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ino()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ino(&self) -> u64; @@ -88,16 +88,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mode()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mode(&self) -> u32; @@ -105,16 +105,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_nlink()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_nlink(&self) -> u64; @@ -122,16 +122,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_uid()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_uid(&self) -> u32; @@ -139,16 +139,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_gid()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_gid(&self) -> u32; @@ -156,16 +156,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_rdev()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_rdev(&self) -> u64; @@ -176,16 +176,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_size()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_size(&self) -> u64; @@ -193,16 +193,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_atime()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_atime(&self) -> i64; @@ -210,16 +210,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_atime_nsec()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_atime_nsec(&self) -> i64; @@ -227,16 +227,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mtime()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mtime(&self) -> i64; @@ -244,16 +244,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mtime_nsec()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_mtime_nsec(&self) -> i64; @@ -261,16 +261,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ctime()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime(&self) -> i64; @@ -278,16 +278,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ctime_nsec()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_ctime_nsec(&self) -> i64; @@ -295,16 +295,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_blksize()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_blksize(&self) -> u64; @@ -312,16 +312,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_blocks()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_blocks(&self) -> u64; diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 358aa2c37dfb..ce4bbfffc2e4 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -79,7 +79,6 @@ mod prim_bool { } /// write: /// /// ``` -/// #![feature(never_type)] /// # fn foo() -> u32 { /// let x: ! = { /// return 123 @@ -131,13 +130,15 @@ mod prim_bool { } /// [`Result`] which we can unpack like this: /// /// ```ignore (string-from-str-error-type-is-not-never-yet) +/// #[feature(exhaustive_patterns)] /// // NOTE: This does not work today! /// let Ok(s) = String::from_str("hello"); /// ``` /// -/// Since the [`Err`] variant contains a `!`, it can never occur. So we can exhaustively match on -/// [`Result`] by just taking the [`Ok`] variant. This illustrates another behaviour of `!` - -/// it can be used to "delete" certain enum variants from generic types like `Result`. +/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns` +/// feature is present this means we can exhaustively match on [`Result`] by just taking the +/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain +/// enum variants from generic types like `Result`. /// /// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str /// [`Result`]: result/enum.Result.html @@ -154,7 +155,6 @@ mod prim_bool { } /// for example: /// /// ``` -/// # #![feature(never_type)] /// # use std::fmt; /// # trait Debug { /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result; @@ -192,7 +192,6 @@ mod prim_bool { } /// [`Default`]: default/trait.Default.html /// [`default()`]: default/trait.Default.html#tymethod.default /// -#[unstable(feature = "never_type", issue = "35121")] mod prim_never { } #[doc(primitive = "char")] @@ -752,7 +751,7 @@ mod prim_i64 { } /// The 128-bit signed integer type. /// /// *[See also the `std::i128` module](i128/index.html).* -#[unstable(feature = "i128", issue="35118")] +#[stable(feature = "i128", since="1.26.0")] mod prim_i128 { } #[doc(primitive = "u8")] @@ -792,7 +791,7 @@ mod prim_u64 { } /// The 128-bit unsigned integer type. /// /// *[See also the `std::u128` module](u128/index.html).* -#[unstable(feature = "i128", issue="35118")] +#[stable(feature = "i128", since="1.26.0")] mod prim_u128 { } #[doc(primitive = "isize")] diff --git a/src/libstd/process.rs b/src/libstd/process.rs index d5ac2d19e831..40bc84f4bc10 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1420,14 +1420,13 @@ pub fn abort() -> ! { /// Basic usage: /// /// ```no_run -/// #![feature(getpid)] /// use std::process; /// /// println!("My pid is {}", process::id()); /// ``` /// /// -#[unstable(feature = "getpid", issue = "44971", reason = "recently added")] +#[stable(feature = "getpid", since = "1.26.0")] pub fn id() -> u32 { ::sys::os::getpid() } @@ -1442,8 +1441,9 @@ pub fn id() -> u32 { /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. #[cfg_attr(not(test), lang = "termination")] #[unstable(feature = "termination_trait_lib", issue = "43301")] -#[rustc_on_unimplemented = - "`main` can only return types that implement {Termination}, not `{Self}`"] +#[rustc_on_unimplemented( + message="`main` has invalid return type `{Self}`", + label="`main` can only return types that implement `{Termination}`")] pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index e1392762a59d..8f945470b7e9 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -73,3 +73,18 @@ fn lang_start { lang_start_internal(&move || main().report(), argc, argv) } + +/// Function used for reverting changes to the main stack before setrlimit(). +/// This is POSIX (non-Linux) specific and unlikely to be directly stabilized. +#[unstable(feature = "rustc_stack_internals", issue = "0")] +pub unsafe fn deinit_stack_guard() { + ::sys::thread::guard::deinit(); +} + +/// Function used for resetting the main stack guard address after setrlimit(). +/// This is POSIX specific and unlikely to be directly stabilized. +#[unstable(feature = "rustc_stack_internals", issue = "0")] +pub unsafe fn update_stack_guard() { + let main_guard = ::sys::thread::guard::init(); + ::sys_common::thread_info::reset_guard(main_guard); +} diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 78a3b82546e3..a22d9053b696 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -118,6 +118,7 @@ pub mod guard { pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 5d4edc2cf92c..0f4762aa8810 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -30,13 +30,14 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::redox::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); /// - /// println!("permissions: {}", permissions.mode()); - /// # Ok(()) } + /// println!("permissions: {}", permissions.mode()); + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -49,14 +50,15 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::redox::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// # Ok(()) } + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -291,13 +293,13 @@ impl FileTypeExt for fs::FileType { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::os::redox::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index 655bfdb91670..da27787babb9 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4719a94c7e9..f20350269b7c 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -91,4 +91,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 2e17fd58e0a1..3c5b9424fb06 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -41,20 +41,20 @@ pub trait FileExt { /// /// # Examples /// - /// ``` - /// use std::os::unix::prelude::FileExt; + /// ```no_run + /// use std::io; /// use std::fs::File; + /// use std::os::unix::prelude::FileExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let mut buf = [0u8; 8]; - /// let file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut buf = [0u8; 8]; + /// let file = File::open("foo.txt")?; /// - /// // We now read 8 bytes from the offset 10. - /// let num_bytes_read = file.read_at(&mut buf, 10)?; - /// println!("read {} bytes: {:?}", num_bytes_read, buf); - /// # Ok(()) - /// # } + /// // We now read 8 bytes from the offset 10. + /// let num_bytes_read = file.read_at(&mut buf, 10)?; + /// println!("read {} bytes: {:?}", num_bytes_read, buf); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; @@ -78,18 +78,18 @@ pub trait FileExt { /// /// # Examples /// - /// ``` - /// use std::os::unix::prelude::FileExt; + /// ```no_run /// use std::fs::File; + /// use std::io; + /// use std::os::unix::prelude::FileExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let file = File::open("foo.txt")?; /// - /// // We now write at the offset 10. - /// file.write_at(b"sushi", 10)?; - /// # Ok(()) - /// # } + /// // We now write at the offset 10. + /// file.write_at(b"sushi", 10)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; @@ -117,13 +117,13 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); /// - /// println!("permissions: {}", permissions.mode()); - /// # Ok(()) } + /// println!("permissions: {}", permissions.mode()); + /// Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -136,14 +136,14 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// # Ok(()) } + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -260,15 +260,15 @@ pub trait MetadataExt { /// # Examples /// /// ```no_run + /// use std::io; /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let dev_id = meta.dev(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let dev_id = meta.dev(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn dev(&self) -> u64; @@ -279,13 +279,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let inode = meta.ino(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let inode = meta.ino(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ino(&self) -> u64; @@ -296,17 +296,17 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let mode = meta.mode(); - /// let user_has_write_access = mode & 0o200; - /// let user_has_read_write_access = mode & 0o600; - /// let group_has_read_access = mode & 0o040; - /// let others_have_exec_access = mode & 0o001; - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let mode = meta.mode(); + /// let user_has_write_access = mode & 0o200; + /// let user_has_read_write_access = mode & 0o600; + /// let group_has_read_access = mode & 0o040; + /// let others_have_exec_access = mode & 0o001; + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -317,13 +317,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nb_hard_links = meta.nlink(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nb_hard_links = meta.nlink(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn nlink(&self) -> u64; @@ -334,13 +334,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let user_id = meta.uid(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let user_id = meta.uid(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn uid(&self) -> u32; @@ -351,13 +351,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let group_id = meta.gid(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let group_id = meta.gid(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn gid(&self) -> u32; @@ -368,13 +368,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let device_id = meta.rdev(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let device_id = meta.rdev(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn rdev(&self) -> u64; @@ -385,13 +385,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let file_size = meta.size(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let file_size = meta.size(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn size(&self) -> u64; @@ -402,13 +402,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_access_time = meta.atime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_access_time = meta.atime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime(&self) -> i64; @@ -419,13 +419,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_access_time = meta.atime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_access_time = meta.atime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime_nsec(&self) -> i64; @@ -436,13 +436,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_modification_time = meta.mtime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_modification_time = meta.mtime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime(&self) -> i64; @@ -453,13 +453,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_modification_time = meta.mtime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_modification_time = meta.mtime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime_nsec(&self) -> i64; @@ -470,13 +470,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_status_change_time = meta.ctime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_status_change_time = meta.ctime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime(&self) -> i64; @@ -487,13 +487,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_status_change_time = meta.ctime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_status_change_time = meta.ctime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; @@ -504,13 +504,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocksize = meta.blksize(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocksize = meta.blksize(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blksize(&self) -> u64; @@ -523,13 +523,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocks = meta.blocks(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocks = meta.blocks(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blocks(&self) -> u64; @@ -562,17 +562,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("block_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_block_device()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("block_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_block_device()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_block_device(&self) -> bool; @@ -580,17 +580,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("char_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_char_device()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("char_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_char_device()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_char_device(&self) -> bool; @@ -598,17 +598,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("fifo_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_fifo()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("fifo_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_fifo()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_fifo(&self) -> bool; @@ -616,17 +616,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("unix.socket")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_socket()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("unix.socket")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_socket()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_socket(&self) -> bool; @@ -687,13 +687,13 @@ impl DirEntryExt for fs::DirEntry { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::os::unix::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index ad437658d144..ba80cbe47c82 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -51,13 +51,11 @@ use libc::MSG_NOSIGNAL; const MSG_NOSIGNAL: libc::c_int = 0x0; fn sun_path_offset() -> usize { - unsafe { - // Work with an actual instance of the type since using a null pointer is UB - let addr: libc::sockaddr_un = mem::uninitialized(); - let base = &addr as *const _ as usize; - let path = &addr.sun_path as *const _ as usize; - path - base - } + // Work with an actual instance of the type since using a null pointer is UB + let addr: libc::sockaddr_un = unsafe { mem::uninitialized() }; + let base = &addr as *const _ as usize; + let path = &addr.sun_path as *const _ as usize; + path - base } unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 60309bec6d4f..7b4ec20d91fb 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -193,7 +193,7 @@ impl IntoRawFd for process::ChildStderr { } /// Returns the OS-assigned process identifier associated with this process's parent. -#[unstable(feature = "unix_ppid", issue = "46104")] +#[stable(feature = "unix_ppid", since = "1.27.0")] pub fn parent_id() -> u32 { ::sys::os::getppid() } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 3f65975e6088..04d9f0b06d34 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -383,12 +383,12 @@ impl IntoInner for Socket { // believe it's thread-safe). #[cfg(target_env = "gnu")] fn on_resolver_failure() { + use sys; + // If the version fails to parse, we treat it the same as "not glibc". - if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { - if let Some(version) = parse_glibc_version(version_str) { - if version < (2, 26) { - unsafe { libc::res_init() }; - } + if let Some(version) = sys::os::glibc_version() { + if version < (2, 26) { + unsafe { libc::res_init() }; } } } @@ -396,29 +396,6 @@ fn on_resolver_failure() { #[cfg(not(target_env = "gnu"))] fn on_resolver_failure() {} -#[cfg(target_env = "gnu")] -fn glibc_version_cstr() -> Option<&'static CStr> { - weak! { - fn gnu_get_libc_version() -> *const libc::c_char - } - if let Some(f) = gnu_get_libc_version.get() { - unsafe { Some(CStr::from_ptr(f())) } - } else { - None - } -} - -// Returns Some((major, minor)) if the string is a valid "x.y" version, -// ignoring any extra dot-separated parts. Otherwise return None. -#[cfg(target_env = "gnu")] -fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { - let mut parsed_ints = version.split(".").map(str::parse::).fuse(); - match (parsed_ints.next(), parsed_ints.next()) { - (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), - _ => None - } -} - #[cfg(all(test, taget_env = "gnu"))] mod test { use super::*; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index a46e855b4a6f..4c86fddee4b4 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -546,3 +546,35 @@ pub fn getpid() -> u32 { pub fn getppid() -> u32 { unsafe { libc::getppid() as u32 } } + +#[cfg(target_env = "gnu")] +pub fn glibc_version() -> Option<(usize, usize)> { + if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { + parse_glibc_version(version_str) + } else { + None + } +} + +#[cfg(target_env = "gnu")] +fn glibc_version_cstr() -> Option<&'static CStr> { + weak! { + fn gnu_get_libc_version() -> *const libc::c_char + } + if let Some(f) = gnu_get_libc_version.get() { + unsafe { Some(CStr::from_ptr(f())) } + } else { + None + } +} + +// Returns Some((major, minor)) if the string is a valid "x.y" version, +// ignoring any extra dot-separated parts. Otherwise return None. +#[cfg(target_env = "gnu")] +fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { + let mut parsed_ints = version.split(".").map(str::parse::).fuse(); + match (parsed_ints.next(), parsed_ints.next()) { + (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)), + _ => None + } +} diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index e03493879986..e43bc6da5f1f 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index d0486f06a143..b7f30600b8a4 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -184,6 +184,10 @@ impl Command { let maybe_env = self.env.capture_if_changed(); maybe_env.map(|env| construct_envp(env, &mut self.saw_nul)) } + #[allow(dead_code)] + pub fn env_saw_path(&self) -> bool { + self.env.have_changed_path() + } pub fn setup_io(&self, default: Stdio, needs_stdin: bool) -> io::Result<(StdioPipes, ChildPipes)> { diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 189280a4ba9a..9d6d607e3f34 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -34,6 +34,11 @@ impl Command { } let (ours, theirs) = self.setup_io(default, needs_stdin)?; + + if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? { + return Ok((ret, ours)) + } + let (input, output) = sys::pipe::anon_pipe()?; let pid = unsafe { @@ -229,6 +234,119 @@ impl Command { libc::execvp(self.get_argv()[0], self.get_argv().as_ptr()); io::Error::last_os_error() } + + #[cfg(not(any(target_os = "macos", target_os = "freebsd", + all(target_os = "linux", target_env = "gnu"))))] + fn posix_spawn(&mut self, _: &ChildPipes, _: Option<&CStringArray>) + -> io::Result> + { + Ok(None) + } + + // Only support platforms for which posix_spawn() can return ENOENT + // directly. + #[cfg(any(target_os = "macos", target_os = "freebsd", + all(target_os = "linux", target_env = "gnu")))] + fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) + -> io::Result> + { + use mem; + use sys; + + if self.get_cwd().is_some() || + self.get_gid().is_some() || + self.get_uid().is_some() || + self.env_saw_path() || + self.get_closures().len() != 0 { + return Ok(None) + } + + // Only glibc 2.24+ posix_spawn() supports returning ENOENT directly. + #[cfg(all(target_os = "linux", target_env = "gnu"))] + { + if let Some(version) = sys::os::glibc_version() { + if version < (2, 24) { + return Ok(None) + } + } else { + return Ok(None) + } + } + + let mut p = Process { pid: 0, status: None }; + + struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t); + + impl Drop for PosixSpawnFileActions { + fn drop(&mut self) { + unsafe { + libc::posix_spawn_file_actions_destroy(&mut self.0); + } + } + } + + struct PosixSpawnattr(libc::posix_spawnattr_t); + + impl Drop for PosixSpawnattr { + fn drop(&mut self) { + unsafe { + libc::posix_spawnattr_destroy(&mut self.0); + } + } + } + + unsafe { + let mut file_actions = PosixSpawnFileActions(mem::uninitialized()); + let mut attrs = PosixSpawnattr(mem::uninitialized()); + + libc::posix_spawnattr_init(&mut attrs.0); + libc::posix_spawn_file_actions_init(&mut file_actions.0); + + if let Some(fd) = stdio.stdin.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDIN_FILENO))?; + } + if let Some(fd) = stdio.stdout.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDOUT_FILENO))?; + } + if let Some(fd) = stdio.stderr.fd() { + cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0, + fd, + libc::STDERR_FILENO))?; + } + + let mut set: libc::sigset_t = mem::uninitialized(); + cvt(libc::sigemptyset(&mut set))?; + cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0, + &set))?; + cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?; + cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0, + &set))?; + + let flags = libc::POSIX_SPAWN_SETSIGDEF | + libc::POSIX_SPAWN_SETSIGMASK; + cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?; + + let envp = envp.map(|c| c.as_ptr()) + .unwrap_or(*sys::os::environ() as *const _); + let ret = libc::posix_spawnp( + &mut p.pid, + self.get_argv()[0], + &file_actions.0, + &attrs.0, + self.get_argv().as_ptr() as *const _, + envp as *const _, + ); + if ret == 0 { + Ok(Some(p)) + } else { + Err(io::Error::from_raw_os_error(ret)) + } + } + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 72cdb9440b8e..2db3d4a5744e 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -209,6 +209,7 @@ pub mod guard { pub type Guard = Range; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } @@ -222,8 +223,8 @@ pub mod guard { #[cfg_attr(test, allow(dead_code))] pub mod guard { use libc; - use libc::mmap; - use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use libc::{mmap, mprotect}; + use libc::{PROT_NONE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; use ops::Range; use sys::os; @@ -284,10 +285,10 @@ pub mod guard { ret } - pub unsafe fn init() -> Option { - PAGE_SIZE = os::page_size(); - - let mut stackaddr = get_stack_start()?; + // Precondition: PAGE_SIZE is initialized. + unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> { + assert!(PAGE_SIZE != 0); + let stackaddr = get_stack_start()?; // Ensure stackaddr is page aligned! A parent process might // have reset RLIMIT_STACK to be non-page aligned. The @@ -296,10 +297,17 @@ pub mod guard { // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize let remainder = (stackaddr as usize) % PAGE_SIZE; - if remainder != 0 { - stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) - as *mut libc::c_void; - } + Some(if remainder == 0 { + stackaddr + } else { + ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void + }) + } + + pub unsafe fn init() -> Option { + PAGE_SIZE = os::page_size(); + + let stackaddr = get_stack_start_aligned()?; if cfg!(target_os = "linux") { // Linux doesn't allocate the whole stack right away, and @@ -336,6 +344,26 @@ pub mod guard { } } + pub unsafe fn deinit() { + if !cfg!(target_os = "linux") { + if let Some(stackaddr) = get_stack_start_aligned() { + // Remove the protection on the guard page. + // FIXME: we cannot unmap the page, because when we mmap() + // above it may be already mapped by the OS, which we can't + // detect from mmap()'s return value. If we unmap this page, + // it will lead to failure growing stack size on platforms like + // macOS. Instead, just restore the page to a writable state. + // This ain't Linux, so we probably don't need to care about + // execstack. + let result = mprotect(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE); + + if result != 0 { + panic!("unable to reset the guard page"); + } + } + } + } + #[cfg(any(target_os = "macos", target_os = "bitrig", target_os = "openbsd", diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs index 543c22ebe18a..84f560af69be 100644 --- a/src/libstd/sys/wasm/os_str.rs +++ b/src/libstd/sys/wasm/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 6a066509b492..7345843b975e 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -46,4 +46,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 38bf4cca851f..e5cd51b6550b 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -45,15 +45,15 @@ pub trait FileExt { /// use std::fs::File; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // Read 10 bytes, starting 72 bytes from the - /// // start of the file. - /// file.seek_read(&mut buffer[..], 72)?; - /// # Ok(()) - /// # } + /// // Read 10 bytes, starting 72 bytes from the + /// // start of the file. + /// file.seek_read(&mut buffer[..], 72)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result; @@ -79,14 +79,14 @@ pub trait FileExt { /// use std::fs::File; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // Write a byte string starting 72 bytes from - /// // the start of the file. - /// buffer.seek_write(b"some bytes", 72)?; - /// # Ok(()) - /// # } + /// // Write a byte string starting 72 bytes from + /// // the start of the file. + /// buffer.seek_write(b"some bytes", 72)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result; @@ -305,11 +305,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let attributes = metadata.file_attributes(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let attributes = metadata.file_attributes(); + /// Ok(()) + /// } /// ``` /// /// [File Attribute Constants]: @@ -335,11 +335,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let creation_time = metadata.creation_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let creation_time = metadata.creation_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -370,11 +370,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_access_time = metadata.last_access_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_access_time = metadata.last_access_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -403,11 +403,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_write_time = metadata.last_write_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_write_time = metadata.last_write_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -426,11 +426,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let file_size = metadata.file_size(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let file_size = metadata.file_size(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn file_size(&self) -> u64; @@ -473,10 +473,10 @@ impl FileTypeExt for fs::FileType { /// ```no_run /// use std::os::windows::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink_file("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink_file("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_file, Q: AsRef>(src: P, dst: Q) @@ -494,10 +494,10 @@ pub fn symlink_file, Q: AsRef>(src: P, dst: Q) /// ```no_run /// use std::os::windows::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink_dir("a", "b")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink_dir("a", "b")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_dir, Q: AsRef>(src: P, dst: Q) diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index 414c9c5418e4..bcc66b9954b8 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -113,6 +113,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + #[inline] pub fn into_box(self) -> Box { unsafe { mem::transmute(self.inner.into_box()) } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index f1ab9c476096..afa8e3e13693 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,7 +10,6 @@ #![unstable(feature = "process_internals", issue = "0")] -use ascii::AsciiExt; use collections::BTreeMap; use env::split_paths; use env; diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 43abfbb1f645..4b3d1b586b57 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -96,4 +96,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index fd1a5fdb4109..d0c5951bd6c0 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -47,6 +47,7 @@ impl EnvKey for DefaultEnvKey {} #[derive(Clone, Debug)] pub struct CommandEnv { clear: bool, + saw_path: bool, vars: BTreeMap> } @@ -54,6 +55,7 @@ impl Default for CommandEnv { fn default() -> Self { CommandEnv { clear: false, + saw_path: false, vars: Default::default() } } @@ -108,9 +110,11 @@ impl CommandEnv { // The following functions build up changes pub fn set(&mut self, key: &OsStr, value: &OsStr) { + self.maybe_saw_path(&key); self.vars.insert(key.to_owned().into(), Some(value.to_owned())); } pub fn remove(&mut self, key: &OsStr) { + self.maybe_saw_path(&key); if self.clear { self.vars.remove(key); } else { @@ -121,4 +125,12 @@ impl CommandEnv { self.clear = true; self.vars.clear(); } + pub fn have_changed_path(&self) -> bool { + self.saw_path || self.clear + } + fn maybe_saw_path(&mut self, key: &OsStr) { + if !self.saw_path && key == "PATH" { + self.saw_path = true; + } + } } diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 6a2b6742367a..d75cbded7347 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -50,3 +50,7 @@ pub fn set(stack_guard: Option, thread: Thread) { thread, })); } + +pub fn reset_guard(stack_guard: Option) { + THREAD_INFO.with(move |c| c.borrow_mut().as_mut().unwrap().stack_guard = stack_guard); +} diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 9fff8b91f96f..dda4e1bab3b4 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -27,7 +27,6 @@ use core::str::next_code_point; -use ascii::*; use borrow::Cow; use char; use fmt; @@ -254,6 +253,11 @@ impl Wtf8Buf { self.bytes.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.bytes.shrink_to(min_capacity) + } + /// Returns the number of bytes that this string buffer can hold without reallocating. #[inline] pub fn capacity(&self) -> usize { @@ -871,24 +875,22 @@ impl Hash for Wtf8 { } } -impl AsciiExt for Wtf8 { - type Owned = Wtf8Buf; - - fn is_ascii(&self) -> bool { +impl Wtf8 { + pub fn is_ascii(&self) -> bool { self.bytes.is_ascii() } - fn to_ascii_uppercase(&self) -> Wtf8Buf { + pub fn to_ascii_uppercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } } - fn to_ascii_lowercase(&self) -> Wtf8Buf { + pub fn to_ascii_lowercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } } - fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { + pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { self.bytes.eq_ignore_ascii_case(&other.bytes) } - fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } - fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } + pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } + pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } } #[cfg(test)] diff --git a/src/test/run-pass-fulldeps/env.rs b/src/libstd/tests/env.rs similarity index 97% rename from src/test/run-pass-fulldeps/env.rs rename to src/libstd/tests/env.rs index cf2ea732ee1b..d4376523691a 100644 --- a/src/test/run-pass-fulldeps/env.rs +++ b/src/libstd/tests/env.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --test - -#![feature(rustc_private, std_panic)] - extern crate rand; use std::env::*; diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 12f2a9bb85f8..1215302757c3 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -49,6 +49,9 @@ pub use core::time::Duration; /// allows measuring the duration between two instants (or comparing two /// instants). /// +/// The size of an `Instant` struct may vary depending on the target operating +/// system. +/// /// Example: /// /// ```no_run @@ -88,6 +91,9 @@ pub struct Instant(time::Instant); /// fixed point in time, a `SystemTime` can be converted to a human-readable time, /// or perhaps some other string representation. /// +/// The size of a `SystemTime` struct may vary depending on the target operating +/// system. +/// /// [`Instant`]: ../../std/time/struct.Instant.html /// [`Result`]: ../../std/result/enum.Result.html /// [`Duration`]: ../../std/time/struct.Duration.html @@ -253,6 +259,29 @@ impl fmt::Debug for Instant { } impl SystemTime { + /// An anchor in time which can be used to create new `SystemTime` instances or + /// learn about where in time a `SystemTime` lies. + /// + /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with + /// respect to the system clock. Using `duration_since` on an existing + /// `SystemTime` instance can tell how far away from this point in time a + /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a + /// `SystemTime` instance to represent another fixed point in time. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(assoc_unix_epoch)] + /// use std::time::SystemTime; + /// + /// match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { + /// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), + /// Err(_) => panic!("SystemTime before UNIX EPOCH!"), + /// } + /// ``` + #[unstable(feature = "assoc_unix_epoch", issue = "49502")] + pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH; + /// Returns the system time corresponding to "now". /// /// # Examples diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index de8b46d5f1b0..33e47ade8cb9 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -42,7 +42,7 @@ pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode}; pub use core::char::ParseCharError; // unstable re-exports -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] pub use core::char::CharTryFromError; #[unstable(feature = "decode_utf8", issue = "33906")] pub use core::char::{DecodeUtf8, decode_utf8}; diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index f155b62e3cc7..c22ea1671fa5 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -39,7 +39,6 @@ #![feature(lang_items)] #![feature(non_exhaustive)] #![feature(staged_api)] -#![feature(try_from)] #![feature(unboxed_closures)] mod bool_trie; diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 07631e0dcfc1..8c24f36615bd 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["dylib"] bitflags = "1.0" serialize = { path = "../libserialize" } log = "0.4" +scoped-tls = "0.1" syntax_pos = { path = "../libsyntax_pos" } rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/libsyntax/README.md b/src/libsyntax/README.md index 3bf735ee8680..7214203830e7 100644 --- a/src/libsyntax/README.md +++ b/src/libsyntax/README.md @@ -1,7 +1,9 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - The `syntax` crate contains those things concerned purely with syntax – that is, the AST ("abstract syntax tree"), parser, pretty-printer, lexer, macro expander, and utilities for traversing ASTs. + +For more information about how these things work in rustc, see the +rustc guide: + +- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html) +- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8b3a7164cccb..31bb1c88b871 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -108,17 +108,16 @@ impl Path { } } - // Add starting "crate root" segment to all paths except those that - // already have it or start with `self`, `super`, `Self` or `$crate`. - pub fn default_to_global(mut self) -> Path { - if !self.is_global() { - let ident = self.segments[0].identifier; - if !::parse::token::Ident(ident).is_path_segment_keyword() || - ident.name == keywords::Crate.name() { - self.segments.insert(0, PathSegment::crate_root(self.span)); + // Make a "crate root" segment for this path unless it already has it + // or starts with something like `self`/`super`/`$crate`/etc. + pub fn make_root(&self) -> Option { + if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) { + if ::parse::token::is_path_segment_keyword(ident) && + ident.name != keywords::Crate.name() { + return None; } } - self + Some(PathSegment::crate_root(self.span.shrink_to_lo())) } pub fn is_global(&self) -> bool { @@ -838,6 +837,13 @@ impl Stmt { _ => false, } } + + pub fn is_expr(&self) -> bool { + match self.node { + StmtKind::Expr(_) => true, + _ => false, + } + } } impl fmt::Debug for Stmt { @@ -1005,7 +1011,6 @@ impl Expr { pub fn precedence(&self) -> ExprPrecedence { match self.node { ExprKind::Box(_) => ExprPrecedence::Box, - ExprKind::InPlace(..) => ExprPrecedence::InPlace, ExprKind::Array(_) => ExprPrecedence::Array, ExprKind::Call(..) => ExprPrecedence::Call, ExprKind::MethodCall(..) => ExprPrecedence::MethodCall, @@ -1065,8 +1070,6 @@ pub enum RangeLimits { pub enum ExprKind { /// A `box x` expression. Box(P), - /// First expr is the place; second expr is the value. - InPlace(P, P), /// An array (`[a, b, c, d]`) Array(Vec>), /// A function call @@ -1878,20 +1881,37 @@ pub struct Variant_ { pub type Variant = Spanned; +/// Part of `use` item to the right of its prefix. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum UseTreeKind { - Simple(Ident), - Glob, + /// `use prefix` or `use prefix as rename` + Simple(Option), + /// `use prefix::{...}` Nested(Vec<(UseTree, NodeId)>), + /// `use prefix::*` + Glob, } +/// A tree of paths sharing common prefixes. +/// Used in `use` items both at top-level and inside of braces in import groups. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct UseTree { - pub kind: UseTreeKind, pub prefix: Path, + pub kind: UseTreeKind, pub span: Span, } +impl UseTree { + pub fn ident(&self) -> Ident { + match self.kind { + UseTreeKind::Simple(Some(rename)) => rename, + UseTreeKind::Simple(None) => + self.prefix.segments.last().expect("empty prefix in a simple import").identifier, + _ => panic!("`UseTree::ident` can only be used on a simple import"), + } + } +} + /// Distinguishes between Attributes that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. @@ -2055,7 +2075,7 @@ pub struct Item { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ItemKind { - /// An `extern crate` item, with optional original crate name. + /// An `extern crate` item, with optional *original* crate name if the crate was renamed. /// /// E.g. `extern crate foo` or `extern crate foo_bar as foo` ExternCrate(Option), diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 4818248129e7..5954b9eb2747 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -30,15 +30,10 @@ use ptr::P; use symbol::Symbol; use tokenstream::{TokenStream, TokenTree, Delimited}; use util::ThinVec; +use GLOBALS; -use std::cell::RefCell; use std::iter; -thread_local! { - static USED_ATTRS: RefCell> = RefCell::new(Vec::new()); - static KNOWN_ATTRS: RefCell> = RefCell::new(Vec::new()); -} - enum AttrError { MultipleItem(Name), UnknownMetaItem(Name), @@ -65,22 +60,24 @@ fn handle_errors(diag: &Handler, span: Span, error: AttrError) { pub fn mark_used(attr: &Attribute) { debug!("Marking {:?} as used.", attr); let AttrId(id) = attr.id; - USED_ATTRS.with(|slot| { + GLOBALS.with(|globals| { + let mut slot = globals.used_attrs.lock(); let idx = (id / 64) as usize; let shift = id % 64; - if slot.borrow().len() <= idx { - slot.borrow_mut().resize(idx + 1, 0); + if slot.len() <= idx { + slot.resize(idx + 1, 0); } - slot.borrow_mut()[idx] |= 1 << shift; + slot[idx] |= 1 << shift; }); } pub fn is_used(attr: &Attribute) -> bool { let AttrId(id) = attr.id; - USED_ATTRS.with(|slot| { + GLOBALS.with(|globals| { + let slot = globals.used_attrs.lock(); let idx = (id / 64) as usize; let shift = id % 64; - slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0) + slot.get(idx).map(|bits| bits & (1 << shift) != 0) .unwrap_or(false) }) } @@ -88,22 +85,24 @@ pub fn is_used(attr: &Attribute) -> bool { pub fn mark_known(attr: &Attribute) { debug!("Marking {:?} as known.", attr); let AttrId(id) = attr.id; - KNOWN_ATTRS.with(|slot| { + GLOBALS.with(|globals| { + let mut slot = globals.known_attrs.lock(); let idx = (id / 64) as usize; let shift = id % 64; - if slot.borrow().len() <= idx { - slot.borrow_mut().resize(idx + 1, 0); + if slot.len() <= idx { + slot.resize(idx + 1, 0); } - slot.borrow_mut()[idx] |= 1 << shift; + slot[idx] |= 1 << shift; }); } pub fn is_known(attr: &Attribute) -> bool { let AttrId(id) = attr.id; - KNOWN_ATTRS.with(|slot| { + GLOBALS.with(|globals| { + let slot = globals.known_attrs.lock(); let idx = (id / 64) as usize; let shift = id % 64; - slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0) + slot.get(idx).map(|bits| bits & (1 << shift) != 0) .unwrap_or(false) }) } @@ -1107,7 +1106,8 @@ impl IntType { impl MetaItem { fn tokens(&self) -> TokenStream { - let ident = TokenTree::Token(self.span, Token::Ident(Ident::with_empty_ctxt(self.name))); + let ident = TokenTree::Token(self.span, + Token::from_ast_ident(Ident::with_empty_ctxt(self.name))); TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)]) } @@ -1115,9 +1115,9 @@ impl MetaItem { where I: Iterator, { let (span, name) = match tokens.next() { - Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name), + Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident.name), Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { - token::Nonterminal::NtIdent(ident) => (ident.span, ident.node.name), + token::Nonterminal::NtIdent(ident, _) => (ident.span, ident.node.name), token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), _ => return None, }, @@ -1270,14 +1270,14 @@ impl LitKind { "true" } else { "false" - }))), + })), false), } } fn from_token(token: Token) -> Option { match token { - Token::Ident(ident) if ident.name == "true" => Some(LitKind::Bool(true)), - Token::Ident(ident) if ident.name == "false" => Some(LitKind::Bool(false)), + Token::Ident(ident, false) if ident.name == "true" => Some(LitKind::Bool(true)), + Token::Ident(ident, false) if ident.name == "false" => Some(LitKind::Bool(false)), Token::Interpolated(ref nt) => match nt.0 { token::NtExpr(ref v) => match v.node { ExprKind::Lit(ref lit) => Some(lit.node.clone()), diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index c340f1b8c8ab..73924c4270e6 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -24,8 +24,7 @@ pub use self::ExpnFormat::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; -use std::cell::{RefCell, Ref}; +use rustc_data_structures::sync::{Lrc, Lock, LockGuard}; use std::cmp; use std::hash::Hash; use std::path::{Path, PathBuf}; @@ -125,13 +124,17 @@ impl StableFilemapId { // CodeMap // +pub(super) struct CodeMapFiles { + pub(super) file_maps: Vec>, + stable_id_to_filemap: FxHashMap> +} + pub struct CodeMap { - pub(super) files: RefCell>>, - file_loader: Box, + pub(super) files: Lock, + file_loader: Box, // This is used to apply the file path remapping as specified via // --remap-path-prefix to all FileMaps allocated within this CodeMap. path_mapping: FilePathMapping, - stable_id_to_filemap: RefCell>>, /// In case we are in a doctest, replace all file names with the PathBuf, /// and add the given offsets to the line info doctest_offset: Option<(FileName, isize)>, @@ -140,10 +143,12 @@ pub struct CodeMap { impl CodeMap { pub fn new(path_mapping: FilePathMapping) -> CodeMap { CodeMap { - files: RefCell::new(Vec::new()), + files: Lock::new(CodeMapFiles { + file_maps: Vec::new(), + stable_id_to_filemap: FxHashMap(), + }), file_loader: Box::new(RealFileLoader), path_mapping, - stable_id_to_filemap: RefCell::new(FxHashMap()), doctest_offset: None, } } @@ -157,14 +162,16 @@ impl CodeMap { } - pub fn with_file_loader(file_loader: Box, + pub fn with_file_loader(file_loader: Box, path_mapping: FilePathMapping) -> CodeMap { CodeMap { - files: RefCell::new(Vec::new()), - file_loader, + files: Lock::new(CodeMapFiles { + file_maps: Vec::new(), + stable_id_to_filemap: FxHashMap(), + }), + file_loader: file_loader, path_mapping, - stable_id_to_filemap: RefCell::new(FxHashMap()), doctest_offset: None, } } @@ -187,17 +194,16 @@ impl CodeMap { Ok(self.new_filemap(filename, src)) } - pub fn files(&self) -> Ref>> { - self.files.borrow() + pub fn files(&self) -> LockGuard>> { + LockGuard::map(self.files.borrow(), |files| &mut files.file_maps) } pub fn filemap_by_stable_id(&self, stable_id: StableFilemapId) -> Option> { - self.stable_id_to_filemap.borrow().get(&stable_id).map(|fm| fm.clone()) + self.files.borrow().stable_id_to_filemap.get(&stable_id).map(|fm| fm.clone()) } fn next_start_pos(&self) -> usize { - let files = self.files.borrow(); - match files.last() { + match self.files.borrow().file_maps.last() { None => 0, // Add one so there is some space between files. This lets us distinguish // positions in the codemap, even in the presence of zero-length files. @@ -207,9 +213,9 @@ impl CodeMap { /// Creates a new filemap without setting its line information. If you don't /// intend to set the line information yourself, you should use new_filemap_and_lines. + /// This does not ensure that only one FileMap exists per file name. pub fn new_filemap(&self, filename: FileName, src: String) -> Lrc { let start_pos = self.next_start_pos(); - let mut files = self.files.borrow_mut(); // The path is used to determine the directory for loading submodules and // include files, so it must be before remapping. @@ -233,16 +239,16 @@ impl CodeMap { Pos::from_usize(start_pos), )); - files.push(filemap.clone()); + let mut files = self.files.borrow_mut(); - self.stable_id_to_filemap - .borrow_mut() - .insert(StableFilemapId::new(&filemap), filemap.clone()); + files.file_maps.push(filemap.clone()); + files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone()); filemap } /// Creates a new filemap and sets its line information. + /// This does not ensure that only one FileMap exists per file name. pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc { let fm = self.new_filemap(filename.to_owned().into(), src.to_owned()); let mut byte_pos: u32 = fm.start_pos.0; @@ -273,7 +279,6 @@ impl CodeMap { mut file_local_non_narrow_chars: Vec) -> Lrc { let start_pos = self.next_start_pos(); - let mut files = self.files.borrow_mut(); let end_pos = Pos::from_usize(start_pos + source_len); let start_pos = Pos::from_usize(start_pos); @@ -297,20 +302,19 @@ impl CodeMap { crate_of_origin, src: None, src_hash, - external_src: RefCell::new(ExternalSource::AbsentOk), + external_src: Lock::new(ExternalSource::AbsentOk), start_pos, end_pos, - lines: RefCell::new(file_local_lines), - multibyte_chars: RefCell::new(file_local_multibyte_chars), - non_narrow_chars: RefCell::new(file_local_non_narrow_chars), + lines: Lock::new(file_local_lines), + multibyte_chars: Lock::new(file_local_multibyte_chars), + non_narrow_chars: Lock::new(file_local_non_narrow_chars), name_hash, }); - files.push(filemap.clone()); + let mut files = self.files.borrow_mut(); - self.stable_id_to_filemap - .borrow_mut() - .insert(StableFilemapId::new(&filemap), filemap.clone()); + files.file_maps.push(filemap.clone()); + files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone()); filemap } @@ -401,8 +405,7 @@ impl CodeMap { pub fn lookup_line(&self, pos: BytePos) -> Result> { let idx = self.lookup_filemap_idx(pos); - let files = self.files.borrow(); - let f = (*files)[idx].clone(); + let f = (*self.files.borrow().file_maps)[idx].clone(); match f.lookup_line(pos) { Some(line) => Ok(FileMapAndLine { fm: f, line: line }), @@ -456,7 +459,7 @@ impl CodeMap { } pub fn span_to_string(&self, sp: Span) -> String { - if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) { + if self.files.borrow().file_maps.is_empty() && sp.source_equal(&DUMMY_SP) { return "no-location".to_string(); } @@ -594,6 +597,40 @@ impl CodeMap { self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string()) } + /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span + /// if no character could be found or if an error occurred while retrieving the code snippet. + pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { + if let Ok(prev_source) = self.span_to_prev_source(sp) { + let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_left(); + if !prev_source.is_empty() && !prev_source.contains('\n') { + return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); + } + } + + sp + } + + /// Extend the given `Span` to just after the previous occurrence of `pat` when surrounded by + /// whitespace. Return the same span if no character could be found or if an error occurred + /// while retrieving the code snippet. + pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool) -> Span { + // assure that the pattern is delimited, to avoid the following + // fn my_fn() + // ^^^^ returned span without the check + // ---------- correct span + for ws in &[" ", "\t", "\n"] { + let pat = pat.to_owned() + ws; + if let Ok(prev_source) = self.span_to_prev_source(sp) { + let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_left(); + if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) { + return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); + } + } + } + + sp + } + /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char` pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { @@ -609,72 +646,6 @@ impl CodeMap { } } - /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span - /// if no character could be found or if an error occurred while retrieving the code snippet. - pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { - if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_left(); - if !prev_source.is_empty() && !prev_source.contains('\n') { - return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); - } - } - - sp - } - - /// Extend the given `Span` to just after the previous occurrence of `pat`. Return the same span - /// if no character could be found or if an error occurred while retrieving the code snippet. - pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str) -> Span { - if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(pat).nth(0).unwrap_or("").trim_left(); - if !prev_source.is_empty() && !prev_source.contains('\n') { - return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); - } - } - - sp - } - - /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or - /// the original `Span`. - /// - /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned. - pub fn span_until_non_whitespace(&self, sp: Span) -> Span { - if let Ok(snippet) = self.span_to_snippet(sp) { - let mut offset = 0; - // get the bytes width of all the non-whitespace characters - for c in snippet.chars().take_while(|c| !c.is_whitespace()) { - offset += c.len_utf8(); - } - // get the bytes width of all the whitespace characters after that - for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) { - offset += c.len_utf8(); - } - if offset > 1 { - return sp.with_hi(BytePos(sp.lo().0 + offset as u32)); - } - } - sp - } - - /// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or - /// the original `Span` in case of error. - /// - /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned. - pub fn span_until_whitespace(&self, sp: Span) -> Span { - if let Ok(snippet) = self.span_to_snippet(sp) { - let mut offset = 0; - // Get the bytes width of all the non-whitespace characters - for c in snippet.chars().take_while(|c| !c.is_whitespace()) { - offset += c.len_utf8(); - } - if offset > 1 { - return sp.with_hi(BytePos(sp.lo().0 + offset as u32)); - } - } - sp - } - /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char` /// `c`. pub fn span_through_char(&self, sp: Span, c: char) -> Span { @@ -686,6 +657,50 @@ impl CodeMap { sp } + /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or + /// the original `Span`. + /// + /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned. + pub fn span_until_non_whitespace(&self, sp: Span) -> Span { + let mut whitespace_found = false; + + self.span_take_while(sp, |c| { + if !whitespace_found && c.is_whitespace() { + whitespace_found = true; + } + + if whitespace_found && !c.is_whitespace() { + false + } else { + true + } + }) + } + + /// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or + /// the original `Span` in case of error. + /// + /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned. + pub fn span_until_whitespace(&self, sp: Span) -> Span { + self.span_take_while(sp, |c| !c.is_whitespace()) + } + + /// Given a `Span`, get a shorter one until `predicate` yields false. + pub fn span_take_while

    (&self, sp: Span, predicate: P) -> Span + where P: for <'r> FnMut(&'r char) -> bool + { + if let Ok(snippet) = self.span_to_snippet(sp) { + let offset = snippet.chars() + .take_while(predicate) + .map(|c| c.len_utf8()) + .sum::(); + + sp.with_hi(BytePos(sp.lo().0 + (offset as u32))) + } else { + sp + } + } + pub fn def_span(&self, sp: Span) -> Span { self.span_until_char(sp, '{') } @@ -791,7 +806,7 @@ impl CodeMap { } pub fn get_filemap(&self, filename: &FileName) -> Option> { - for fm in self.files.borrow().iter() { + for fm in self.files.borrow().file_maps.iter() { if *filename == fm.name { return Some(fm.clone()); } @@ -802,7 +817,7 @@ impl CodeMap { /// For a global BytePos compute the local offset within the containing FileMap pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos { let idx = self.lookup_filemap_idx(bpos); - let fm = (*self.files.borrow())[idx].clone(); + let fm = (*self.files.borrow().file_maps)[idx].clone(); let offset = bpos - fm.start_pos; FileMapAndBytePos {fm: fm, pos: offset} } @@ -810,8 +825,7 @@ impl CodeMap { /// Converts an absolute BytePos to a CharPos relative to the filemap. pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos { let idx = self.lookup_filemap_idx(bpos); - let files = self.files.borrow(); - let map = &(*files)[idx]; + let map = &(*self.files.borrow().file_maps)[idx]; // The number of extra bytes due to multibyte chars in the FileMap let mut total_extra_bytes = 0; @@ -837,7 +851,7 @@ impl CodeMap { // Return the index of the filemap (in self.files) which contains pos. pub fn lookup_filemap_idx(&self, pos: BytePos) -> usize { let files = self.files.borrow(); - let files = &*files; + let files = &files.file_maps; let count = files.len(); // Binary search for the filemap. diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 6013c20daf23..c0855d470c8b 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -13,7 +13,7 @@ use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features use {fold, attr}; use ast; use codemap::Spanned; -use epoch::Epoch; +use edition::Edition; use parse::{token, ParseSess}; use ptr::P; @@ -27,7 +27,7 @@ pub struct StripUnconfigured<'a> { } // `cfg_attr`-process the crate's attributes and compute the crate's features. -pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, epoch: Epoch) +pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, edition: Edition) -> (ast::Crate, Features) { let features; { @@ -47,7 +47,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, epoc return (krate, Features::new()); } - features = get_features(&sess.span_diagnostic, &krate.attrs, epoch); + features = get_features(&sess.span_diagnostic, &krate.attrs, edition); // Avoid reconfiguring malformed `cfg_attr`s if err_count == sess.span_diagnostic.err_count() { @@ -149,17 +149,24 @@ impl<'a> StripUnconfigured<'a> { fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) { // flag the offending attributes for attr in attrs.iter() { - if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { - let mut err = feature_err(self.sess, - "stmt_expr_attributes", - attr.span, - GateIssue::Language, - EXPLAIN_STMT_ATTR_SYNTAX); - if attr.is_sugared_doc { - err.help("`///` is for documentation comments. For a plain comment, use `//`."); - } - err.emit(); + self.maybe_emit_expr_attr_err(attr); + } + } + + /// If attributes are not allowed on expressions, emit an error for `attr` + pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) { + if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { + let mut err = feature_err(self.sess, + "stmt_expr_attributes", + attr.span, + GateIssue::Language, + EXPLAIN_STMT_ATTR_SYNTAX); + + if attr.is_sugared_doc { + err.help("`///` is for documentation comments. For a plain comment, use `//`."); } + + err.emit(); } } diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 549ef88afcc6..bb7988e64bce 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -218,8 +218,6 @@ An inclusive range was used with no end. Erroneous code example: ```compile_fail,E0586 -#![feature(inclusive_range_syntax)] - fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; let x = &tmp[1..=]; // error: inclusive range was used with no end @@ -239,8 +237,6 @@ fn main() { Or put an end to your inclusive range: ``` -#![feature(inclusive_range_syntax)] - fn main() { let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; let x = &tmp[1..=3]; // ok! @@ -254,7 +250,10 @@ An unstable feature was used. Erroneous code example: ```compile_fail,E658 -let x = ::std::u128::MAX; // error: use of unstable library feature 'i128' +#[repr(u128)] // error: use of unstable library feature 'repr128' +enum Foo { + Bar(u64), +} ``` If you're using a stable or a beta version of rustc, you won't be able to use @@ -265,10 +264,11 @@ If you're using a nightly version of rustc, just add the corresponding feature to be able to use it: ``` -#![feature(i128)] +#![feature(repr128)] -fn main() { - let x = ::std::u128::MAX; // ok! +#[repr(u128)] // ok! +enum Foo { + Bar(u64), } ``` "##, diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index e8c2d325bd65..aecf32ab6afb 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -19,7 +19,7 @@ use ext::base::{ExtCtxt, MacEager, MacResult}; use ext::build::AstBuilder; use parse::token; use ptr::P; -use symbol::Symbol; +use symbol::{keywords, Symbol}; use tokenstream::{TokenTree}; use util::small_vector::SmallVector; @@ -44,7 +44,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, token_tree: &[TokenTree]) -> Box { let code = match (token_tree.len(), token_tree.get(0)) { - (1, Some(&TokenTree::Token(_, token::Ident(code)))) => code, + (1, Some(&TokenTree::Token(_, token::Ident(code, _)))) => code, _ => unreachable!() }; @@ -82,10 +82,10 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, token_tree.get(1), token_tree.get(2) ) { - (1, Some(&TokenTree::Token(_, token::Ident(ref code))), None, None) => { + (1, Some(&TokenTree::Token(_, token::Ident(ref code, _))), None, None) => { (code, None) }, - (3, Some(&TokenTree::Token(_, token::Ident(ref code))), + (3, Some(&TokenTree::Token(_, token::Ident(ref code, _))), Some(&TokenTree::Token(_, token::Comma)), Some(&TokenTree::Token(_, token::Literal(token::StrRaw(description, _), None)))) => { (code, Some(description)) @@ -150,9 +150,9 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, let (crate_name, name) = match (&token_tree[0], &token_tree[2]) { ( // Crate name. - &TokenTree::Token(_, token::Ident(ref crate_name)), + &TokenTree::Token(_, token::Ident(ref crate_name, _)), // DIAGNOSTICS ident. - &TokenTree::Token(_, token::Ident(ref name)) + &TokenTree::Token(_, token::Ident(ref name, _)) ) => (*&crate_name, name), _ => unreachable!() }; @@ -192,7 +192,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, (descriptions.len(), ecx.expr_vec(span, descriptions)) }); - let static_ = ecx.lifetime(span, Ident::from_str("'static")); + let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident()); let ty_str = ecx.ty_rptr( span, ecx.ty_ident(span, ecx.ident_of("str")), @@ -220,7 +220,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, ty, expr, ), - vis: codemap::respan(span.empty(), ast::VisibilityKind::Public), + vis: codemap::respan(span.shrink_to_lo(), ast::VisibilityKind::Public), span, tokens: None, }) diff --git a/src/libsyntax/epoch.rs b/src/libsyntax/edition.rs similarity index 51% rename from src/libsyntax/epoch.rs rename to src/libsyntax/edition.rs index 32cbc79c550e..e579fc74b426 100644 --- a/src/libsyntax/epoch.rs +++ b/src/libsyntax/edition.rs @@ -11,58 +11,65 @@ use std::fmt; use std::str::FromStr; -/// The epoch of the compiler (RFC 2052) +/// The edition of the compiler (RFC 2052) #[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)] #[non_exhaustive] -pub enum Epoch { - // epochs must be kept in order, newest to oldest +pub enum Edition { + // editions must be kept in order, newest to oldest - /// The 2015 epoch - Epoch2015, - /// The 2018 epoch - Epoch2018, + /// The 2015 edition + Edition2015, + /// The 2018 edition + Edition2018, - // when adding new epochs, be sure to update: + // when adding new editions, be sure to update: // - // - the list in the `parse_epoch` static in librustc::session::config + // - the list in the `parse_edition` static in librustc::session::config // - add a `rust_####()` function to the session // - update the enum in Cargo's sources as well // - // When -Zepoch becomes --epoch, there will - // also be a check for the epoch being nightly-only + // When -Zedition becomes --edition, there will + // also be a check for the edition being nightly-only // somewhere. That will need to be updated - // whenever we're stabilizing/introducing a new epoch + // whenever we're stabilizing/introducing a new edition // as well as changing the default Cargo template. } // must be in order from oldest to newest -pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018]; +pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018]; -impl fmt::Display for Epoch { +impl fmt::Display for Edition { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match *self { - Epoch::Epoch2015 => "2015", - Epoch::Epoch2018 => "2018", + Edition::Edition2015 => "2015", + Edition::Edition2018 => "2018", }; write!(f, "{}", s) } } -impl Epoch { +impl Edition { pub fn lint_name(&self) -> &'static str { match *self { - Epoch::Epoch2015 => "epoch_2015", - Epoch::Epoch2018 => "epoch_2018", + Edition::Edition2015 => "edition_2015", + Edition::Edition2018 => "edition_2018", + } + } + + pub fn feature_name(&self) -> &'static str { + match *self { + Edition::Edition2015 => "rust_2015_preview", + Edition::Edition2018 => "rust_2018_preview", } } } -impl FromStr for Epoch { +impl FromStr for Edition { type Err = (); fn from_str(s: &str) -> Result { match s { - "2015" => Ok(Epoch::Epoch2015), - "2018" => Ok(Epoch::Epoch2018), + "2015" => Ok(Edition::Edition2015), + "2018" => Ok(Edition::Edition2018), _ => Err(()) } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7b333270d041..d3157af984e8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -38,6 +38,8 @@ pub enum Annotatable { Item(P), TraitItem(P), ImplItem(P), + Stmt(P), + Expr(P), } impl HasAttrs for Annotatable { @@ -46,6 +48,8 @@ impl HasAttrs for Annotatable { Annotatable::Item(ref item) => &item.attrs, Annotatable::TraitItem(ref trait_item) => &trait_item.attrs, Annotatable::ImplItem(ref impl_item) => &impl_item.attrs, + Annotatable::Stmt(ref stmt) => stmt.attrs(), + Annotatable::Expr(ref expr) => &expr.attrs, } } @@ -54,6 +58,8 @@ impl HasAttrs for Annotatable { Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)), Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)), Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)), + Annotatable::Stmt(stmt) => Annotatable::Stmt(stmt.map_attrs(f)), + Annotatable::Expr(expr) => Annotatable::Expr(expr.map_attrs(f)), } } } @@ -64,6 +70,8 @@ impl Annotatable { Annotatable::Item(ref item) => item.span, Annotatable::TraitItem(ref trait_item) => trait_item.span, Annotatable::ImplItem(ref impl_item) => impl_item.span, + Annotatable::Stmt(ref stmt) => stmt.span, + Annotatable::Expr(ref expr) => expr.span, } } @@ -229,8 +237,9 @@ impl TTMacroExpander for F impl Folder for AvoidInterpolatedIdents { fn fold_tt(&mut self, tt: tokenstream::TokenTree) -> tokenstream::TokenTree { if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt { - if let token::NtIdent(ident) = nt.0 { - return tokenstream::TokenTree::Token(ident.span, token::Ident(ident.node)); + if let token::NtIdent(ident, is_raw) = nt.0 { + return tokenstream::TokenTree::Token(ident.span, + token::Ident(ident.node, is_raw)); } } fold::noop_fold_tt(tt, self) @@ -555,6 +564,8 @@ pub enum SyntaxExtension { /// Whether the contents of the macro can use `unsafe` /// without triggering the `unsafe_code` lint. allow_internal_unsafe: bool, + /// The macro's feature name if it is unstable, and the stability feature + unstable_feature: Option<(Symbol, u32)>, }, /// A function-like syntax extension that has an extra ident before @@ -670,6 +681,7 @@ pub struct ExpansionData { pub depth: usize, pub module: Rc, pub directory_ownership: DirectoryOwnership, + pub crate_span: Option, } /// One of these is made during expansion and incrementally updated as we go; @@ -701,6 +713,7 @@ impl<'a> ExtCtxt<'a> { depth: 0, module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), directory_ownership: DirectoryOwnership::Owned { relative: None }, + crate_span: None, }, expansions: HashMap::new(), } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b88e064e7e56..269517e998f5 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -214,7 +214,7 @@ pub trait AstBuilder { fn arg(&self, span: Span, name: Ident, ty: P) -> ast::Arg; // FIXME unused self - fn fn_decl(&self, inputs: Vec , output: P) -> P; + fn fn_decl(&self, inputs: Vec , output: ast::FunctionRetTy) -> P; fn item_fn_poly(&self, span: Span, @@ -294,7 +294,7 @@ pub trait AstBuilder { vis: ast::Visibility, vp: P) -> P; fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P; fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, - ident: ast::Ident, path: ast::Path) -> P; + ident: Option, path: ast::Path) -> P; fn item_use_list(&self, sp: Span, vis: ast::Visibility, path: Vec, imports: &[ast::Ident]) -> P; fn item_use_glob(&self, sp: Span, @@ -329,9 +329,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { None }; segments.push(ast::PathSegment { identifier: last_identifier, span, parameters }); - let path = ast::Path { span, segments }; - - if global { path.default_to_global() } else { path } + let mut path = ast::Path { span, segments }; + if global { + if let Some(seg) = path.make_root() { + path.segments.insert(0, seg); + } + } + path } /// Constructs a qualified path. @@ -920,7 +924,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { -> P { let fn_decl = self.fn_decl( ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), - self.ty_infer(span)); + ast::FunctionRetTy::Default(span)); // FIXME -- We are using `span` as the span of the `|...|` // part of the lambda, but it probably (maybe?) corresponds to @@ -966,10 +970,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } // FIXME unused self - fn fn_decl(&self, inputs: Vec, output: P) -> P { + fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { P(ast::FnDecl { inputs, - output: ast::FunctionRetTy::Ty(output), + output, variadic: false }) } @@ -983,7 +987,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { attrs, id: ast::DUMMY_NODE_ID, node, - vis: respan(span.empty(), ast::VisibilityKind::Inherited), + vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), span, tokens: None, }) @@ -999,7 +1003,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.item(span, name, Vec::new(), - ast::ItemKind::Fn(self.fn_decl(inputs, output), + ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)), ast::Unsafety::Normal, dummy_spanned(ast::Constness::NotConst), Abi::Rust, @@ -1029,7 +1033,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: ty.span, ty, ident: None, - vis: respan(span.empty(), ast::VisibilityKind::Inherited), + vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), attrs: Vec::new(), id: ast::DUMMY_NODE_ID, } @@ -1159,16 +1163,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P { - let last = path.segments.last().unwrap().identifier; - self.item_use_simple_(sp, vis, last, path) + self.item_use_simple_(sp, vis, None, path) } fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, - ident: ast::Ident, path: ast::Path) -> P { + rename: Option, path: ast::Path) -> P { self.item_use(sp, vis, P(ast::UseTree { span: sp, prefix: path, - kind: ast::UseTreeKind::Simple(ident), + kind: ast::UseTreeKind::Simple(rename), })) } @@ -1178,7 +1181,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { (ast::UseTree { span: sp, prefix: self.path(sp, vec![*id]), - kind: ast::UseTreeKind::Simple(*id), + kind: ast::UseTreeKind::Simple(None), }, ast::DUMMY_NODE_ID) }).collect(); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 377f47a3ea5a..864969c40750 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -18,7 +18,7 @@ use ext::base::*; use ext::derive::{add_derived_markers, collect_derives}; use ext::hygiene::{Mark, SyntaxContext}; use ext::placeholders::{placeholder, PlaceholderExpander}; -use feature_gate::{self, Features, is_builtin_attr}; +use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use fold; use fold::*; use parse::{DirectoryOwnership, PResult}; @@ -229,6 +229,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { module.directory.pop(); self.cx.root_path = module.directory.clone(); self.cx.current_expansion.module = Rc::new(module); + self.cx.current_expansion.crate_span = Some(krate.span); let orig_mod_span = krate.module.inner; @@ -238,7 +239,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { node: ast::ItemKind::Mod(krate.module), ident: keywords::Invalid.ident(), id: ast::DUMMY_NODE_ID, - vis: respan(krate.span.empty(), ast::VisibilityKind::Public), + vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public), tokens: None, }))); @@ -434,6 +435,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::ImplItem(item) => { Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap())) } + Annotatable::Stmt(stmt) => { + Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap())) + } + Annotatable::Expr(expr) => { + Annotatable::Expr(cfg.fold_expr(expr)) + } } } @@ -484,13 +491,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match *ext { MultiModifier(ref mac) => { - let meta = attr.parse_meta(self.cx.parse_sess).ok()?; + let meta = attr.parse_meta(self.cx.parse_sess) + .map_err(|mut e| { e.emit(); }).ok()?; let item = mac.expand(self.cx, attr.span, &meta, item); Some(kind.expect_from_annotatables(item)) } MultiDecorator(ref mac) => { let mut items = Vec::new(); - let meta = attr.parse_meta(self.cx.parse_sess).ok()?; + let meta = attr.parse_meta(self.cx.parse_sess) + .expect("derive meta should already have been parsed"); mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item)); items.push(item); Some(kind.expect_from_annotatables(items)) @@ -500,6 +509,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Item(item) => token::NtItem(item), Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()), Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()), + Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), + Annotatable::Expr(expr) => token::NtExpr(expr), })).into(); let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok); self.parse_expansion(tok_result, kind, &attr.path, attr.span) @@ -531,11 +542,36 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = &mac.node.path; let ident = ident.unwrap_or_else(|| keywords::Invalid.ident()); - let validate_and_set_expn_info = |def_site_span, + let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture + def_site_span: Option, allow_internal_unstable, - allow_internal_unsafe| { + allow_internal_unsafe, + // can't infer this type + unstable_feature: Option<(Symbol, u32)>| { + + // feature-gate the macro invocation + if let Some((feature, issue)) = unstable_feature { + let crate_span = this.cx.current_expansion.crate_span.unwrap(); + // don't stability-check macros in the same crate + // (the only time this is null is for syntax extensions registered as macros) + if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span)) + && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| { + // macro features will count as lib features + !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature) + }) { + let explain = format!("macro {}! is unstable", path); + emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span, + GateIssue::Library(Some(issue)), &explain); + this.cx.trace_macros_diag(); + return Err(kind.dummy(span)); + } + } + if ident.name != keywords::Invalid.name() { - return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident)); + let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); + this.cx.span_err(path.span, &msg); + this.cx.trace_macros_diag(); + return Err(kind.dummy(span)); } mark.set_expn_info(ExpnInfo { call_site: span, @@ -551,11 +587,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let opt_expanded = match *ext { DeclMacro(ref expand, def_span) => { - if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s), - false, false) { - self.cx.span_err(path.span, &msg); - self.cx.trace_macros_diag(); - kind.dummy(span) + if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s), + false, false, None) { + dummy_span } else { kind.make_from(expand.expand(self.cx, span, mac.node.stream())) } @@ -565,14 +599,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ref expander, def_info, allow_internal_unstable, - allow_internal_unsafe + allow_internal_unsafe, + unstable_feature, } => { - if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s), - allow_internal_unstable, - allow_internal_unsafe) { - self.cx.span_err(path.span, &msg); - self.cx.trace_macros_diag(); - kind.dummy(span) + if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), + allow_internal_unstable, + allow_internal_unsafe, + unstable_feature) { + dummy_span } else { kind.make_from(expander.expand(self.cx, span, mac.node.stream())) } @@ -725,6 +759,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Some(expansion) } Err(mut err) => { + err.set_span(span); err.emit(); self.cx.trace_macros_diag(); kind.dummy(span) @@ -770,7 +805,13 @@ impl<'a> Parser<'a> { Expansion::Stmts(stmts) } ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?), - ExpansionKind::OptExpr => Expansion::OptExpr(Some(self.parse_expr()?)), + ExpansionKind::OptExpr => { + if self.token != token::Eof { + Expansion::OptExpr(Some(self.parse_expr()?)) + } else { + Expansion::OptExpr(None) + } + }, ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?), ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?), }) @@ -878,6 +919,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let mut expr = self.cfg.configure_expr(expr).into_inner(); expr.node = self.cfg.configure_expr_kind(expr.node); + let (attr, derives, expr) = self.classify_item(expr); + + if attr.is_some() || !derives.is_empty() { + // collect the invoc regardless of whether or not attributes are permitted here + // expansion will eat the attribute so it won't error later + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + + // ExpansionKind::Expr requires the macro to emit an expression + return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)), ExpansionKind::Expr) + .make_expr(); + } + if let ast::ExprKind::Mac(mac) = expr.node { self.check_attributes(&expr.attrs); self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr() @@ -890,6 +943,16 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let mut expr = configure!(self, expr).into_inner(); expr.node = self.cfg.configure_expr_kind(expr.node); + let (attr, derives, expr) = self.classify_item(expr); + + if attr.is_some() || !derives.is_empty() { + attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); + + return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)), + ExpansionKind::OptExpr) + .make_opt_expr(); + } + if let ast::ExprKind::Mac(mac) = expr.node { self.check_attributes(&expr.attrs); self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr() @@ -912,33 +975,47 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { } fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector { - let stmt = match self.cfg.configure_stmt(stmt) { + let mut stmt = match self.cfg.configure_stmt(stmt) { Some(stmt) => stmt, None => return SmallVector::new(), }; - let (mac, style, attrs) = if let StmtKind::Mac(mac) = stmt.node { - mac.into_inner() - } else { - // The placeholder expander gives ids to statements, so we avoid folding the id here. - let ast::Stmt { id, node, span } = stmt; - return noop_fold_stmt_kind(node, self).into_iter().map(|node| { - ast::Stmt { id: id, node: node, span: span } - }).collect() - }; + // we'll expand attributes on expressions separately + if !stmt.is_expr() { + let (attr, derives, stmt_) = self.classify_item(stmt); - self.check_attributes(&attrs); - let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts).make_stmts(); - - // If this is a macro invocation with a semicolon, then apply that - // semicolon to the final statement produced by expansion. - if style == MacStmtStyle::Semicolon { - if let Some(stmt) = placeholder.pop() { - placeholder.push(stmt.add_trailing_semicolon()); + if attr.is_some() || !derives.is_empty() { + return self.collect_attr(attr, derives, + Annotatable::Stmt(P(stmt_)), ExpansionKind::Stmts) + .make_stmts(); } + + stmt = stmt_; } - placeholder + if let StmtKind::Mac(mac) = stmt.node { + let (mac, style, attrs) = mac.into_inner(); + self.check_attributes(&attrs); + let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts) + .make_stmts(); + + // If this is a macro invocation with a semicolon, then apply that + // semicolon to the final statement produced by expansion. + if style == MacStmtStyle::Semicolon { + if let Some(stmt) = placeholder.pop() { + placeholder.push(stmt.add_trailing_semicolon()); + } + } + + return placeholder; + } + + // The placeholder expander gives ids to statements, so we avoid folding the id here. + let ast::Stmt { id, node, span } = stmt; + noop_fold_stmt_kind(node, self).into_iter().map(|node| { + ast::Stmt { id, node, span } + }).collect() + } fn fold_block(&mut self, block: P) -> P { diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 7a024dbad883..540a03ff032f 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -75,7 +75,7 @@ pub mod rt { impl ToTokens for ast::Ident { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Ident(*self))] + vec![TokenTree::Token(DUMMY_SP, Token::from_ast_ident(*self))] } } @@ -238,7 +238,9 @@ pub mod rt { if i > 0 { inner.push(TokenTree::Token(self.span, token::Colon).into()); } - inner.push(TokenTree::Token(self.span, token::Ident(segment.identifier)).into()); + inner.push(TokenTree::Token( + self.span, token::Token::from_ast_ident(segment.identifier) + ).into()); } inner.push(self.tokens.clone()); @@ -658,10 +660,10 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { token::Literal(token::ByteStr(i), suf) => return mk_lit!("ByteStr", suf, i), token::Literal(token::ByteStrRaw(i, n), suf) => return mk_lit!("ByteStrRaw", suf, i, n), - token::Ident(ident) => { + token::Ident(ident, is_raw) => { return cx.expr_call(sp, mk_token_path(cx, sp, "Ident"), - vec![mk_ident(cx, sp, ident)]); + vec![mk_ident(cx, sp, ident), cx.expr_bool(sp, is_raw)]); } token::Lifetime(ident) => { @@ -709,7 +711,6 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { token::Pound => "Pound", token::Dollar => "Dollar", token::Question => "Question", - token::Underscore => "Underscore", token::Eof => "Eof", token::Whitespace | token::Comment | token::Shebang(_) => { @@ -721,7 +722,7 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, quoted: bool) -> Vec { match *tt { - TokenTree::Token(sp, token::Ident(ident)) if quoted => { + TokenTree::Token(sp, token::Ident(ident, _)) if quoted => { // tt.extend($ident.to_tokens(ext_cx)) let e_to_toks = @@ -858,7 +859,7 @@ fn expand_wrapper(cx: &ExtCtxt, let path = path.iter().map(|s| s.to_string()).collect(); let use_item = cx.item_use_glob( sp, - respan(sp.empty(), ast::VisibilityKind::Inherited), + respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), ids_ext(path), ); cx.stmt_item(sp, use_item) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 0621f728e2a9..8cb331c65da2 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -86,7 +86,7 @@ use self::TokenTreeOrTokenTreeVec::*; use ast::Ident; use syntax_pos::{self, BytePos, Span}; -use codemap::Spanned; +use codemap::respan; use errors::FatalError; use ext::tt::quoted::{self, TokenTree}; use parse::{Directory, ParseSess}; @@ -364,8 +364,8 @@ pub fn parse_failure_msg(tok: Token) -> String { /// Perform a token equality check, ignoring syntax context (that is, an unhygienic comparison) fn token_name_eq(t1: &Token, t2: &Token) -> bool { - if let (Some(id1), Some(id2)) = (t1.ident(), t2.ident()) { - id1.name == id2.name + if let (Some((id1, is_raw1)), Some((id2, is_raw2))) = (t1.ident(), t2.ident()) { + id1.name == id2.name && is_raw1 == is_raw2 } else if let (&token::Lifetime(id1), &token::Lifetime(id2)) = (t1, t2) { id1.name == id2.name } else { @@ -709,6 +709,16 @@ pub fn parse( } } +/// The token is an identifier, but not `_`. +/// We prohibit passing `_` to macros expecting `ident` for now. +fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> { + match *token { + token::Ident(ident, is_raw) if ident.name != keywords::Underscore.name() => + Some((ident, is_raw)), + _ => None, + } +} + /// Checks whether a non-terminal may begin with a particular token. /// /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that @@ -725,10 +735,10 @@ fn may_begin_with(name: &str, token: &Token) -> bool { match name { "expr" => token.can_begin_expr(), "ty" => token.can_begin_type(), - "ident" => token.is_ident(), + "ident" => get_macro_ident(token).is_some(), "vis" => match *token { // The follow-set of :vis + "priv" keyword + interpolated - Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true, + Token::Comma | Token::Ident(..) | Token::Interpolated(_) => true, _ => token.can_begin_type(), }, "block" => match *token { @@ -737,7 +747,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool { token::NtItem(_) | token::NtPat(_) | token::NtTy(_) - | token::NtIdent(_) + | token::NtIdent(..) | token::NtMeta(_) | token::NtPath(_) | token::NtVis(_) => false, // none of these may start with '{'. @@ -746,7 +756,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool { _ => false, }, "path" | "meta" => match *token { - Token::ModSep | Token::Ident(_) => true, + Token::ModSep | Token::Ident(..) => true, Token::Interpolated(ref nt) => match nt.0 { token::NtPath(_) | token::NtMeta(_) => true, _ => may_be_ident(&nt.0), @@ -754,7 +764,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool { _ => false, }, "pat" => match *token { - Token::Ident(_) | // box, ref, mut, and other identifiers (can stricten) + Token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) Token::OpenDelim(token::Paren) | // tuple pattern Token::OpenDelim(token::Bracket) | // slice pattern Token::BinOp(token::And) | // reference @@ -765,8 +775,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool { Token::DotDotDot | // range pattern (future compat) Token::ModSep | // path Token::Lt | // path (UFCS constant) - Token::BinOp(token::Shl) | // path (double UFCS) - Token::Underscore => true, // placeholder + Token::BinOp(token::Shl) => true, // path (double UFCS) Token::Interpolated(ref nt) => may_be_ident(&nt.0), _ => false, }, @@ -815,21 +824,14 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "expr" => token::NtExpr(panictry!(p.parse_expr())), "ty" => token::NtTy(panictry!(p.parse_ty())), // this could be handled like a token, since it is one - "ident" => match p.token { - token::Ident(sn) => { - p.bump(); - token::NtIdent(Spanned:: { - node: sn, - span: p.prev_span, - }) - } - _ => { - let token_str = pprust::token_to_string(&p.token); - p.fatal(&format!("expected ident, found {}", &token_str[..])) - .emit(); - FatalError.raise() - } - }, + "ident" => if let Some((ident, is_raw)) = get_macro_ident(&p.token) { + p.bump(); + token::NtIdent(respan(p.prev_span, ident), is_raw) + } else { + let token_str = pprust::token_to_string(&p.token); + p.fatal(&format!("expected ident, found {}", &token_str)).emit(); + FatalError.raise() + } "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))), "meta" => token::NtMeta(panictry!(p.parse_meta_item())), "vis" => token::NtVis(panictry!(p.parse_visibility(true))), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 9162a582599f..10e5926eb9e3 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -283,11 +283,22 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item) -> Syntax if body.legacy { let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable"); let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe"); + + let unstable_feature = attr::find_stability(&sess.span_diagnostic, + &def.attrs, def.span).and_then(|stability| { + if let attr::StabilityLevel::Unstable { issue, .. } = stability.level { + Some((stability.feature, issue)) + } else { + None + } + }); + NormalTT { expander, def_info: Some((def.id, def.span)), allow_internal_unstable, - allow_internal_unsafe + allow_internal_unsafe, + unstable_feature } } else { SyntaxExtension::DeclMacro(expander, Some((def.id, def.span))) @@ -820,7 +831,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result match *tok { TokenTree::Token(_, ref tok) => match *tok { FatArrow | Comma | Eq | BinOp(token::Or) => Ok(true), - Ident(i) if i.name == "if" || i.name == "in" => Ok(true), + Ident(i, false) if i.name == "if" || i.name == "in" => Ok(true), _ => Ok(false) }, _ => Ok(false), @@ -829,7 +840,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result match *tok { OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) | Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true), - Ident(i) if i.name == "as" || i.name == "where" => Ok(true), + Ident(i, false) if i.name == "as" || i.name == "where" => Ok(true), _ => Ok(false) }, TokenTree::MetaVarDecl(_, _, frag) if frag.name == "block" => Ok(true), @@ -849,7 +860,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result match *tok { Comma => Ok(true), - Ident(i) if i.name != "priv" => Ok(true), + Ident(i, is_raw) if is_raw || i.name != "priv" => Ok(true), ref tok => Ok(tok.can_begin_type()) }, TokenTree::MetaVarDecl(_, _, frag) if frag.name == "ident" diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 122bb9ba024a..f324edeb1178 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -200,7 +200,7 @@ pub fn parse( let span = match trees.next() { Some(tokenstream::TokenTree::Token(span, token::Colon)) => match trees.next() { Some(tokenstream::TokenTree::Token(end_sp, ref tok)) => match tok.ident() { - Some(kind) => { + Some((kind, _)) => { let span = end_sp.with_lo(start_sp.lo()); result.push(TokenTree::MetaVarDecl(span, ident, kind)); continue; @@ -289,14 +289,14 @@ where // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special // metavariable that names the crate of the invokation. Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => { - let ident = token.ident().unwrap(); + let (ident, _) = token.ident().unwrap(); let span = ident_span.with_lo(span.lo()); if ident.name == keywords::Crate.name() { let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident }; - TokenTree::Token(span, token::Ident(ident)) + TokenTree::Token(span, token::Ident(ident, false)) } else { TokenTree::MetaVar(span, ident) } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 7883c4bbc164..3f01d5ec6dd8 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -169,7 +169,7 @@ pub fn transcribe(cx: &ExtCtxt, Ident { ctxt: ident.ctxt.apply_mark(cx.current_expansion.mark), ..ident }; sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark)); result.push(TokenTree::Token(sp, token::Dollar).into()); - result.push(TokenTree::Token(sp, token::Ident(ident)).into()); + result.push(TokenTree::Token(sp, token::Token::from_ast_ident(ident)).into()); } } quoted::TokenTree::Delimited(mut span, delimited) => { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index ec9a15d9f2b4..0f039895dee7 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -26,9 +26,9 @@ use self::AttributeType::*; use self::AttributeGate::*; use abi::Abi; -use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax}; +use ast::{self, NodeId, PatKind, RangeEnd}; use attr; -use epoch::Epoch; +use edition::{ALL_EDITIONS, Edition}; use codemap::Spanned; use syntax_pos::{Span, DUMMY_SP}; use errors::{DiagnosticBuilder, Handler, FatalError}; @@ -55,13 +55,13 @@ macro_rules! set { } macro_rules! declare_features { - ($((active, $feature: ident, $ver: expr, $issue: expr, $epoch: expr),)+) => { + ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. const ACTIVE_FEATURES: &'static [(&'static str, &'static str, Option, - Option, fn(&mut Features, Span))] = - &[$((stringify!($feature), $ver, $issue, $epoch, set!($feature))),+]; + Option, fn(&mut Features, Span))] = + &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+]; /// A set of features to be used by later passes. #[derive(Clone)] @@ -145,9 +145,7 @@ declare_features! ( // rustc internal (active, rustc_diagnostic_macros, "1.0.0", None, None), (active, rustc_const_unstable, "1.0.0", None, None), - (active, advanced_slice_patterns, "1.0.0", Some(23121), None), (active, box_syntax, "1.0.0", Some(27779), None), - (active, placement_in_syntax, "1.0.0", Some(27779), None), (active, unboxed_closures, "1.0.0", Some(29625), None), (active, fundamental, "1.0.0", Some(29635), None), @@ -195,7 +193,7 @@ declare_features! ( (active, rustc_attrs, "1.0.0", Some(29642), None), // Allows the use of non lexical lifetimes; RFC 2094 - (active, nll, "1.0.0", Some(43234), None), + (active, nll, "1.0.0", Some(43234), Some(Edition::Edition2018)), // Allows the use of #[allow_internal_unstable]. This is an // attribute on macro_rules! and can't use the attribute handling @@ -268,9 +266,6 @@ declare_features! ( // rustc internal (active, abi_vectorcall, "1.7.0", None, None), - // a..=b and ..=b - (active, inclusive_range_syntax, "1.7.0", Some(28237), None), - // X..Y patterns (active, exclusive_range_pattern, "1.11.0", Some(37854), None), @@ -280,14 +275,8 @@ declare_features! ( // Allows cfg(target_has_atomic = "..."). (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - // Allows `impl Trait` in function return types. - (active, conservative_impl_trait, "1.12.0", Some(34511), None), - - // Allows `impl Trait` in function arguments. - (active, universal_impl_trait, "1.23.0", Some(34511), None), - - // The `!` type - (active, never_type, "1.13.0", Some(35121), None), + // Allows exhaustive pattern matching on types that contain uninhabited types. + (active, exhaustive_patterns, "1.13.0", None, None), // Allows all literals in attribute lists and values of key-value pairs. (active, attr_literals, "1.13.0", Some(34981), None), @@ -299,9 +288,6 @@ declare_features! ( // rustc internal (active, compiler_builtins, "1.13.0", None, None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327) - (active, generic_param_attrs, "1.11.0", Some(34761), None), - // Allows #[link(..., cfg(..))] (active, link_cfg, "1.14.0", Some(37406), None), @@ -313,9 +299,6 @@ declare_features! ( // `extern "ptx-*" fn()` (active, abi_ptx, "1.15.0", None, None), - // The `i128` type - (active, i128_type, "1.16.0", Some(35118), None), - // The `repr(i128)` annotation for enums (active, repr128, "1.16.0", Some(35118), None), @@ -395,24 +378,17 @@ declare_features! ( // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109), None), - // Copy/Clone closures (RFC 2132) - (active, clone_closures, "1.22.0", Some(44490), None), - (active, copy_closures, "1.22.0", Some(44490), None), - // allow `'_` placeholder lifetimes (active, underscore_lifetimes, "1.22.0", Some(44524), None), - // allow `..=` in patterns (RFC 1192) - (active, dotdoteq_in_patterns, "1.22.0", Some(28237), None), - // Default match binding modes (RFC 2005) (active, match_default_bindings, "1.22.0", Some(42640), None), // Trait object syntax with `dyn` prefix - (active, dyn_trait, "1.22.0", Some(44662), Some(Epoch::Epoch2018)), + (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)), // `crate` as visibility modifier, synonymous to `pub(crate)` - (active, crate_visibility_modifier, "1.23.0", Some(45388), None), + (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)), // extern types (active, extern_types, "1.23.0", Some(43467), None), @@ -421,10 +397,10 @@ declare_features! ( (active, arbitrary_self_types, "1.23.0", Some(44874), None), // `crate` in paths - (active, crate_in_paths, "1.23.0", Some(45477), None), + (active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)), // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) - (active, in_band_lifetimes, "1.23.0", Some(44524), None), + (active, in_band_lifetimes, "1.23.0", Some(44524), Some(Edition::Edition2018)), // generic associated types (RFC 1598) (active, generic_associated_types, "1.23.0", Some(44265), None), @@ -433,10 +409,10 @@ declare_features! ( (active, extern_absolute_paths, "1.24.0", Some(44660), None), // `foo.rs` as an alternative to `foo/mod.rs` - (active, non_modrs_mods, "1.24.0", Some(44660), None), + (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)), - // Termination trait in main (RFC 1937) - (active, termination_trait, "1.24.0", Some(43301), None), + // Termination trait in tests (RFC 1937) + (active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)), // Allows use of the :lifetime macro fragment specifier (active, macro_lifetime_matcher, "1.24.0", Some(46895), None), @@ -455,6 +431,18 @@ declare_features! ( // Parentheses in patterns (active, pattern_parentheses, "1.26.0", None, None), + + // `use path as _;` and `extern crate c as _;` + (active, underscore_imports, "1.26.0", Some(48216), None), + + // The #[wasm_custom_section] attribute + (active, wasm_custom_section, "1.26.0", None, None), + + // The #![wasm_import_module] attribute + (active, wasm_import_module, "1.26.0", None, None), + + // Allows keywords to be escaped for use as identifiers + (active, raw_identifiers, "1.26.0", Some(48589), None), ); declare_features! ( @@ -477,6 +465,8 @@ declare_features! ( (removed, allocator, "1.0.0", None, None), // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]` (removed, simd, "1.0.0", Some(27731), None), + // Merged into `slice_patterns` + (removed, advanced_slice_patterns, "1.0.0", Some(23121), None), ); declare_features! ( @@ -554,6 +544,27 @@ declare_features! ( (accepted, match_beginning_vert, "1.25.0", Some(44101), None), // Nested groups in `use` (RFC 2128) (accepted, use_nested_groups, "1.25.0", Some(44494), None), + // a..=b and ..=b + (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), + // allow `..=` in patterns (RFC 1192) + (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + // Termination trait in main (RFC 1937) + (accepted, termination_trait, "1.26.0", Some(43301), None), + // Copy/Clone closures (RFC 2132) + (accepted, clone_closures, "1.26.0", Some(44490), None), + (accepted, copy_closures, "1.26.0", Some(44490), None), + // Allows `impl Trait` in function arguments. + (accepted, universal_impl_trait, "1.26.0", Some(34511), None), + // Allows `impl Trait` in function return types. + (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), + // The `i128` type + (accepted, i128_type, "1.26.0", Some(35118), None), + // Default match binding modes (RFC 2005) + (accepted, match_default_bindings, "1.26.0", Some(42640), None), + // allow `'_` placeholder lifetimes + (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), + // Allows attributes on lifetime/type formal parameters in generics (RFC 1327) + (accepted, generic_param_attrs, "1.26.0", Some(48848), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -831,6 +842,13 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG across crates and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_dump_program_clauses", Whitelisted, Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_dump_program_clauses]` \ + attribute is just used for rustc unit \ + tests and will never be stable", + cfg_fn!(rustc_attrs))), + // RFC #2094 ("nll", Whitelisted, Gated(Stability::Unstable, "nll", @@ -908,6 +926,10 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "the `#[no_debug]` attribute was an experimental feature that has been \ deprecated due to lack of demand", cfg_fn!(no_debug))), + ("wasm_import_module", Normal, Gated(Stability::Unstable, + "wasm_import_module", + "experimental attribute", + cfg_fn!(wasm_import_module))), ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable, "omit_gdb_pretty_printer_section", "the `#[omit_gdb_pretty_printer_section]` \ @@ -995,6 +1017,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "never will be stable", cfg_fn!(rustc_attrs))), + ("wasm_custom_section", Whitelisted, Gated(Stability::Unstable, + "wasm_custom_section", + "attribute is currently unstable", + cfg_fn!(wasm_custom_section))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), @@ -1221,7 +1248,7 @@ const EXPLAIN_BOX_SYNTAX: &'static str = "box expression syntax is experimental; you can call `Box::new` instead."; pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str = - "attributes on non-item statements and expressions are experimental."; + "attributes on expressions are experimental."; pub const EXPLAIN_ASM: &'static str = "inline assembly is not stable enough for use and is subject to change"; @@ -1258,9 +1285,6 @@ pub const EXPLAIN_VIS_MATCHER: &'static str = pub const EXPLAIN_LIFETIME_MATCHER: &'static str = ":lifetime fragment specifier is experimental and subject to change"; -pub const EXPLAIN_PLACEMENT_IN: &'static str = - "placement-in expression syntax is experimental and subject to change."; - pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "Unsized tuple coercion is not stable enough for use and is subject to change"; @@ -1436,9 +1460,24 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) { + if let ast::UseTreeKind::Simple(Some(ident)) = use_tree.kind { + if ident.name == "_" { + gate_feature_post!(&self, underscore_imports, use_tree.span, + "renaming imports with `_` is unstable"); + } + } + + visit::walk_use_tree(self, use_tree, id); + } + fn visit_item(&mut self, i: &'a ast::Item) { match i.node { ast::ItemKind::ExternCrate(_) => { + if i.ident.name == "_" { + gate_feature_post!(&self, underscore_imports, i.span, + "renaming extern crates with `_` is unstable"); + } if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") { gate_feature_post!(&self, macro_reexport, attr.span, "macros re-exports are experimental \ @@ -1566,10 +1605,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::TyKind::BareFn(ref bare_fn_ty) => { self.check_abi(bare_fn_ty.abi, ty.span); } - ast::TyKind::Never => { - gate_feature_post!(&self, never_type, ty.span, - "The `!` type is experimental"); - }, ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => { gate_feature_post!(&self, dyn_trait, ty.span, "`dyn Trait` syntax is unstable"); @@ -1596,31 +1631,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, type_ascription, e.span, "type ascription is experimental"); } - ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => { - gate_feature_post!(&self, inclusive_range_syntax, - e.span, - "inclusive range syntax is experimental"); - } - ast::ExprKind::InPlace(..) => { - gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN); - } ast::ExprKind::Yield(..) => { gate_feature_post!(&self, generators, e.span, "yield syntax is experimental"); } - ast::ExprKind::Lit(ref lit) => { - if let ast::LitKind::Int(_, ref ty) = lit.node { - match *ty { - ast::LitIntType::Signed(ast::IntTy::I128) | - ast::LitIntType::Unsigned(ast::UintTy::U128) => { - gate_feature_post!(&self, i128_type, e.span, - "128-bit integers are not stable"); - } - _ => {} - } - } - } ast::ExprKind::Catch(_) => { gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental"); } @@ -1641,17 +1656,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_pat(&mut self, pattern: &'a ast::Pat) { match pattern.node { - PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => { - gate_feature_post!(&self, advanced_slice_patterns, - pattern.span, - "multiple-element slice matches anywhere \ - but at the end of a slice (e.g. \ - `[0, ..xs, 0]`) are experimental") - } - PatKind::Slice(..) => { + PatKind::Slice(_, Some(ref subslice), _) => { gate_feature_post!(&self, slice_patterns, - pattern.span, - "slice pattern syntax is experimental"); + subslice.span, + "syntax for subslices in slice patterns is not yet stabilized"); } PatKind::Box(..) => { gate_feature_post!(&self, box_patterns, @@ -1662,10 +1670,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, exclusive_range_pattern, pattern.span, "exclusive range pattern syntax is experimental"); } - PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotEq)) => { - gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span, - "`..=` syntax in patterns is experimental"); - } PatKind::Paren(..) => { gate_feature_post!(&self, pattern_parentheses, pattern.span, "parentheses in patterns are unstable"); @@ -1770,47 +1774,18 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } visit::walk_vis(self, vis); } - - fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { - let (attrs, explain) = match *param { - ast::GenericParam::Lifetime(ref ld) => - (&ld.attrs, "attributes on lifetime bindings are experimental"), - ast::GenericParam::Type(ref t) => - (&t.attrs, "attributes on type parameter bindings are experimental"), - }; - - if !attrs.is_empty() { - gate_feature_post!(&self, generic_param_attrs, attrs[0].span, explain); - } - - visit::walk_generic_param(self, param) - } - - fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) { - if lt.ident.name == "'_" { - gate_feature_post!(&self, underscore_lifetimes, lt.span, - "underscore lifetimes are unstable"); - } - visit::walk_lifetime(self, lt) - } } pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], - epoch: Epoch) -> Features { + crate_edition: Edition) -> Features { + fn feature_removed(span_handler: &Handler, span: Span) { + span_err!(span_handler, span, E0557, "feature has been removed"); + } + let mut features = Features::new(); let mut feature_checker = FeatureChecker::default(); - for &(.., f_epoch, set) in ACTIVE_FEATURES.iter() { - if let Some(f_epoch) = f_epoch { - if epoch >= f_epoch { - // FIXME(Manishearth) there is currently no way to set - // lang features by epoch - set(&mut features, DUMMY_SP); - } - } - } - for attr in krate_attrs { if !attr.check_name("feature") { continue @@ -1823,6 +1798,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } Some(list) => { for mi in list { + let name = if let Some(word) = mi.word() { word.name() } else { @@ -1840,11 +1816,26 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], .find(|& &(n, _, _)| name == n) .or_else(|| STABLE_REMOVED_FEATURES.iter() .find(|& &(n, _, _)| name == n)) { - span_err!(span_handler, mi.span, E0557, "feature has been removed"); + feature_removed(span_handler, mi.span); } else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter() .find(|& &(n, _, _)| name == n) { features.declared_stable_lang_features.push((name, mi.span)); + } else if let Some(&edition) = ALL_EDITIONS.iter() + .find(|e| name == e.feature_name()) { + if edition <= crate_edition { + feature_removed(span_handler, mi.span); + } else { + for &(.., f_edition, set) in ACTIVE_FEATURES.iter() { + if let Some(f_edition) = f_edition { + if edition >= f_edition { + // FIXME(Manishearth) there is currently no way to set + // lib features by edition + set(&mut features, DUMMY_SP); + } + } + } + } } else { features.declared_lib_features.push((name, mi.span)); } @@ -1863,8 +1854,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], struct FeatureChecker { proc_macro: Option, custom_attribute: Option, - copy_closures: Option, - clone_closures: Option, } impl FeatureChecker { @@ -1880,14 +1869,6 @@ impl FeatureChecker { if features.custom_attribute { self.custom_attribute = self.custom_attribute.or(Some(span)); } - - if features.copy_closures { - self.copy_closures = self.copy_closures.or(Some(span)); - } - - if features.clone_closures { - self.clone_closures = self.clone_closures.or(Some(span)); - } } fn check(self, handler: &Handler) { @@ -1899,15 +1880,6 @@ impl FeatureChecker { FatalError.raise(); } - - if let (Some(span), None) = (self.copy_closures, self.clone_closures) { - handler.struct_span_err(span, "`#![feature(copy_closures)]` can only be used with \ - `#![feature(clone_closures)]`") - .span_note(span, "`#![feature(copy_closures)]` declared here") - .emit(); - - FatalError.raise(); - } } } @@ -1922,6 +1894,17 @@ pub fn check_crate(krate: &ast::Crate, parse_sess: sess, plugin_attributes, }; + + if !features.raw_identifiers { + for &span in sess.raw_identifier_spans.borrow().iter() { + if !span.allows_unstable() { + gate_feature!(&ctx, raw_identifiers, span, + "raw identifiers are experimental and subject to change" + ); + } + } + } + let visitor = &mut PostExpansionVisitor { context: &ctx }; visitor.whole_crate_feature_gates(krate); visit::walk_crate(visitor, krate); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index bc1854d3cd89..e702bf56e7f8 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -323,7 +323,8 @@ pub fn noop_fold_use_tree(use_tree: UseTree, fld: &mut T) -> UseTree span: fld.new_span(use_tree.span), prefix: fld.fold_path(use_tree.prefix), kind: match use_tree.kind { - UseTreeKind::Simple(ident) => UseTreeKind::Simple(fld.fold_ident(ident)), + UseTreeKind::Simple(rename) => + UseTreeKind::Simple(rename.map(|ident| fld.fold_ident(ident))), UseTreeKind::Glob => UseTreeKind::Glob, UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| { (fld.fold_use_tree(tree), fld.new_id(id)) @@ -577,7 +578,7 @@ pub fn noop_fold_tts(tts: TokenStream, fld: &mut T) -> TokenStream { // apply ident folder if it's an ident, apply other folds to interpolated nodes pub fn noop_fold_token(t: token::Token, fld: &mut T) -> token::Token { match t { - token::Ident(id) => token::Ident(fld.fold_ident(id)), + token::Ident(id, is_raw) => token::Ident(fld.fold_ident(id), is_raw), token::Lifetime(id) => token::Lifetime(fld.fold_ident(id)), token::Interpolated(nt) => { let nt = match Lrc::try_unwrap(nt) { @@ -629,7 +630,8 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)), token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), - token::NtIdent(id) => token::NtIdent(Spanned::{node: fld.fold_ident(id.node), ..id}), + token::NtIdent(id, is_raw) => + token::NtIdent(Spanned::{node: fld.fold_ident(id.node), ..id}, is_raw), token::NtMeta(meta) => token::NtMeta(fld.fold_meta_item(meta)), token::NtPath(path) => token::NtPath(fld.fold_path(path)), token::NtTT(tt) => token::NtTT(fld.fold_tt(tt)), @@ -886,7 +888,7 @@ pub fn noop_fold_block(b: P, folder: &mut T) -> P { pub fn noop_fold_item_kind(i: ItemKind, folder: &mut T) -> ItemKind { match i { - ItemKind::ExternCrate(string) => ItemKind::ExternCrate(string), + ItemKind::ExternCrate(orig_name) => ItemKind::ExternCrate(orig_name), ItemKind::Use(use_tree) => { ItemKind::Use(use_tree.map(|tree| folder.fold_use_tree(tree))) } @@ -1018,7 +1020,7 @@ pub fn noop_fold_crate(Crate {module, attrs, span}: Crate, ident: keywords::Invalid.ident(), attrs, id: ast::DUMMY_NODE_ID, - vis: respan(span.empty(), ast::VisibilityKind::Public), + vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Public), span, node: ast::ItemKind::Mod(module), tokens: None, @@ -1165,9 +1167,6 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Box(e) => { ExprKind::Box(folder.fold_expr(e)) } - ExprKind::InPlace(p, e) => { - ExprKind::InPlace(folder.fold_expr(p), folder.fold_expr(e)) - } ExprKind::Array(exprs) => { ExprKind::Array(folder.fold_exprs(exprs)) } @@ -1386,6 +1385,7 @@ mod tests { use util::parser_testing::{string_to_crate, matches_codepattern}; use print::pprust; use fold; + use with_globals; use super::*; // this version doesn't care about getting comments or docstrings in. @@ -1423,28 +1423,32 @@ mod tests { // make sure idents get transformed everywhere #[test] fn ident_transformation () { - let mut zz_fold = ToZzIdentFolder; - let ast = string_to_crate( - "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string()); - let folded_crate = zz_fold.fold_crate(ast); - assert_pred!( - matches_codepattern, - "matches_codepattern", - pprust::to_string(|s| fake_print_crate(s, &folded_crate)), - "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()); + with_globals(|| { + let mut zz_fold = ToZzIdentFolder; + let ast = string_to_crate( + "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string()); + let folded_crate = zz_fold.fold_crate(ast); + assert_pred!( + matches_codepattern, + "matches_codepattern", + pprust::to_string(|s| fake_print_crate(s, &folded_crate)), + "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()); + }) } // even inside macro defs.... #[test] fn ident_transformation_in_defs () { - let mut zz_fold = ToZzIdentFolder; - let ast = string_to_crate( - "macro_rules! a {(b $c:expr $(d $e:token)f+ => \ - (g $(d $d $e)+))} ".to_string()); - let folded_crate = zz_fold.fold_crate(ast); - assert_pred!( - matches_codepattern, - "matches_codepattern", - pprust::to_string(|s| fake_print_crate(s, &folded_crate)), - "macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string()); + with_globals(|| { + let mut zz_fold = ToZzIdentFolder; + let ast = string_to_crate( + "macro_rules! a {(b $c:expr $(d $e:token)f+ => \ + (g $(d $d $e)+))} ".to_string()); + let folded_crate = zz_fold.fold_crate(ast); + assert_pred!( + matches_codepattern, + "matches_codepattern", + pprust::to_string(|s| fake_print_crate(s, &folded_crate)), + "macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string()); + }) } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index eed3c6914054..b4f34fb12e36 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -26,7 +26,7 @@ use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, CodeMapper}; use errors::DiagnosticId; use errors::emitter::{Emitter, EmitterWriter}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use std::io::{self, Write}; use std::vec; use std::sync::{Arc, Mutex}; @@ -36,7 +36,7 @@ use rustc_serialize::json::{as_json, as_pretty_json}; pub struct JsonEmitter { dst: Box, registry: Option, - cm: Lrc, + cm: Lrc, pretty: bool, /// Whether "approximate suggestions" are enabled in the config approximate_suggestions: bool, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 50e94e5cba7a..dc349c1a3e6a 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -22,9 +22,9 @@ #![feature(unicode)] #![feature(rustc_diagnostic_macros)] -#![feature(match_default_bindings)] +#![cfg_attr(stage0, feature(match_default_bindings))] #![feature(non_exhaustive)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(const_atomic_usize_new)] #![feature(rustc_attrs)] @@ -39,9 +39,12 @@ extern crate std_unicode; pub extern crate rustc_errors as errors; extern crate syntax_pos; extern crate rustc_data_structures; +#[macro_use] extern crate scoped_tls; extern crate serialize as rustc_serialize; // used by deriving +use rustc_data_structures::sync::Lock; + // A variant of 'try!' that panics on an Err. This is used as a crutch on the // way towards a non-panic!-prone parser. It should be used for fatal parsing // errors; eventually we plan to convert all code using panictry to just use @@ -72,6 +75,33 @@ macro_rules! unwrap_or { } } +struct Globals { + used_attrs: Lock>, + known_attrs: Lock>, + syntax_pos_globals: syntax_pos::Globals, +} + +impl Globals { + fn new() -> Globals { + Globals { + used_attrs: Lock::new(Vec::new()), + known_attrs: Lock::new(Vec::new()), + syntax_pos_globals: syntax_pos::Globals::new(), + } + } +} + +pub fn with_globals(f: F) -> R + where F: FnOnce() -> R +{ + let globals = Globals::new(); + GLOBALS.set(&globals, || { + syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f) + }) +} + +scoped_thread_local!(static GLOBALS: Globals); + #[macro_use] pub mod diagnostics { #[macro_use] @@ -115,7 +145,7 @@ pub mod codemap; #[macro_use] pub mod config; pub mod entry; -pub mod epoch; +pub mod edition; pub mod feature_gate; pub mod fold; pub mod parse; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 053746b579dc..4c3f42d9c6b7 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -90,7 +90,7 @@ impl<'a> Parser<'a> { debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}", inner_parse_policy, self.token); - let (span, path, tokens, mut style) = match self.token { + let (span, path, tokens, style) = match self.token { token::Pound => { let lo = self.span; self.bump(); @@ -129,15 +129,6 @@ impl<'a> Parser<'a> { } }; - if inner_parse_policy == InnerAttributeParsePolicy::Permitted && - self.token == token::Semi { - self.bump(); - self.span_warn(span, - "this inner attribute syntax is deprecated. The new syntax is \ - `#![foo]`, with a bang and no semicolon"); - style = ast::AttrStyle::Inner; - } - Ok(ast::Attribute { id: attr::mk_attr_id(), style, diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index cdf38453d7ea..068929c8948d 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -14,7 +14,7 @@ use codemap::{CodeMap, FilePathMapping}; use errors::{FatalError, DiagnosticBuilder}; use parse::{token, ParseSess}; use str::char_at; -use symbol::Symbol; +use symbol::{Symbol, keywords}; use std_unicode::property::Pattern_White_Space; use std::borrow::Cow; @@ -34,7 +34,7 @@ pub struct TokenAndSpan { impl Default for TokenAndSpan { fn default() -> Self { - TokenAndSpan { tok: token::Underscore, sp: syntax_pos::DUMMY_SP } + TokenAndSpan { tok: token::Whitespace, sp: syntax_pos::DUMMY_SP } } } @@ -126,7 +126,7 @@ impl<'a> StringReader<'a> { pub fn try_next_token(&mut self) -> Result { assert!(self.fatal_errs.is_empty()); let ret_val = TokenAndSpan { - tok: replace(&mut self.peek_tok, token::Underscore), + tok: replace(&mut self.peek_tok, token::Whitespace), sp: self.peek_span, }; self.advance_token()?; @@ -214,7 +214,7 @@ impl<'a> StringReader<'a> { // Make the range zero-length if the span is invalid. if span.lo() > span.hi() || begin.fm.start_pos != end.fm.start_pos { - span = span.with_hi(span.lo()); + span = span.shrink_to_lo(); } let mut sr = StringReader::new_raw_internal(sess, begin.fm); @@ -611,7 +611,7 @@ impl<'a> StringReader<'a> { // I guess this is the only way to figure out if // we're at the beginning of the file... let cmap = CodeMap::new(FilePathMapping::empty()); - cmap.files.borrow_mut().push(self.filemap.clone()); + cmap.files.borrow_mut().file_maps.push(self.filemap.clone()); let loc = cmap.lookup_char_pos_adj(self.pos); debug!("Skipping a shebang"); if loc.line == 1 && loc.col == CharPos(0) { @@ -1115,32 +1115,53 @@ impl<'a> StringReader<'a> { /// token, and updates the interner fn next_token_inner(&mut self) -> Result { let c = self.ch; - if ident_start(c) && - match (c.unwrap(), self.nextch(), self.nextnextch()) { - // Note: r as in r" or r#" is part of a raw string literal, - // b as in b' is part of a byte literal. - // They are not identifiers, and are handled further down. - ('r', Some('"'), _) | - ('r', Some('#'), _) | - ('b', Some('"'), _) | - ('b', Some('\''), _) | - ('b', Some('r'), Some('"')) | - ('b', Some('r'), Some('#')) => false, - _ => true, - } { - let start = self.pos; - while ident_continue(self.ch) { - self.bump(); - } - return Ok(self.with_str_from(start, |string| { - if string == "_" { - token::Underscore - } else { - // FIXME: perform NFKC normalization here. (Issue #2253) - token::Ident(self.mk_ident(string)) + if ident_start(c) { + let (is_ident_start, is_raw_ident) = + match (c.unwrap(), self.nextch(), self.nextnextch()) { + // r# followed by an identifier starter is a raw identifier. + // This is an exception to the r# case below. + ('r', Some('#'), x) if ident_start(x) => (true, true), + // r as in r" or r#" is part of a raw string literal. + // b as in b' is part of a byte literal. + // They are not identifiers, and are handled further down. + ('r', Some('"'), _) | + ('r', Some('#'), _) | + ('b', Some('"'), _) | + ('b', Some('\''), _) | + ('b', Some('r'), Some('"')) | + ('b', Some('r'), Some('#')) => (false, false), + _ => (true, false), + }; + if is_ident_start { + let raw_start = self.pos; + if is_raw_ident { + // Consume the 'r#' characters. + self.bump(); + self.bump(); } - })); + + let start = self.pos; + while ident_continue(self.ch) { + self.bump(); + } + + return Ok(self.with_str_from(start, |string| { + // FIXME: perform NFKC normalization here. (Issue #2253) + let ident = self.mk_ident(string); + if is_raw_ident && (token::is_path_segment_keyword(ident) || + ident.name == keywords::Underscore.name()) { + self.fatal_span_(raw_start, self.pos, + &format!("`r#{}` is not currently supported.", ident.name) + ).raise(); + } + if is_raw_ident { + let span = self.mk_sp(raw_start, self.pos); + self.sess.raw_identifier_spans.borrow_mut().push(span); + } + token::Ident(ident, is_raw_ident) + })); + } } if is_dec_digit(c) { @@ -1766,6 +1787,7 @@ mod tests { use std::path::PathBuf; use diagnostics::plugin::ErrorMap; use rustc_data_structures::sync::Lock; + use with_globals; fn mk_sess(cm: Lrc) -> ParseSess { let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), Some(cm.clone()), @@ -1778,6 +1800,7 @@ mod tests { included_mod_stack: RefCell::new(Vec::new()), code_map: cm, missing_fragment_specifiers: RefCell::new(HashSet::new()), + raw_identifier_spans: RefCell::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), non_modrs_mods: RefCell::new(vec![]), } @@ -1794,33 +1817,35 @@ mod tests { #[test] fn t1() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - let mut string_reader = setup(&cm, - &sh, - "/* my source file */ fn main() { println!(\"zebra\"); }\n" - .to_string()); - let id = Ident::from_str("fn"); - assert_eq!(string_reader.next_token().tok, token::Comment); - assert_eq!(string_reader.next_token().tok, token::Whitespace); - let tok1 = string_reader.next_token(); - let tok2 = TokenAndSpan { - tok: token::Ident(id), - sp: Span::new(BytePos(21), BytePos(23), NO_EXPANSION), - }; - assert_eq!(tok1, tok2); - assert_eq!(string_reader.next_token().tok, token::Whitespace); - // the 'main' id is already read: - assert_eq!(string_reader.pos.clone(), BytePos(28)); - // read another token: - let tok3 = string_reader.next_token(); - let tok4 = TokenAndSpan { - tok: token::Ident(Ident::from_str("main")), - sp: Span::new(BytePos(24), BytePos(28), NO_EXPANSION), - }; - assert_eq!(tok3, tok4); - // the lparen is already read: - assert_eq!(string_reader.pos.clone(), BytePos(29)) + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + let mut string_reader = setup(&cm, + &sh, + "/* my source file */ fn main() { println!(\"zebra\"); }\n" + .to_string()); + let id = Ident::from_str("fn"); + assert_eq!(string_reader.next_token().tok, token::Comment); + assert_eq!(string_reader.next_token().tok, token::Whitespace); + let tok1 = string_reader.next_token(); + let tok2 = TokenAndSpan { + tok: token::Ident(id, false), + sp: Span::new(BytePos(21), BytePos(23), NO_EXPANSION), + }; + assert_eq!(tok1, tok2); + assert_eq!(string_reader.next_token().tok, token::Whitespace); + // the 'main' id is already read: + assert_eq!(string_reader.pos.clone(), BytePos(28)); + // read another token: + let tok3 = string_reader.next_token(); + let tok4 = TokenAndSpan { + tok: mk_ident("main"), + sp: Span::new(BytePos(24), BytePos(28), NO_EXPANSION), + }; + assert_eq!(tok3, tok4); + // the lparen is already read: + assert_eq!(string_reader.pos.clone(), BytePos(29)) + }) } // check that the given reader produces the desired stream @@ -1833,118 +1858,138 @@ mod tests { // make the identifier by looking up the string in the interner fn mk_ident(id: &str) -> token::Token { - token::Ident(Ident::from_str(id)) + token::Token::from_ast_ident(Ident::from_str(id)) } #[test] fn doublecolonparsing() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - check_tokenization(setup(&cm, &sh, "a b".to_string()), - vec![mk_ident("a"), token::Whitespace, mk_ident("b")]); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + check_tokenization(setup(&cm, &sh, "a b".to_string()), + vec![mk_ident("a"), token::Whitespace, mk_ident("b")]); + }) } #[test] fn dcparsing_2() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - check_tokenization(setup(&cm, &sh, "a::b".to_string()), - vec![mk_ident("a"), token::ModSep, mk_ident("b")]); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + check_tokenization(setup(&cm, &sh, "a::b".to_string()), + vec![mk_ident("a"), token::ModSep, mk_ident("b")]); + }) } #[test] fn dcparsing_3() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - check_tokenization(setup(&cm, &sh, "a ::b".to_string()), - vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + check_tokenization(setup(&cm, &sh, "a ::b".to_string()), + vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]); + }) } #[test] fn dcparsing_4() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - check_tokenization(setup(&cm, &sh, "a:: b".to_string()), - vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + check_tokenization(setup(&cm, &sh, "a:: b".to_string()), + vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]); + }) } #[test] fn character_a() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok, - token::Literal(token::Char(Symbol::intern("a")), None)); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok, + token::Literal(token::Char(Symbol::intern("a")), None)); + }) } #[test] fn character_space() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok, - token::Literal(token::Char(Symbol::intern(" ")), None)); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok, + token::Literal(token::Char(Symbol::intern(" ")), None)); + }) } #[test] fn character_escaped() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok, - token::Literal(token::Char(Symbol::intern("\\n")), None)); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok, + token::Literal(token::Char(Symbol::intern("\\n")), None)); + }) } #[test] fn lifetime_name() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok, - token::Lifetime(Ident::from_str("'abc"))); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok, + token::Lifetime(Ident::from_str("'abc"))); + }) } #[test] fn raw_string() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()) - .next_token() - .tok, - token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None)); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()) + .next_token() + .tok, + token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None)); + }) } #[test] fn literal_suffixes() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - macro_rules! test { - ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ - assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok, - token::Literal(token::$tok_type(Symbol::intern($tok_contents)), - Some(Symbol::intern("suffix")))); - // with a whitespace separator: - assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok, - token::Literal(token::$tok_type(Symbol::intern($tok_contents)), - None)); - }} - } + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + macro_rules! test { + ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ + assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok, + token::Literal(token::$tok_type(Symbol::intern($tok_contents)), + Some(Symbol::intern("suffix")))); + // with a whitespace separator: + assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok, + token::Literal(token::$tok_type(Symbol::intern($tok_contents)), + None)); + }} + } - test!("'a'", Char, "a"); - test!("b'a'", Byte, "a"); - test!("\"a\"", Str_, "a"); - test!("b\"a\"", ByteStr, "a"); - test!("1234", Integer, "1234"); - test!("0b101", Integer, "0b101"); - test!("0xABC", Integer, "0xABC"); - test!("1.0", Float, "1.0"); - test!("1.0e10", Float, "1.0e10"); + test!("'a'", Char, "a"); + test!("b'a'", Byte, "a"); + test!("\"a\"", Str_, "a"); + test!("b\"a\"", ByteStr, "a"); + test!("1234", Integer, "1234"); + test!("0b101", Integer, "0b101"); + test!("0xABC", Integer, "0xABC"); + test!("1.0", Float, "1.0"); + test!("1.0e10", Float, "1.0e10"); - assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok, - token::Literal(token::Integer(Symbol::intern("2")), - Some(Symbol::intern("us")))); - assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok, - token::Literal(token::StrRaw(Symbol::intern("raw"), 3), - Some(Symbol::intern("suffix")))); - assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok, - token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3), - Some(Symbol::intern("suffix")))); + assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok, + token::Literal(token::Integer(Symbol::intern("2")), + Some(Symbol::intern("us")))); + assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok, + token::Literal(token::StrRaw(Symbol::intern("raw"), 3), + Some(Symbol::intern("suffix")))); + assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok, + token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3), + Some(Symbol::intern("suffix")))); + }) } #[test] @@ -1956,27 +2001,31 @@ mod tests { #[test] fn nested_block_comments() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - let mut lexer = setup(&cm, &sh, "/* /* */ */'a'".to_string()); - match lexer.next_token().tok { - token::Comment => {} - _ => panic!("expected a comment!"), - } - assert_eq!(lexer.next_token().tok, - token::Literal(token::Char(Symbol::intern("a")), None)); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + let mut lexer = setup(&cm, &sh, "/* /* */ */'a'".to_string()); + match lexer.next_token().tok { + token::Comment => {} + _ => panic!("expected a comment!"), + } + assert_eq!(lexer.next_token().tok, + token::Literal(token::Char(Symbol::intern("a")), None)); + }) } #[test] fn crlf_comments() { - let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); - let sh = mk_sess(cm.clone()); - let mut lexer = setup(&cm, &sh, "// test\r\n/// test\r\n".to_string()); - let comment = lexer.next_token(); - assert_eq!(comment.tok, token::Comment); - assert_eq!((comment.sp.lo(), comment.sp.hi()), (BytePos(0), BytePos(7))); - assert_eq!(lexer.next_token().tok, token::Whitespace); - assert_eq!(lexer.next_token().tok, - token::DocComment(Symbol::intern("/// test"))); + with_globals(|| { + let cm = Lrc::new(CodeMap::new(FilePathMapping::empty())); + let sh = mk_sess(cm.clone()); + let mut lexer = setup(&cm, &sh, "// test\r\n/// test\r\n".to_string()); + let comment = lexer.next_token(); + assert_eq!(comment.tok, token::Comment); + assert_eq!((comment.sp.lo(), comment.sp.hi()), (BytePos(0), BytePos(7))); + assert_eq!(lexer.next_token().tok, token::Whitespace); + assert_eq!(lexer.next_token().tok, + token::DocComment(Symbol::intern("/// test"))); + }) } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 3fb0c209f70f..1483691a1eae 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -40,7 +40,6 @@ pub mod attr; pub mod common; pub mod classify; -pub mod obsolete; /// Info about a parsing session. pub struct ParseSess { @@ -48,6 +47,9 @@ pub struct ParseSess { pub unstable_features: UnstableFeatures, pub config: CrateConfig, pub missing_fragment_specifiers: RefCell>, + /// Places where raw identifiers were used. This is used for feature gating + /// raw identifiers + pub raw_identifier_spans: RefCell>, /// The registered diagnostics codes pub registered_diagnostics: Lock, // Spans where a `mod foo;` statement was included in a non-mod.rs file. @@ -74,6 +76,7 @@ impl ParseSess { unstable_features: UnstableFeatures::from_environment(), config: HashSet::new(), missing_fragment_specifiers: RefCell::new(HashSet::new()), + raw_identifier_spans: RefCell::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), included_mod_stack: RefCell::new(vec![]), code_map, @@ -298,7 +301,6 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { debug!("parse_str_lit: given {}", escape_default(lit)); let mut res = String::with_capacity(lit.len()); - // FIXME #8372: This could be a for-loop if it didn't borrow the iterator let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace @@ -503,7 +505,6 @@ pub fn byte_lit(lit: &str) -> (u8, usize) { pub fn byte_str_lit(lit: &str) -> Lrc> { let mut res = Vec::with_capacity(lit.len()); - // FIXME #8372: This could be a for-loop if it didn't borrow the iterator let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace @@ -680,6 +681,7 @@ mod tests { use util::parser_testing::{string_to_stream, string_to_parser}; use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt}; use util::ThinVec; + use with_globals; // produce a syntax_pos::span fn sp(a: u32, b: u32) -> Span { @@ -691,156 +693,172 @@ mod tests { } #[test] fn path_exprs_1() { - assert!(string_to_expr("a".to_string()) == - P(ast::Expr{ - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Path(None, ast::Path { + with_globals(|| { + assert!(string_to_expr("a".to_string()) == + P(ast::Expr{ + id: ast::DUMMY_NODE_ID, + node: ast::ExprKind::Path(None, ast::Path { + span: sp(0, 1), + segments: vec![str2seg("a", 0, 1)], + }), span: sp(0, 1), - segments: vec![str2seg("a", 0, 1)], - }), - span: sp(0, 1), - attrs: ThinVec::new(), - })) + attrs: ThinVec::new(), + })) + }) } #[test] fn path_exprs_2 () { - assert!(string_to_expr("::a::b".to_string()) == - P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Path(None, ast::Path { + with_globals(|| { + assert!(string_to_expr("::a::b".to_string()) == + P(ast::Expr { + id: ast::DUMMY_NODE_ID, + node: ast::ExprKind::Path(None, ast::Path { + span: sp(0, 6), + segments: vec![ast::PathSegment::crate_root(sp(0, 0)), + str2seg("a", 2, 3), + str2seg("b", 5, 6)] + }), span: sp(0, 6), - segments: vec![ast::PathSegment::crate_root(sp(0, 2)), - str2seg("a", 2, 3), - str2seg("b", 5, 6)] - }), - span: sp(0, 6), - attrs: ThinVec::new(), - })) + attrs: ThinVec::new(), + })) + }) } #[should_panic] #[test] fn bad_path_expr_1() { - string_to_expr("::abc::def::return".to_string()); + with_globals(|| { + string_to_expr("::abc::def::return".to_string()); + }) } // check the token-tree-ization of macros #[test] fn string_to_tts_macro () { - let tts: Vec<_> = - string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect(); - let tts: &[TokenTree] = &tts[..]; + with_globals(|| { + let tts: Vec<_> = + string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect(); + let tts: &[TokenTree] = &tts[..]; - match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) { - ( - 4, - Some(&TokenTree::Token(_, token::Ident(name_macro_rules))), - Some(&TokenTree::Token(_, token::Not)), - Some(&TokenTree::Token(_, token::Ident(name_zip))), - Some(&TokenTree::Delimited(_, ref macro_delimed)), - ) - if name_macro_rules.name == "macro_rules" - && name_zip.name == "zip" => { - let tts = ¯o_delimed.stream().trees().collect::>(); - match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { - ( - 3, - Some(&TokenTree::Delimited(_, ref first_delimed)), - Some(&TokenTree::Token(_, token::FatArrow)), - Some(&TokenTree::Delimited(_, ref second_delimed)), - ) - if macro_delimed.delim == token::Paren => { - let tts = &first_delimed.stream().trees().collect::>(); - match (tts.len(), tts.get(0), tts.get(1)) { - ( - 2, - Some(&TokenTree::Token(_, token::Dollar)), - Some(&TokenTree::Token(_, token::Ident(ident))), - ) - if first_delimed.delim == token::Paren && ident.name == "a" => {}, - _ => panic!("value 3: {:?}", *first_delimed), - } - let tts = &second_delimed.stream().trees().collect::>(); - match (tts.len(), tts.get(0), tts.get(1)) { - ( - 2, - Some(&TokenTree::Token(_, token::Dollar)), - Some(&TokenTree::Token(_, token::Ident(ident))), - ) - if second_delimed.delim == token::Paren - && ident.name == "a" => {}, - _ => panic!("value 4: {:?}", *second_delimed), - } - }, - _ => panic!("value 2: {:?}", *macro_delimed), - } - }, - _ => panic!("value: {:?}",tts), - } + match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) { + ( + 4, + Some(&TokenTree::Token(_, token::Ident(name_macro_rules, false))), + Some(&TokenTree::Token(_, token::Not)), + Some(&TokenTree::Token(_, token::Ident(name_zip, false))), + Some(&TokenTree::Delimited(_, ref macro_delimed)), + ) + if name_macro_rules.name == "macro_rules" + && name_zip.name == "zip" => { + let tts = ¯o_delimed.stream().trees().collect::>(); + match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { + ( + 3, + Some(&TokenTree::Delimited(_, ref first_delimed)), + Some(&TokenTree::Token(_, token::FatArrow)), + Some(&TokenTree::Delimited(_, ref second_delimed)), + ) + if macro_delimed.delim == token::Paren => { + let tts = &first_delimed.stream().trees().collect::>(); + match (tts.len(), tts.get(0), tts.get(1)) { + ( + 2, + Some(&TokenTree::Token(_, token::Dollar)), + Some(&TokenTree::Token(_, token::Ident(ident, false))), + ) + if first_delimed.delim == token::Paren && ident.name == "a" => {}, + _ => panic!("value 3: {:?}", *first_delimed), + } + let tts = &second_delimed.stream().trees().collect::>(); + match (tts.len(), tts.get(0), tts.get(1)) { + ( + 2, + Some(&TokenTree::Token(_, token::Dollar)), + Some(&TokenTree::Token(_, token::Ident(ident, false))), + ) + if second_delimed.delim == token::Paren + && ident.name == "a" => {}, + _ => panic!("value 4: {:?}", *second_delimed), + } + }, + _ => panic!("value 2: {:?}", *macro_delimed), + } + }, + _ => panic!("value: {:?}",tts), + } + }) } #[test] fn string_to_tts_1() { - let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); + with_globals(|| { + let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); - let expected = TokenStream::concat(vec![ - TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"))).into(), - TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"))).into(), - TokenTree::Delimited( - sp(5, 14), - tokenstream::Delimited { - delim: token::DelimToken::Paren, - tts: TokenStream::concat(vec![ - TokenTree::Token(sp(6, 7), token::Ident(Ident::from_str("b"))).into(), - TokenTree::Token(sp(8, 9), token::Colon).into(), - TokenTree::Token(sp(10, 13), token::Ident(Ident::from_str("i32"))).into(), - ]).into(), - }).into(), - TokenTree::Delimited( - sp(15, 21), - tokenstream::Delimited { - delim: token::DelimToken::Brace, - tts: TokenStream::concat(vec![ - TokenTree::Token(sp(17, 18), token::Ident(Ident::from_str("b"))).into(), - TokenTree::Token(sp(18, 19), token::Semi).into(), - ]).into(), - }).into() - ]); + let expected = TokenStream::concat(vec![ + TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(), + TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(), + TokenTree::Delimited( + sp(5, 14), + tokenstream::Delimited { + delim: token::DelimToken::Paren, + tts: TokenStream::concat(vec![ + TokenTree::Token(sp(6, 7), + token::Ident(Ident::from_str("b"), false)).into(), + TokenTree::Token(sp(8, 9), token::Colon).into(), + TokenTree::Token(sp(10, 13), + token::Ident(Ident::from_str("i32"), false)).into(), + ]).into(), + }).into(), + TokenTree::Delimited( + sp(15, 21), + tokenstream::Delimited { + delim: token::DelimToken::Brace, + tts: TokenStream::concat(vec![ + TokenTree::Token(sp(17, 18), + token::Ident(Ident::from_str("b"), false)).into(), + TokenTree::Token(sp(18, 19), token::Semi).into(), + ]).into(), + }).into() + ]); - assert_eq!(tts, expected); + assert_eq!(tts, expected); + }) } #[test] fn ret_expr() { - assert!(string_to_expr("return d".to_string()) == - P(ast::Expr{ - id: ast::DUMMY_NODE_ID, - node:ast::ExprKind::Ret(Some(P(ast::Expr{ + with_globals(|| { + assert!(string_to_expr("return d".to_string()) == + P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node:ast::ExprKind::Path(None, ast::Path{ - span: sp(7, 8), - segments: vec![str2seg("d", 7, 8)], - }), - span:sp(7,8), + node:ast::ExprKind::Ret(Some(P(ast::Expr{ + id: ast::DUMMY_NODE_ID, + node:ast::ExprKind::Path(None, ast::Path{ + span: sp(7, 8), + segments: vec![str2seg("d", 7, 8)], + }), + span:sp(7,8), + attrs: ThinVec::new(), + }))), + span:sp(0,8), attrs: ThinVec::new(), - }))), - span:sp(0,8), - attrs: ThinVec::new(), - })) + })) + }) } #[test] fn parse_stmt_1 () { - assert!(string_to_stmt("b;".to_string()) == - Some(ast::Stmt { - node: ast::StmtKind::Expr(P(ast::Expr { - id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Path(None, ast::Path { - span:sp(0,1), - segments: vec![str2seg("b", 0, 1)], - }), - span: sp(0,1), - attrs: ThinVec::new()})), - id: ast::DUMMY_NODE_ID, - span: sp(0,1)})) - + with_globals(|| { + assert!(string_to_stmt("b;".to_string()) == + Some(ast::Stmt { + node: ast::StmtKind::Expr(P(ast::Expr { + id: ast::DUMMY_NODE_ID, + node: ast::ExprKind::Path(None, ast::Path { + span:sp(0,1), + segments: vec![str2seg("b", 0, 1)], + }), + span: sp(0,1), + attrs: ThinVec::new()})), + id: ast::DUMMY_NODE_ID, + span: sp(0,1)})) + }) } fn parser_done(p: Parser){ @@ -848,120 +866,128 @@ mod tests { } #[test] fn parse_ident_pat () { - let sess = ParseSess::new(FilePathMapping::empty()); - let mut parser = string_to_parser(&sess, "b".to_string()); - assert!(panictry!(parser.parse_pat()) - == P(ast::Pat{ - id: ast::DUMMY_NODE_ID, - node: PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable), - Spanned{ span:sp(0, 1), - node: Ident::from_str("b") - }, - None), - span: sp(0,1)})); - parser_done(parser); + with_globals(|| { + let sess = ParseSess::new(FilePathMapping::empty()); + let mut parser = string_to_parser(&sess, "b".to_string()); + assert!(panictry!(parser.parse_pat()) + == P(ast::Pat{ + id: ast::DUMMY_NODE_ID, + node: PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable), + Spanned{ span:sp(0, 1), + node: Ident::from_str("b") + }, + None), + span: sp(0,1)})); + parser_done(parser); + }) } // check the contents of the tt manually: #[test] fn parse_fundecl () { - // this test depends on the intern order of "fn" and "i32" - let item = string_to_item("fn a (b : i32) { b; }".to_string()).map(|m| { - m.map(|mut m| { - m.tokens = None; - m - }) - }); - assert_eq!(item, - Some( - P(ast::Item{ident:Ident::from_str("a"), - attrs:Vec::new(), - id: ast::DUMMY_NODE_ID, - tokens: None, - node: ast::ItemKind::Fn(P(ast::FnDecl { - inputs: vec![ast::Arg{ - ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Path(None, ast::Path{ - span:sp(10,13), - segments: vec![str2seg("i32", 10, 13)], + with_globals(|| { + // this test depends on the intern order of "fn" and "i32" + let item = string_to_item("fn a (b : i32) { b; }".to_string()).map(|m| { + m.map(|mut m| { + m.tokens = None; + m + }) + }); + assert_eq!(item, + Some( + P(ast::Item{ident:Ident::from_str("a"), + attrs:Vec::new(), + id: ast::DUMMY_NODE_ID, + tokens: None, + node: ast::ItemKind::Fn(P(ast::FnDecl { + inputs: vec![ast::Arg{ + ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, + node: ast::TyKind::Path(None, ast::Path{ + span:sp(10,13), + segments: vec![str2seg("i32", 10, 13)], + }), + span:sp(10,13) }), - span:sp(10,13) - }), - pat: P(ast::Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Ident( - ast::BindingMode::ByValue( - ast::Mutability::Immutable), - Spanned{ - span: sp(6,7), - node: Ident::from_str("b")}, - None - ), - span: sp(6,7) - }), - id: ast::DUMMY_NODE_ID - }], - output: ast::FunctionRetTy::Default(sp(15, 15)), - variadic: false - }), - ast::Unsafety::Normal, - Spanned { - span: sp(0,2), - node: ast::Constness::NotConst, - }, - Abi::Rust, - ast::Generics{ - params: Vec::new(), - where_clause: ast::WhereClause { + pat: P(ast::Pat { id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), + node: PatKind::Ident( + ast::BindingMode::ByValue( + ast::Mutability::Immutable), + Spanned{ + span: sp(6,7), + node: Ident::from_str("b")}, + None + ), + span: sp(6,7) + }), + id: ast::DUMMY_NODE_ID + }], + output: ast::FunctionRetTy::Default(sp(15, 15)), + variadic: false + }), + ast::Unsafety::Normal, + Spanned { + span: sp(0,2), + node: ast::Constness::NotConst, + }, + Abi::Rust, + ast::Generics{ + params: Vec::new(), + where_clause: ast::WhereClause { + id: ast::DUMMY_NODE_ID, + predicates: Vec::new(), + span: syntax_pos::DUMMY_SP, + }, span: syntax_pos::DUMMY_SP, }, - span: syntax_pos::DUMMY_SP, - }, - P(ast::Block { - stmts: vec![ast::Stmt { - node: ast::StmtKind::Semi(P(ast::Expr{ + P(ast::Block { + stmts: vec![ast::Stmt { + node: ast::StmtKind::Semi(P(ast::Expr{ + id: ast::DUMMY_NODE_ID, + node: ast::ExprKind::Path(None, + ast::Path{ + span:sp(17,18), + segments: vec![str2seg("b", 17, 18)], + }), + span: sp(17,18), + attrs: ThinVec::new()})), id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Path(None, - ast::Path{ - span:sp(17,18), - segments: vec![str2seg("b", 17, 18)], - }), - span: sp(17,18), - attrs: ThinVec::new()})), + span: sp(17,19)}], id: ast::DUMMY_NODE_ID, - span: sp(17,19)}], - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Default, // no idea - span: sp(15,21), - recovered: false, - })), - vis: respan(sp(0, 0), ast::VisibilityKind::Inherited), - span: sp(0,21)}))); + rules: ast::BlockCheckMode::Default, // no idea + span: sp(15,21), + recovered: false, + })), + vis: respan(sp(0, 0), ast::VisibilityKind::Inherited), + span: sp(0,21)}))); + }) } #[test] fn parse_use() { - let use_s = "use foo::bar::baz;"; - let vitem = string_to_item(use_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], use_s); + with_globals(|| { + let use_s = "use foo::bar::baz;"; + let vitem = string_to_item(use_s.to_string()).unwrap(); + let vitem_s = item_to_string(&vitem); + assert_eq!(&vitem_s[..], use_s); - let use_s = "use foo::bar as baz;"; - let vitem = string_to_item(use_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], use_s); + let use_s = "use foo::bar as baz;"; + let vitem = string_to_item(use_s.to_string()).unwrap(); + let vitem_s = item_to_string(&vitem); + assert_eq!(&vitem_s[..], use_s); + }) } #[test] fn parse_extern_crate() { - let ex_s = "extern crate foo;"; - let vitem = string_to_item(ex_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], ex_s); + with_globals(|| { + let ex_s = "extern crate foo;"; + let vitem = string_to_item(ex_s.to_string()).unwrap(); + let vitem_s = item_to_string(&vitem); + assert_eq!(&vitem_s[..], ex_s); - let ex_s = "extern crate foo as bar;"; - let vitem = string_to_item(ex_s.to_string()).unwrap(); - let vitem_s = item_to_string(&vitem); - assert_eq!(&vitem_s[..], ex_s); + let ex_s = "extern crate foo as bar;"; + let vitem = string_to_item(ex_s.to_string()).unwrap(); + let vitem_s = item_to_string(&vitem); + assert_eq!(&vitem_s[..], ex_s); + }) } fn get_spans_of_pat_idents(src: &str) -> Vec { @@ -988,31 +1014,36 @@ mod tests { } #[test] fn span_of_self_arg_pat_idents_are_correct() { + with_globals(|| { - let srcs = ["impl z { fn a (&self, &myarg: i32) {} }", - "impl z { fn a (&mut self, &myarg: i32) {} }", - "impl z { fn a (&'a self, &myarg: i32) {} }", - "impl z { fn a (self, &myarg: i32) {} }", - "impl z { fn a (self: Foo, &myarg: i32) {} }", - ]; + let srcs = ["impl z { fn a (&self, &myarg: i32) {} }", + "impl z { fn a (&mut self, &myarg: i32) {} }", + "impl z { fn a (&'a self, &myarg: i32) {} }", + "impl z { fn a (self, &myarg: i32) {} }", + "impl z { fn a (self: Foo, &myarg: i32) {} }", + ]; - for &src in &srcs { - let spans = get_spans_of_pat_idents(src); - let (lo, hi) = (spans[0].lo(), spans[0].hi()); - assert!("self" == &src[lo.to_usize()..hi.to_usize()], - "\"{}\" != \"self\". src=\"{}\"", - &src[lo.to_usize()..hi.to_usize()], src) - } + for &src in &srcs { + let spans = get_spans_of_pat_idents(src); + let (lo, hi) = (spans[0].lo(), spans[0].hi()); + assert!("self" == &src[lo.to_usize()..hi.to_usize()], + "\"{}\" != \"self\". src=\"{}\"", + &src[lo.to_usize()..hi.to_usize()], src) + } + }) } #[test] fn parse_exprs () { - // just make sure that they parse.... - string_to_expr("3 + 4".to_string()); - string_to_expr("a::z.froob(b,&(987+3))".to_string()); + with_globals(|| { + // just make sure that they parse.... + string_to_expr("3 + 4".to_string()); + string_to_expr("a::z.froob(b,&(987+3))".to_string()); + }) } #[test] fn attrs_fix_bug () { - string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) + with_globals(|| { + string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) -> Result, String> { #[cfg(windows)] fn wb() -> c_int { @@ -1024,49 +1055,54 @@ mod tests { let mut fflags: c_int = wb(); }".to_string()); + }) } #[test] fn crlf_doc_comments() { - let sess = ParseSess::new(FilePathMapping::empty()); + with_globals(|| { + let sess = ParseSess::new(FilePathMapping::empty()); - let name = FileName::Custom("source".to_string()); - let source = "/// doc comment\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name.clone(), source, &sess) - .unwrap().unwrap(); - let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); - assert_eq!(doc, "/// doc comment"); + let name = FileName::Custom("source".to_string()); + let source = "/// doc comment\r\nfn foo() {}".to_string(); + let item = parse_item_from_source_str(name.clone(), source, &sess) + .unwrap().unwrap(); + let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); + assert_eq!(doc, "/// doc comment"); - let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name.clone(), source, &sess) - .unwrap().unwrap(); - let docs = item.attrs.iter().filter(|a| a.path == "doc") - .map(|a| a.value_str().unwrap().to_string()).collect::>(); - let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; - assert_eq!(&docs[..], b); + let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); + let item = parse_item_from_source_str(name.clone(), source, &sess) + .unwrap().unwrap(); + let docs = item.attrs.iter().filter(|a| a.path == "doc") + .map(|a| a.value_str().unwrap().to_string()).collect::>(); + let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; + assert_eq!(&docs[..], b); - let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name, source, &sess).unwrap().unwrap(); - let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); - assert_eq!(doc, "/** doc comment\n * with CRLF */"); + let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); + let item = parse_item_from_source_str(name, source, &sess).unwrap().unwrap(); + let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); + assert_eq!(doc, "/** doc comment\n * with CRLF */"); + }); } #[test] fn ttdelim_span() { - let sess = ParseSess::new(FilePathMapping::empty()); - let expr = parse::parse_expr_from_source_str(PathBuf::from("foo").into(), - "foo!( fn main() { body } )".to_string(), &sess).unwrap(); + with_globals(|| { + let sess = ParseSess::new(FilePathMapping::empty()); + let expr = parse::parse_expr_from_source_str(PathBuf::from("foo").into(), + "foo!( fn main() { body } )".to_string(), &sess).unwrap(); - let tts: Vec<_> = match expr.node { - ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(), - _ => panic!("not a macro"), - }; + let tts: Vec<_> = match expr.node { + ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(), + _ => panic!("not a macro"), + }; - let span = tts.iter().rev().next().unwrap().span(); + let span = tts.iter().rev().next().unwrap().span(); - match sess.codemap().span_to_snippet(span) { - Ok(s) => assert_eq!(&s[..], "{ body }"), - Err(_) => panic!("could not get snippet"), - } + match sess.codemap().span_to_snippet(span) { + Ok(s) => assert_eq!(&s[..], "{ body }"), + Err(_) => panic!("could not get snippet"), + } + }); } // This tests that when parsing a string (rather than a file) we don't try @@ -1074,17 +1110,19 @@ mod tests { // See `recurse_into_file_modules` in the parser. #[test] fn out_of_line_mod() { - let sess = ParseSess::new(FilePathMapping::empty()); - let item = parse_item_from_source_str( - PathBuf::from("foo").into(), - "mod foo { struct S; mod this_does_not_exist; }".to_owned(), - &sess, - ).unwrap().unwrap(); + with_globals(|| { + let sess = ParseSess::new(FilePathMapping::empty()); + let item = parse_item_from_source_str( + PathBuf::from("foo").into(), + "mod foo { struct S; mod this_does_not_exist; }".to_owned(), + &sess, + ).unwrap().unwrap(); - if let ast::ItemKind::Mod(ref m) = item.node { - assert!(m.items.len() == 2); - } else { - panic!(); - } + if let ast::ItemKind::Mod(ref m) = item.node { + assert!(m.items.len() == 2); + } else { + panic!(); + } + }); } } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs deleted file mode 100644 index 49a697edf416..000000000000 --- a/src/libsyntax/parse/obsolete.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of -//! these syntaxes is tested by compile-test/obsolete-syntax.rs. -//! -//! Obsolete syntax that becomes too hard to parse can be removed. - -use syntax_pos::Span; -use parse::parser; - -/// The specific types of unsupported syntax -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub enum ObsoleteSyntax { - // Nothing here at the moment -} - -pub trait ParserObsoleteMethods { - /// Reports an obsolete syntax non-fatal error. - fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax); - fn report(&mut self, - sp: Span, - kind: ObsoleteSyntax, - kind_str: &str, - desc: &str, - error: bool); -} - -impl<'a> ParserObsoleteMethods for parser::Parser<'a> { - /// Reports an obsolete syntax non-fatal error. - #[allow(unused_variables)] - #[allow(unreachable_code)] - fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { - let (kind_str, desc, error) = match kind { - // Nothing here at the moment - }; - - self.report(sp, kind, kind_str, desc, error); - } - - fn report(&mut self, - sp: Span, - kind: ObsoleteSyntax, - kind_str: &str, - desc: &str, - error: bool) { - let mut err = if error { - self.diagnostic().struct_span_err(sp, &format!("obsolete syntax: {}", kind_str)) - } else { - self.diagnostic().struct_span_warn(sp, &format!("obsolete syntax: {}", kind_str)) - }; - - if !self.obsolete_set.contains(&kind) && - (error || self.sess.span_diagnostic.flags.can_emit_warnings) { - err.note(desc); - self.obsolete_set.insert(kind); - } - err.emit(); - } -} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f5aa01fb0345..f5ab023b30e8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -48,7 +48,6 @@ use parse::{self, classify, token}; use parse::common::SeqSep; use parse::lexer::TokenAndSpan; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use parse::obsolete::ObsoleteSyntax; use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; use util::parser::{AssocOp, Fixity}; use print::pprust; @@ -59,7 +58,6 @@ use symbol::{Symbol, keywords}; use util::ThinVec; use std::cmp; -use std::collections::HashSet; use std::mem; use std::path::{self, Path, PathBuf}; use std::slice; @@ -229,9 +227,6 @@ pub struct Parser<'a> { /// the previous token kind prev_token_kind: PrevTokenKind, pub restrictions: Restrictions, - /// The set of seen errors about obsolete syntax. Used to suppress - /// extra detail when the same error is seen twice - pub obsolete_set: HashSet, /// Used to determine the path to externally loaded source files pub directory: Directory, /// Whether to parse sub-modules in other files. @@ -358,7 +353,7 @@ impl TokenCursor { let body = TokenTree::Delimited(sp, Delimited { delim: token::Bracket, - tts: [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"))), + tts: [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), TokenTree::Token(sp, token::Eq), TokenTree::Token(sp, token::Literal( token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))] @@ -460,7 +455,7 @@ impl Error { ref dir_path } => { let mut err = struct_span_err!(handler, sp, E0583, "file not found for module `{}`", mod_name); - err.help(&format!("name the file either {} or {} inside the directory {:?}", + err.help(&format!("name the file either {} or {} inside the directory \"{}\"", default_path, secondary_path, dir_path)); @@ -549,13 +544,12 @@ impl<'a> Parser<'a> { -> Self { let mut parser = Parser { sess, - token: token::Underscore, + token: token::Whitespace, span: syntax_pos::DUMMY_SP, prev_span: syntax_pos::DUMMY_SP, meta_var_span: None, prev_token_kind: PrevTokenKind::Other, restrictions: Restrictions::empty(), - obsolete_set: HashSet::new(), recurse_into_file_modules, directory: Directory { path: PathBuf::new(), @@ -784,7 +778,7 @@ impl<'a> Parser<'a> { fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { match self.token { - token::Ident(i) => { + token::Ident(i, _) => { if self.token.is_reserved_ident() { let mut err = self.expected_ident_found(); if recover { @@ -800,11 +794,7 @@ impl<'a> Parser<'a> { Err(if self.prev_token_kind == PrevTokenKind::DocComment { self.span_fatal_err(self.prev_span, Error::UselessDocComment) } else { - let mut err = self.expected_ident_found(); - if self.token == token::Underscore { - err.note("`_` is a wildcard pattern, not an identifier"); - } - err + self.expected_ident_found() }) } } @@ -1512,7 +1502,7 @@ impl<'a> Parser<'a> { if self.eat(&token::RArrow) { Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?)) } else { - Ok(FunctionRetTy::Default(self.span.with_hi(self.span.lo()))) + Ok(FunctionRetTy::Default(self.span.shrink_to_lo())) } } @@ -1602,7 +1592,7 @@ impl<'a> Parser<'a> { let e = self.parse_expr()?; self.expect(&token::CloseDelim(token::Paren))?; TyKind::Typeof(e) - } else if self.eat(&token::Underscore) { + } else if self.eat_keyword(keywords::Underscore) { // A type to be inferred `_` TyKind::Infer } else if self.token_is_bare_fn_keyword() { @@ -1796,7 +1786,7 @@ impl<'a> Parser<'a> { _ => 0, }; - self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) && + self.look_ahead(offset, |t| t.is_ident()) && self.look_ahead(offset + 1, |t| t == &token::Colon) } @@ -1929,7 +1919,7 @@ impl<'a> Parser<'a> { pub fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> { match self.token { - token::Ident(sid) if self.token.is_path_segment_keyword() => { + token::Ident(sid, _) if self.token.is_path_segment_keyword() => { self.bump(); Ok(sid) } @@ -1990,7 +1980,7 @@ impl<'a> Parser<'a> { let lo = self.meta_var_span.unwrap_or(self.span); let mut segments = Vec::new(); if self.eat(&token::ModSep) { - segments.push(PathSegment::crate_root(lo)); + segments.push(PathSegment::crate_root(lo.shrink_to_lo())); } self.parse_path_segments(&mut segments, style, enable_warning)?; @@ -2025,7 +2015,7 @@ impl<'a> Parser<'a> { loop { segments.push(self.parse_path_segment(style, enable_warning)?); - if self.is_import_coupler(false) || !self.eat(&token::ModSep) { + if self.is_import_coupler() || !self.eat(&token::ModSep) { return Ok(()); } } @@ -2744,11 +2734,14 @@ impl<'a> Parser<'a> { } pub fn process_potential_macro_variable(&mut self) { - let ident = match self.token { + let (ident, is_raw) = match self.token { token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() && self.look_ahead(1, |t| t.is_ident()) => { self.bump(); - let name = match self.token { token::Ident(ident) => ident, _ => unreachable!() }; + let name = match self.token { + token::Ident(ident, _) => ident, + _ => unreachable!() + }; let mut err = self.fatal(&format!("unknown macro variable `{}`", name)); err.span_label(self.span, "unknown macro variable"); err.emit(); @@ -2757,13 +2750,13 @@ impl<'a> Parser<'a> { token::Interpolated(ref nt) => { self.meta_var_span = Some(self.span); match nt.0 { - token::NtIdent(ident) => ident, + token::NtIdent(ident, is_raw) => (ident, is_raw), _ => return, } } _ => return, }; - self.token = token::Ident(ident.node); + self.token = token::Ident(ident.node, is_raw); self.span = ident.span; } @@ -2782,7 +2775,7 @@ impl<'a> Parser<'a> { }, token::CloseDelim(_) | token::Eof => unreachable!(), _ => { - let (token, span) = (mem::replace(&mut self.token, token::Underscore), self.span); + let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span); self.bump(); TokenTree::Token(span, token) } @@ -2831,9 +2824,10 @@ impl<'a> Parser<'a> { let (span, e) = self.interpolated_or_expr_span(e)?; let span_of_tilde = lo; let mut err = self.diagnostic().struct_span_err(span_of_tilde, - "`~` can not be used as a unary operator"); - err.span_label(span_of_tilde, "did you mean `!`?"); - err.help("use `!` instead of `~` if you meant to perform bitwise negation"); + "`~` cannot be used as a unary operator"); + err.span_suggestion_short(span_of_tilde, + "use `!` to perform bitwise negation", + "!".to_owned()); err.emit(); (lo.to(span), self.mk_unary(UnOp::Not, e)) } @@ -2856,17 +2850,6 @@ impl<'a> Parser<'a> { let (span, e) = self.interpolated_or_expr_span(e)?; (lo.to(span), ExprKind::AddrOf(m, e)) } - token::Ident(..) if self.token.is_keyword(keywords::In) => { - self.bump(); - let place = self.parse_expr_res( - Restrictions::NO_STRUCT_LITERAL, - None, - )?; - let blk = self.parse_block()?; - let span = blk.span; - let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new()); - (lo.to(span), ExprKind::InPlace(place, blk_expr)) - } token::Ident(..) if self.token.is_keyword(keywords::Box) => { self.bump(); let e = self.parse_prefix_expr(None); @@ -3029,8 +3012,6 @@ impl<'a> Parser<'a> { } AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()), - AssocOp::Inplace => - self.mk_expr(span, ExprKind::InPlace(lhs, rhs), ThinVec::new()), AssocOp::AssignOp(k) => { let aop = match k { token::Plus => BinOpKind::Add, @@ -3389,7 +3370,7 @@ impl<'a> Parser<'a> { None)?; if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { if self.token == token::Token::Semi { - e.span_note(match_span, "did you mean to remove this `match` keyword?"); + e.span_suggestion_short(match_span, "try removing this `match`", "".to_owned()); } return Err(e) } @@ -3621,7 +3602,7 @@ impl<'a> Parser<'a> { slice = Some(P(Pat { id: ast::DUMMY_NODE_ID, node: PatKind::Wild, - span: self.span, + span: self.prev_span, })); before_slice = false; } @@ -3675,7 +3656,13 @@ impl<'a> Parser<'a> { if self.token != token::CloseDelim(token::Brace) { let token_str = self.this_token_to_string(); let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str)); - err.span_label(self.span, "expected `}`"); + if self.token == token::Comma { // Issue #49257 + err.span_label(self.span, + "`..` must be in the last position, \ + and cannot have a trailing comma"); + } else { + err.span_label(self.span, "expected `}`"); + } return Err(err); } etc = true; @@ -3803,16 +3790,17 @@ impl<'a> Parser<'a> { /// Parse a pattern. pub fn parse_pat(&mut self) -> PResult<'a, P> { + self.parse_pat_with_range_pat(true) + } + + /// Parse a pattern, with a setting whether modern range patterns e.g. `a..=b`, `a..b` are + /// allowed. + fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P> { maybe_whole!(self, NtPat, |x| x); let lo = self.span; let pat; match self.token { - token::Underscore => { - // Parse _ - self.bump(); - pat = PatKind::Wild; - } token::BinOp(token::And) | token::AndAnd => { // Parse &pat / &mut pat self.expect_and()?; @@ -3823,7 +3811,7 @@ impl<'a> Parser<'a> { err.span_label(self.span, "unexpected lifetime"); return Err(err); } - let subpat = self.parse_pat()?; + let subpat = self.parse_pat_with_range_pat(false)?; pat = PatKind::Ref(subpat, mutbl); } token::OpenDelim(token::Paren) => { @@ -3842,8 +3830,11 @@ impl<'a> Parser<'a> { self.expect(&token::CloseDelim(token::Bracket))?; pat = PatKind::Slice(before, slice, after); } - // At this point, token != _, &, &&, (, [ - _ => if self.eat_keyword(keywords::Mut) { + // At this point, token != &, &&, (, [ + _ => if self.eat_keyword(keywords::Underscore) { + // Parse _ + pat = PatKind::Wild; + } else if self.eat_keyword(keywords::Mut) { // Parse mut ident @ pat / mut ref ident @ pat let mutref_span = self.prev_span.to(self.span); let binding_mode = if self.eat_keyword(keywords::Ref) { @@ -3862,7 +3853,7 @@ impl<'a> Parser<'a> { pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?; } else if self.eat_keyword(keywords::Box) { // Parse box pat - let subpat = self.parse_pat()?; + let subpat = self.parse_pat_with_range_pat(false)?; pat = PatKind::Box(subpat); } else if self.token.is_ident() && !self.token.is_reserved_ident() && self.parse_as_ident() { @@ -3967,6 +3958,25 @@ impl<'a> Parser<'a> { let pat = Pat { node: pat, span: lo.to(self.prev_span), id: ast::DUMMY_NODE_ID }; let pat = self.maybe_recover_from_bad_qpath(pat, true)?; + if !allow_range_pat { + match pat.node { + PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotDot)) => {} + PatKind::Range(..) => { + let mut err = self.struct_span_err( + pat.span, + "the range pattern here has ambiguous interpretation", + ); + err.span_suggestion( + pat.span, + "add parentheses to clarify the precedence", + format!("({})", pprust::pat_to_string(&pat)), + ); + return Err(err); + } + _ => {} + } + } + Ok(P(pat)) } @@ -4225,7 +4235,7 @@ impl<'a> Parser<'a> { -> PResult<'a, Option>> { let token_lo = self.span; let (ident, def) = match self.token { - token::Ident(ident) if ident.name == keywords::Macro.name() => { + token::Ident(ident, false) if ident.name == keywords::Macro.name() => { self.bump(); let ident = self.parse_ident()?; let tokens = if self.check(&token::OpenDelim(token::Brace)) { @@ -4253,7 +4263,7 @@ impl<'a> Parser<'a> { (ident, ast::MacroDef { tokens: tokens.into(), legacy: false }) } - token::Ident(ident) if ident.name == "macro_rules" && + token::Ident(ident, _) if ident.name == "macro_rules" && self.look_ahead(1, |t| *t == token::Not) => { let prev_span = self.prev_span; self.complain_if_pub_macro(&vis.node, prev_span); @@ -4578,6 +4588,9 @@ impl<'a> Parser<'a> { /// Parse a statement, including the trailing semicolon. pub fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option> { + // skip looking for a trailing semicolon when we have an interpolated statement + maybe_whole!(self, NtStmt, |x| Some(x)); + let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? { Some(stmt) => stmt, None => return Ok(None), @@ -5058,7 +5071,9 @@ impl<'a> Parser<'a> { fn parse_self_arg(&mut self) -> PResult<'a, Option> { let expect_ident = |this: &mut Self| match this.token { // Preserve hygienic context. - token::Ident(ident) => { let sp = this.span; this.bump(); codemap::respan(sp, ident) } + token::Ident(ident, _) => { + let sp = this.span; this.bump(); codemap::respan(sp, ident) + } _ => unreachable!() }; let isolated_self = |this: &mut Self, n| { @@ -5355,13 +5370,15 @@ impl<'a> Parser<'a> { VisibilityKind::Inherited => Ok(()), _ => { let is_macro_rules: bool = match self.token { - token::Ident(sid) => sid.name == Symbol::intern("macro_rules"), + token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"), _ => false, }; if is_macro_rules { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); - err.help("did you mean #[macro_export]?"); + err.span_suggestion(sp, + "try exporting the macro", + "#[macro_export]".to_owned()); Err(err) } else { let mut err = self.diagnostic() @@ -5841,7 +5858,7 @@ impl<'a> Parser<'a> { // `pub(in path)` self.bump(); // `(` self.bump(); // `in` - let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path` + let path = self.parse_path(PathStyle::Mod)?; // `path` self.expect(&token::CloseDelim(token::Paren))?; // `)` let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { path: P(path), @@ -5854,7 +5871,7 @@ impl<'a> Parser<'a> { { // `pub(self)` or `pub(super)` self.bump(); // `(` - let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self` + let path = self.parse_path(PathStyle::Mod)?; // `super`/`self` self.expect(&token::CloseDelim(token::Paren))?; // `)` let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { path: P(path), @@ -6263,23 +6280,17 @@ impl<'a> Parser<'a> { lo: Span, visibility: Visibility, attrs: Vec) - -> PResult<'a, P> { - - let crate_name = self.parse_ident()?; - let (maybe_path, ident) = if let Some(ident) = self.parse_rename()? { - (Some(crate_name.name), ident) + -> PResult<'a, P> { + let orig_name = self.parse_ident()?; + let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { + (rename, Some(orig_name.name)) } else { - (None, crate_name) + (orig_name, None) }; self.expect(&token::Semi)?; - let prev_span = self.prev_span; - - Ok(self.mk_item(lo.to(prev_span), - ident, - ItemKind::ExternCrate(maybe_path), - visibility, - attrs)) + let span = lo.to(self.prev_span); + Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs)) } /// Parse `extern` for foreign ABIs @@ -6458,12 +6469,11 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Use) { // USE ITEM - let item_ = ItemKind::Use(P(self.parse_use_tree(false)?)); + let item_ = ItemKind::Use(P(self.parse_use_tree()?)); self.expect(&token::Semi)?; - let prev_span = self.prev_span; - let invalid = keywords::Invalid.ident(); - let item = self.mk_item(lo.to(prev_span), invalid, item_, visibility, attrs); + let span = lo.to(self.prev_span); + let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs); return Ok(Some(item)); } @@ -6938,90 +6948,53 @@ impl<'a> Parser<'a> { })) } - /// `{` or `::{` or `*` or `::*` - /// `::{` or `::*` (also `{` or `*` if unprefixed is true) - fn is_import_coupler(&mut self, unprefixed: bool) -> bool { - self.is_import_coupler_inner(&token::OpenDelim(token::Brace), unprefixed) || - self.is_import_coupler_inner(&token::BinOp(token::Star), unprefixed) - } - - fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) -> bool { - if self.check(&token::ModSep) { - self.look_ahead(1, |t| t == token) - } else if unprefixed { - self.check(token) - } else { - false - } + /// `::{` or `::*` + fn is_import_coupler(&mut self) -> bool { + self.check(&token::ModSep) && + self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) || + *t == token::BinOp(token::Star)) } /// Parse UseTree /// - /// USE_TREE = `*` | - /// `{` USE_TREE_LIST `}` | + /// USE_TREE = [`::`] `*` | + /// [`::`] `{` USE_TREE_LIST `}` | /// PATH `::` `*` | /// PATH `::` `{` USE_TREE_LIST `}` | /// PATH [`as` IDENT] - fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> { + fn parse_use_tree(&mut self) -> PResult<'a, UseTree> { let lo = self.span; - let mut prefix = ast::Path { - segments: vec![], - span: lo.to(self.span), - }; - - let kind = if self.is_import_coupler(true) { - // `use *;` or `use ::*;` or `use {...};` `use ::{...};` - - // Remove the first `::` + let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() }; + let kind = if self.check(&token::OpenDelim(token::Brace)) || + self.check(&token::BinOp(token::Star)) || + self.is_import_coupler() { + // `use *;` or `use ::*;` or `use {...};` or `use ::{...};` if self.eat(&token::ModSep) { - prefix.segments.push(PathSegment::crate_root(self.prev_span)); - } else if !nested { - prefix.segments.push(PathSegment::crate_root(self.span)); + prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo())); } if self.eat(&token::BinOp(token::Star)) { - // `use *;` UseTreeKind::Glob - } else if self.check(&token::OpenDelim(token::Brace)) { - // `use {...};` - UseTreeKind::Nested(self.parse_use_tree_list()?) } else { - return self.unexpected(); + UseTreeKind::Nested(self.parse_use_tree_list()?) } } else { - // `use path::...;` - let mut parsed = self.parse_path(PathStyle::Mod)?; - if !nested { - parsed = parsed.default_to_global(); - } - - prefix.segments.append(&mut parsed.segments); - prefix.span = prefix.span.to(parsed.span); + // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;` + prefix = self.parse_path(PathStyle::Mod)?; if self.eat(&token::ModSep) { if self.eat(&token::BinOp(token::Star)) { - // `use path::*;` UseTreeKind::Glob - } else if self.check(&token::OpenDelim(token::Brace)) { - // `use path::{...};` - UseTreeKind::Nested(self.parse_use_tree_list()?) } else { - return self.unexpected(); + UseTreeKind::Nested(self.parse_use_tree_list()?) } } else { - // `use path::foo;` or `use path::foo as bar;` - let rename = self.parse_rename()?. - unwrap_or(prefix.segments.last().unwrap().identifier); - UseTreeKind::Simple(rename) + UseTreeKind::Simple(self.parse_rename()?) } }; - Ok(UseTree { - span: lo.to(self.prev_span), - kind, - prefix, - }) + Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) }) } /// Parse UseTreeKind::Nested(list) @@ -7031,13 +7004,19 @@ impl<'a> Parser<'a> { self.parse_unspanned_seq(&token::OpenDelim(token::Brace), &token::CloseDelim(token::Brace), SeqSep::trailing_allowed(token::Comma), |this| { - Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID)) + Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID)) }) } fn parse_rename(&mut self) -> PResult<'a, Option> { if self.eat_keyword(keywords::As) { - self.parse_ident().map(Some) + match self.token { + token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { + self.bump(); // `_` + Ok(Some(Ident { name: ident.name.gensymed(), ..ident })) + } + _ => self.parse_ident().map(Some), + } } else { Ok(None) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 097a2eb89fdf..e2dfca5d10a3 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -91,8 +91,8 @@ impl Lit { } } -fn ident_can_begin_expr(ident: ast::Ident) -> bool { - let ident_token: Token = Ident(ident); +fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool { + let ident_token: Token = Ident(ident, is_raw); !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || @@ -116,12 +116,13 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool { ].contains(&ident.name) } -fn ident_can_begin_type(ident: ast::Ident) -> bool { - let ident_token: Token = Ident(ident); +fn ident_can_begin_type(ident: ast::Ident, is_raw: bool) -> bool { + let ident_token: Token = Ident(ident, is_raw); !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() || [ + keywords::Underscore.name(), keywords::For.name(), keywords::Impl.name(), keywords::Fn.name(), @@ -131,6 +132,44 @@ fn ident_can_begin_type(ident: ast::Ident) -> bool { ].contains(&ident.name) } +pub fn is_path_segment_keyword(id: ast::Ident) -> bool { + id.name == keywords::Super.name() || + id.name == keywords::SelfValue.name() || + id.name == keywords::SelfType.name() || + id.name == keywords::Extern.name() || + id.name == keywords::Crate.name() || + id.name == keywords::CrateRoot.name() || + id.name == keywords::DollarCrate.name() +} + +// We see this identifier in a normal identifier position, like variable name or a type. +// How was it written originally? Did it use the raw form? Let's try to guess. +pub fn is_raw_guess(ident: ast::Ident) -> bool { + ident.name != keywords::Invalid.name() && + is_reserved_ident(ident) && !is_path_segment_keyword(ident) +} + +// Returns true for reserved identifiers used internally for elided lifetimes, +// unnamed method parameters, crate root module, error recovery etc. +pub fn is_special_ident(id: ast::Ident) -> bool { + id.name <= keywords::Underscore.name() +} + +/// Returns `true` if the token is a keyword used in the language. +pub fn is_used_keyword(id: ast::Ident) -> bool { + id.name >= keywords::As.name() && id.name <= keywords::While.name() +} + +/// Returns `true` if the token is a keyword reserved for possible future use. +pub fn is_unused_keyword(id: ast::Ident) -> bool { + id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name() +} + +/// Returns `true` if the token is either a special identifier or a keyword. +pub fn is_reserved_ident(id: ast::Ident) -> bool { + is_special_ident(id) || is_used_keyword(id) || is_unused_keyword(id) +} + #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)] pub enum Token { /* Expression-operator symbols. */ @@ -174,8 +213,7 @@ pub enum Token { Literal(Lit, Option), /* Name components */ - Ident(ast::Ident), - Underscore, + Ident(ast::Ident, /* is_raw */ bool), Lifetime(ast::Ident), // The `LazyTokenStream` is a pure function of the `Nonterminal`, @@ -203,6 +241,11 @@ impl Token { Token::Interpolated(Lrc::new((nt, LazyTokenStream::new()))) } + /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary. + pub fn from_ast_ident(ident: ast::Ident) -> Token { + Ident(ident, is_raw_guess(ident)) + } + /// Returns `true` if the token starts with '>'. pub fn is_like_gt(&self) -> bool { match *self { @@ -214,7 +257,8 @@ impl Token { /// Returns `true` if the token can appear at the start of an expression. pub fn can_begin_expr(&self) -> bool { match *self { - Ident(ident) => ident_can_begin_expr(ident), // value name or keyword + Ident(ident, is_raw) => + ident_can_begin_expr(ident, is_raw), // value name or keyword OpenDelim(..) | // tuple, array or block Literal(..) | // literal Not | // operator not @@ -239,10 +283,10 @@ impl Token { /// Returns `true` if the token can appear at the start of a type. pub fn can_begin_type(&self) -> bool { match *self { - Ident(ident) => ident_can_begin_type(ident), // type name or keyword + Ident(ident, is_raw) => + ident_can_begin_type(ident, is_raw), // type name or keyword OpenDelim(Paren) | // tuple OpenDelim(Bracket) | // array - Underscore | // placeholder Not | // never BinOp(Star) | // raw pointer BinOp(And) | // reference @@ -273,11 +317,11 @@ impl Token { } } - pub fn ident(&self) -> Option { + pub fn ident(&self) -> Option<(ast::Ident, bool)> { match *self { - Ident(ident) => Some(ident), + Ident(ident, is_raw) => Some((ident, is_raw)), Interpolated(ref nt) => match nt.0 { - NtIdent(ident) => Some(ident.node), + NtIdent(ident, is_raw) => Some((ident.node, is_raw)), _ => None, }, _ => None, @@ -352,18 +396,13 @@ impl Token { /// Returns `true` if the token is a given keyword, `kw`. pub fn is_keyword(&self, kw: keywords::Keyword) -> bool { - self.ident().map(|ident| ident.name == kw.name()).unwrap_or(false) + self.ident().map(|(ident, is_raw)| ident.name == kw.name() && !is_raw).unwrap_or(false) } pub fn is_path_segment_keyword(&self) -> bool { match self.ident() { - Some(id) => id.name == keywords::Super.name() || - id.name == keywords::SelfValue.name() || - id.name == keywords::SelfType.name() || - id.name == keywords::Extern.name() || - id.name == keywords::Crate.name() || - id.name == keywords::DollarCrate.name(), - None => false, + Some((id, false)) => is_path_segment_keyword(id), + _ => false, } } @@ -371,7 +410,7 @@ impl Token { // unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(&self) -> bool { match self.ident() { - Some(id) => id.name <= keywords::DollarCrate.name(), + Some((id, false)) => is_special_ident(id), _ => false, } } @@ -379,7 +418,7 @@ impl Token { /// Returns `true` if the token is a keyword used in the language. pub fn is_used_keyword(&self) -> bool { match self.ident() { - Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(), + Some((id, false)) => is_used_keyword(id), _ => false, } } @@ -387,7 +426,7 @@ impl Token { /// Returns `true` if the token is a keyword reserved for possible future use. pub fn is_unused_keyword(&self) -> bool { match self.ident() { - Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(), + Some((id, false)) => is_unused_keyword(id), _ => false, } } @@ -441,7 +480,7 @@ impl Token { Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | - Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None, + Question | OpenDelim(..) | CloseDelim(..) => return None, Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) | Whitespace | Comment | Shebang(..) | Eof => return None, @@ -460,7 +499,10 @@ impl Token { /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { - self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword() + match self.ident() { + Some((id, false)) => is_reserved_ident(id), + _ => false, + } } pub fn interpolated_to_tokenstream(&self, sess: &ParseSess, span: Span) @@ -496,8 +538,8 @@ impl Token { Nonterminal::NtImplItem(ref item) => { tokens = prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span); } - Nonterminal::NtIdent(ident) => { - let token = Token::Ident(ident.node); + Nonterminal::NtIdent(ident, is_raw) => { + let token = Token::Ident(ident.node, is_raw); tokens = Some(TokenTree::Token(ident.span, token).into()); } Nonterminal::NtLifetime(lifetime) => { @@ -529,7 +571,7 @@ pub enum Nonterminal { NtPat(P), NtExpr(P), NtTy(P), - NtIdent(ast::SpannedIdent), + NtIdent(ast::SpannedIdent, /* is_raw */ bool), /// Stuff inside brackets for attributes NtMeta(ast::MetaItem), NtPath(ast::Path), @@ -573,7 +615,7 @@ impl fmt::Debug for Nonterminal { pub fn is_op(tok: &Token) -> bool { match *tok { OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | - Ident(..) | Underscore | Lifetime(..) | Interpolated(..) | + Ident(..) | Lifetime(..) | Interpolated(..) | Whitespace | Comment | Shebang(..) | Eof => false, _ => true, } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 77afafbb4e00..c3785c10f690 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -250,9 +250,9 @@ pub fn token_to_string(tok: &Token) -> String { } /* Name components */ - token::Ident(s) => s.to_string(), + token::Ident(s, false) => s.to_string(), + token::Ident(s, true) => format!("r#{}", s), token::Lifetime(s) => s.to_string(), - token::Underscore => "_".to_string(), /* Other */ token::DocComment(s) => s.to_string(), @@ -262,24 +262,25 @@ pub fn token_to_string(tok: &Token) -> String { token::Shebang(s) => format!("/* shebang: {}*/", s), token::Interpolated(ref nt) => match nt.0 { - token::NtExpr(ref e) => expr_to_string(e), - token::NtMeta(ref e) => meta_item_to_string(e), - token::NtTy(ref e) => ty_to_string(e), - token::NtPath(ref e) => path_to_string(e), - token::NtItem(ref e) => item_to_string(e), - token::NtBlock(ref e) => block_to_string(e), - token::NtStmt(ref e) => stmt_to_string(e), - token::NtPat(ref e) => pat_to_string(e), - token::NtIdent(ref e) => ident_to_string(e.node), - token::NtTT(ref tree) => tt_to_string(tree.clone()), - token::NtArm(ref e) => arm_to_string(e), - token::NtImplItem(ref e) => impl_item_to_string(e), - token::NtTraitItem(ref e) => trait_item_to_string(e), - token::NtGenerics(ref e) => generic_params_to_string(&e.params), - token::NtWhereClause(ref e) => where_clause_to_string(e), - token::NtArg(ref e) => arg_to_string(e), - token::NtVis(ref e) => vis_to_string(e), - token::NtLifetime(ref e) => lifetime_to_string(e), + token::NtExpr(ref e) => expr_to_string(e), + token::NtMeta(ref e) => meta_item_to_string(e), + token::NtTy(ref e) => ty_to_string(e), + token::NtPath(ref e) => path_to_string(e), + token::NtItem(ref e) => item_to_string(e), + token::NtBlock(ref e) => block_to_string(e), + token::NtStmt(ref e) => stmt_to_string(e), + token::NtPat(ref e) => pat_to_string(e), + token::NtIdent(ref e, false) => ident_to_string(e.node), + token::NtIdent(ref e, true) => format!("r#{}", ident_to_string(e.node)), + token::NtTT(ref tree) => tt_to_string(tree.clone()), + token::NtArm(ref e) => arm_to_string(e), + token::NtImplItem(ref e) => impl_item_to_string(e), + token::NtTraitItem(ref e) => trait_item_to_string(e), + token::NtGenerics(ref e) => generic_params_to_string(&e.params), + token::NtWhereClause(ref e) => where_clause_to_string(e), + token::NtArg(ref e) => arg_to_string(e), + token::NtVis(ref e) => vis_to_string(e), + token::NtLifetime(ref e) => lifetime_to_string(e), } } } @@ -353,7 +354,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String { } pub fn path_to_string(p: &ast::Path) -> String { - to_string(|s| s.print_path(p, false, 0, false)) + to_string(|s| s.print_path(p, false, 0)) } pub fn path_segment_to_string(p: &ast::PathSegment) -> String { @@ -1051,7 +1052,7 @@ impl<'a> State<'a> { &f.generic_params)?; } ast::TyKind::Path(None, ref path) => { - self.print_path(path, false, 0, false)?; + self.print_path(path, false, 0)?; } ast::TyKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)? @@ -1174,15 +1175,10 @@ impl<'a> State<'a> { self.print_outer_attributes(&item.attrs)?; self.ann.pre(self, NodeItem(item))?; match item.node { - ast::ItemKind::ExternCrate(ref optional_path) => { + ast::ItemKind::ExternCrate(orig_name) => { self.head(&visibility_qualified(&item.vis, "extern crate"))?; - if let Some(p) = *optional_path { - let val = p.as_str(); - if val.contains('-') { - self.print_string(&val, ast::StrStyle::Cooked)?; - } else { - self.print_name(p)?; - } + if let Some(orig_name) = orig_name { + self.print_name(orig_name)?; self.s.space()?; self.s.word("as")?; self.s.space()?; @@ -1383,7 +1379,7 @@ impl<'a> State<'a> { self.s.word(";")?; } ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => { - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?; @@ -1408,7 +1404,7 @@ impl<'a> State<'a> { } fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> { - self.print_path(&t.path, false, 0, false) + self.print_path(&t.path, false, 0) } fn print_formal_generic_params( @@ -1465,7 +1461,7 @@ impl<'a> State<'a> { ast::CrateSugar::JustCrate => self.word_nbsp("crate") } ast::VisibilityKind::Restricted { ref path, .. } => { - let path = to_string(|s| s.print_path(path, false, 0, true)); + let path = to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { self.word_nbsp(&format!("pub({})", path)) } else { @@ -1573,7 +1569,7 @@ impl<'a> State<'a> { ti.ident, ty, default.as_ref().map(|expr| &**expr), - &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited), + &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited), )?; } ast::TraitItemKind::Method(ref sig, ref body) => { @@ -1584,7 +1580,7 @@ impl<'a> State<'a> { ti.ident, &ti.generics, sig, - &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited), + &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited), )?; if let Some(ref body) = *body { self.nbsp()?; @@ -1599,7 +1595,7 @@ impl<'a> State<'a> { } ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; @@ -1633,7 +1629,7 @@ impl<'a> State<'a> { } ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => { // code copied from ItemKind::Mac: - self.print_path(&node.path, false, 0, false)?; + self.print_path(&node.path, false, 0)?; self.s.word("! ")?; self.cbox(INDENT_UNIT)?; self.popen()?; @@ -1819,7 +1815,7 @@ impl<'a> State<'a> { pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) -> io::Result<()> { - self.print_path(&m.node.path, false, 0, false)?; + self.print_path(&m.node.path, false, 0)?; self.s.word("!")?; match delim { token::Paren => self.popen()?, @@ -1881,16 +1877,6 @@ impl<'a> State<'a> { Ok(()) } - fn print_expr_in_place(&mut self, - place: &ast::Expr, - expr: &ast::Expr) -> io::Result<()> { - let prec = AssocOp::Inplace.precedence() as i8; - self.print_expr_maybe_paren(place, prec + 1)?; - self.s.space()?; - self.word_space("<-")?; - self.print_expr_maybe_paren(expr, prec) - } - fn print_expr_vec(&mut self, exprs: &[P], attrs: &[Attribute]) -> io::Result<()> { self.ibox(INDENT_UNIT)?; @@ -1920,7 +1906,7 @@ impl<'a> State<'a> { fields: &[ast::Field], wth: &Option>, attrs: &[Attribute]) -> io::Result<()> { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.s.word("{")?; self.print_inner_attributes_inline(attrs)?; self.commasep_cmnt( @@ -2060,9 +2046,6 @@ impl<'a> State<'a> { self.word_space("box")?; self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)?; } - ast::ExprKind::InPlace(ref place, ref expr) => { - self.print_expr_in_place(place, expr)?; - } ast::ExprKind::Array(ref exprs) => { self.print_expr_vec(&exprs[..], attrs)?; } @@ -2241,7 +2224,7 @@ impl<'a> State<'a> { } } ast::ExprKind::Path(None, ref path) => { - self.print_path(path, true, 0, false)? + self.print_path(path, true, 0)? } ast::ExprKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, true)? @@ -2377,7 +2360,11 @@ impl<'a> State<'a> { } pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { - self.s.word(&ident.name.as_str())?; + if token::is_raw_guess(ident) { + self.s.word(&format!("r#{}", ident))?; + } else { + self.s.word(&ident.name.as_str())?; + } self.ann.post(self, NodeIdent(&ident)) } @@ -2401,17 +2388,12 @@ impl<'a> State<'a> { fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, - depth: usize, - defaults_to_global: bool) + depth: usize) -> io::Result<()> { self.maybe_print_comment(path.span.lo())?; - let mut segments = path.segments[..path.segments.len()-depth].iter(); - if defaults_to_global && path.is_global() { - segments.next(); - } - for (i, segment) in segments.enumerate() { + for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() { if i > 0 { self.s.word("::")? } @@ -2450,7 +2432,7 @@ impl<'a> State<'a> { self.s.space()?; self.word_space("as")?; let depth = path.segments.len() - qself.position; - self.print_path(path, false, depth, false)?; + self.print_path(path, false, depth)?; } self.s.word(">")?; self.s.word("::")?; @@ -2553,7 +2535,7 @@ impl<'a> State<'a> { } } PatKind::TupleStruct(ref path, ref elts, ddpos) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.popen()?; if let Some(ddpos) = ddpos { self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?; @@ -2571,13 +2553,13 @@ impl<'a> State<'a> { self.pclose()?; } PatKind::Path(None, ref path) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; } PatKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)?; } PatKind::Struct(ref path, ref fields, etc) => { - self.print_path(path, true, 0, false)?; + self.print_path(path, true, 0)?; self.nbsp()?; self.word_space("{")?; self.commasep_cmnt( @@ -2954,18 +2936,17 @@ impl<'a> State<'a> { pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> { match tree.kind { - ast::UseTreeKind::Simple(ref ident) => { - self.print_path(&tree.prefix, false, 0, true)?; - - if tree.prefix.segments.last().unwrap().identifier.name != ident.name { + ast::UseTreeKind::Simple(rename) => { + self.print_path(&tree.prefix, false, 0)?; + if let Some(rename) = rename { self.s.space()?; self.word_space("as")?; - self.print_ident(*ident)?; + self.print_ident(rename)?; } } ast::UseTreeKind::Glob => { if !tree.prefix.segments.is_empty() { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; self.s.word("::")?; } self.s.word("*")?; @@ -2974,7 +2955,7 @@ impl<'a> State<'a> { if tree.prefix.segments.is_empty() { self.s.word("{")?; } else { - self.print_path(&tree.prefix, false, 0, true)?; + self.print_path(&tree.prefix, false, 0)?; self.s.word("::{")?; } self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { @@ -3178,36 +3159,41 @@ mod tests { use ast; use codemap; use syntax_pos; + use with_globals; #[test] fn test_fun_to_string() { - let abba_ident = ast::Ident::from_str("abba"); + with_globals(|| { + let abba_ident = ast::Ident::from_str("abba"); - let decl = ast::FnDecl { - inputs: Vec::new(), - output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP), - variadic: false - }; - let generics = ast::Generics::default(); - assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, - ast::Constness::NotConst, - abba_ident, &generics), - "fn abba()"); + let decl = ast::FnDecl { + inputs: Vec::new(), + output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP), + variadic: false + }; + let generics = ast::Generics::default(); + assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, + ast::Constness::NotConst, + abba_ident, &generics), + "fn abba()"); + }) } #[test] fn test_variant_to_string() { - let ident = ast::Ident::from_str("principal_skinner"); + with_globals(|| { + let ident = ast::Ident::from_str("principal_skinner"); - let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ { - name: ident, - attrs: Vec::new(), - // making this up as I go.... ? - data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), - disr_expr: None, - }); + let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ { + name: ident, + attrs: Vec::new(), + // making this up as I go.... ? + data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), + disr_expr: None, + }); - let varstr = variant_to_string(&var); - assert_eq!(varstr, "principal_skinner"); + let varstr = variant_to_string(&var); + assert_eq!(varstr, "principal_skinner"); + }) } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index da24107f4c33..fdbc795b2d36 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -43,7 +43,7 @@ thread_local! { static INJECTED_CRATE_NAME: Cell> = Cell::new(None); } -pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option) -> ast::Crate { +pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>) -> ast::Crate { let name = if attr::contains_name(&krate.attrs, "no_core") { return krate; } else if attr::contains_name(&krate.attrs, "no_std") { @@ -54,14 +54,12 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option ast::Crate { // Check for #[reexport_test_harness_main = "some_name"] which - // creates a `use some_name = __test::main;`. This needs to be + // creates a `use __test::main as some_name;`. This needs to be // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = @@ -240,7 +240,8 @@ fn mk_reexport_mod(cx: &mut TestCtxt, cx.ext_cx.path(DUMMY_SP, vec![super_, r])) }).chain(tested_submods.into_iter().map(|(r, sym)| { let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); - cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), r, path) + cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), + Some(r), path) })).collect(); let reexport_mod = ast::Mod { @@ -331,7 +332,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => { // If the termination trait is active, the compiler will check that the output // type implements the `Termination` trait as `libtest` enforces that. - let output_matches = if cx.features.termination_trait { + let output_matches = if cx.features.termination_trait_test { true } else { let no_output = match decl.output { @@ -358,7 +359,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { match has_test_signature(cx, i) { Yes => true, No => { - if cx.features.termination_trait { + if cx.features.termination_trait_test { diag.span_err(i.span, "functions used as tests can not have any arguments"); } else { diag.span_err(i.span, "functions used as tests must have signature fn() -> ()"); @@ -387,7 +388,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { // If the termination trait is active, the compiler will check that the output // type implements the `Termination` trait as `libtest` enforces that. - let output_matches = if cx.features.termination_trait { + let output_matches = if cx.features.termination_trait_test { true } else { let no_output = match decl.output { @@ -415,7 +416,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { if has_bench_attr && !has_bench_signature { let diag = cx.span_diagnostic; - if cx.features.termination_trait { + if cx.features.termination_trait_test { diag.span_err(i.span, "functions used as benches must have signature \ `fn(&mut Bencher) -> impl Termination`"); } else { @@ -502,7 +503,7 @@ fn mk_std(cx: &TestCtxt) -> P { (ast::ItemKind::Use(P(ast::UseTree { span: DUMMY_SP, prefix: path_node(vec![id_test]), - kind: ast::UseTreeKind::Simple(id_test), + kind: ast::UseTreeKind::Simple(None), })), ast::VisibilityKind::Public, keywords::Invalid.ident()) } else { @@ -546,7 +547,7 @@ fn mk_main(cx: &mut TestCtxt) -> P { // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); let main_body = ecx.block(sp, vec![call_test_main]); - let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], main_ret_ty), + let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)), ast::Unsafety::Normal, dummy_spanned(ast::Constness::NotConst), ::abi::Abi::Rust, ast::Generics::default(), main_body); @@ -590,13 +591,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P, Option>) { tokens: None, })).pop().unwrap(); let reexport = cx.reexport_test_harness_main.map(|s| { - // building `use = __test::main` - let reexport_ident = Ident::with_empty_ctxt(s); + // building `use __test::main as ;` + let rename = Ident::with_empty_ctxt(s); let use_path = ast::UseTree { span: DUMMY_SP, prefix: path_node(vec![mod_ident, Ident::from_str("main")]), - kind: ast::UseTreeKind::Simple(reexport_ident), + kind: ast::UseTreeKind::Simple(Some(rename)), }; expander.fold_item(P(ast::Item { @@ -627,8 +628,15 @@ fn path_node(ids: Vec) -> ast::Path { } fn path_name_i(idents: &[Ident]) -> String { - // FIXME: Bad copies (#2543 -- same for everything else that says "bad") - idents.iter().map(|i| i.to_string()).collect::>().join("::") + let mut path_name = "".to_string(); + let mut idents_iter = idents.iter().peekable(); + while let Some(ident) = idents_iter.next() { + path_name.push_str(&ident.name.as_str()); + if let Some(_) = idents_iter.peek() { + path_name.push_str("::") + } + } + path_name } fn mk_tests(cx: &TestCtxt) -> P { @@ -681,7 +689,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // gensym information. let span = ignored_span(cx, test.span); - let path = test.path.clone(); let ecx = &cx.ext_cx; let self_id = ecx.ident_of("self"); let test_id = ecx.ident_of("test"); @@ -693,10 +700,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // creates $name: $expr let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr); - debug!("encoding {}", path_name_i(&path[..])); - // path to the #[test] function: "foo::bar::baz" - let path_string = path_name_i(&path[..]); + let path_string = path_name_i(&test.path[..]); + + debug!("encoding {}", path_string); + let name_expr = ecx.expr_str(span, Symbol::intern(&path_string)); // self::test::StaticTestName($name_expr) @@ -743,7 +751,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { diag.bug("expected to find top-level re-export name, but found None"); } }; - visible_path.extend(path); + visible_path.extend_from_slice(&test.path[..]); // Rather than directly give the test function to the test // harness, we create a wrapper like one of the following: diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index 772334e3ef13..81dcc1998edd 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -18,6 +18,7 @@ use std::str; use std::sync::{Arc, Mutex}; use std::path::Path; use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan}; +use with_globals; /// Identify a position in the text by the Nth occurrence of a string. struct Position { @@ -46,37 +47,39 @@ impl Write for Shared { } fn test_harness(file_text: &str, span_labels: Vec, expected_output: &str) { - let output = Arc::new(Mutex::new(Vec::new())); + with_globals(|| { + let output = Arc::new(Mutex::new(Vec::new())); - let code_map = Lrc::new(CodeMap::new(FilePathMapping::empty())); - code_map.new_filemap_and_lines(Path::new("test.rs"), &file_text); + let code_map = Lrc::new(CodeMap::new(FilePathMapping::empty())); + code_map.new_filemap_and_lines(Path::new("test.rs"), &file_text); - let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end); - let mut msp = MultiSpan::from_span(primary_span); - for span_label in span_labels { - let span = make_span(&file_text, &span_label.start, &span_label.end); - msp.push_span_label(span, span_label.label.to_string()); - println!("span: {:?} label: {:?}", span, span_label.label); - println!("text: {:?}", code_map.span_to_snippet(span)); - } + let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end); + let mut msp = MultiSpan::from_span(primary_span); + for span_label in span_labels { + let span = make_span(&file_text, &span_label.start, &span_label.end); + msp.push_span_label(span, span_label.label.to_string()); + println!("span: {:?} label: {:?}", span, span_label.label); + println!("text: {:?}", code_map.span_to_snippet(span)); + } - let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), - Some(code_map.clone()), - false, - false); - let handler = Handler::with_emitter(true, false, Box::new(emitter)); - handler.span_err(msp, "foo"); + let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), + Some(code_map.clone()), + false, + false); + let handler = Handler::with_emitter(true, false, Box::new(emitter)); + handler.span_err(msp, "foo"); - assert!(expected_output.chars().next() == Some('\n'), - "expected output should begin with newline"); - let expected_output = &expected_output[1..]; + assert!(expected_output.chars().next() == Some('\n'), + "expected output should begin with newline"); + let expected_output = &expected_output[1..]; - let bytes = output.lock().unwrap(); - let actual_output = str::from_utf8(&bytes).unwrap(); - println!("expected output:\n------\n{}------", expected_output); - println!("actual output:\n------\n{}------", actual_output); + let bytes = output.lock().unwrap(); + let actual_output = str::from_utf8(&bytes).unwrap(); + println!("expected output:\n------\n{}------", expected_output); + println!("actual output:\n------\n{}------", actual_output); - assert!(expected_output == actual_output) + assert!(expected_output == actual_output) + }) } fn make_span(file_text: &str, start: &Position, end: &Position) -> Span { diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index ad04b6ab2b55..3a7a1b9a6696 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -599,6 +599,7 @@ impl Hash for ThinTokenStream { mod tests { use super::*; use syntax::ast::Ident; + use with_globals; use syntax_pos::{Span, BytePos, NO_EXPANSION}; use parse::token::Token; use util::parser_testing::string_to_stream; @@ -613,67 +614,83 @@ mod tests { #[test] fn test_concat() { - let test_res = string_to_ts("foo::bar::baz"); - let test_fst = string_to_ts("foo::bar"); - let test_snd = string_to_ts("::baz"); - let eq_res = TokenStream::concat(vec![test_fst, test_snd]); - assert_eq!(test_res.trees().count(), 5); - assert_eq!(eq_res.trees().count(), 5); - assert_eq!(test_res.eq_unspanned(&eq_res), true); + with_globals(|| { + let test_res = string_to_ts("foo::bar::baz"); + let test_fst = string_to_ts("foo::bar"); + let test_snd = string_to_ts("::baz"); + let eq_res = TokenStream::concat(vec![test_fst, test_snd]); + assert_eq!(test_res.trees().count(), 5); + assert_eq!(eq_res.trees().count(), 5); + assert_eq!(test_res.eq_unspanned(&eq_res), true); + }) } #[test] fn test_to_from_bijection() { - let test_start = string_to_ts("foo::bar(baz)"); - let test_end = test_start.trees().collect(); - assert_eq!(test_start, test_end) + with_globals(|| { + let test_start = string_to_ts("foo::bar(baz)"); + let test_end = test_start.trees().collect(); + assert_eq!(test_start, test_end) + }) } #[test] fn test_eq_0() { - let test_res = string_to_ts("foo"); - let test_eqs = string_to_ts("foo"); - assert_eq!(test_res, test_eqs) + with_globals(|| { + let test_res = string_to_ts("foo"); + let test_eqs = string_to_ts("foo"); + assert_eq!(test_res, test_eqs) + }) } #[test] fn test_eq_1() { - let test_res = string_to_ts("::bar::baz"); - let test_eqs = string_to_ts("::bar::baz"); - assert_eq!(test_res, test_eqs) + with_globals(|| { + let test_res = string_to_ts("::bar::baz"); + let test_eqs = string_to_ts("::bar::baz"); + assert_eq!(test_res, test_eqs) + }) } #[test] fn test_eq_3() { - let test_res = string_to_ts(""); - let test_eqs = string_to_ts(""); - assert_eq!(test_res, test_eqs) + with_globals(|| { + let test_res = string_to_ts(""); + let test_eqs = string_to_ts(""); + assert_eq!(test_res, test_eqs) + }) } #[test] fn test_diseq_0() { - let test_res = string_to_ts("::bar::baz"); - let test_eqs = string_to_ts("bar::baz"); - assert_eq!(test_res == test_eqs, false) + with_globals(|| { + let test_res = string_to_ts("::bar::baz"); + let test_eqs = string_to_ts("bar::baz"); + assert_eq!(test_res == test_eqs, false) + }) } #[test] fn test_diseq_1() { - let test_res = string_to_ts("(bar,baz)"); - let test_eqs = string_to_ts("bar,baz"); - assert_eq!(test_res == test_eqs, false) + with_globals(|| { + let test_res = string_to_ts("(bar,baz)"); + let test_eqs = string_to_ts("bar,baz"); + assert_eq!(test_res == test_eqs, false) + }) } #[test] fn test_is_empty() { - let test0: TokenStream = Vec::::new().into_iter().collect(); - let test1: TokenStream = - TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a"))).into(); - let test2 = string_to_ts("foo(bar::baz)"); + with_globals(|| { + let test0: TokenStream = Vec::::new().into_iter().collect(); + let test1: TokenStream = + TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a"), false)).into(); + let test2 = string_to_ts("foo(bar::baz)"); - assert_eq!(test0.is_empty(), true); - assert_eq!(test1.is_empty(), false); - assert_eq!(test2.is_empty(), false); + assert_eq!(test0.is_empty(), true); + assert_eq!(test1.is_empty(), false); + assert_eq!(test2.is_empty(), false); + }) } #[test] diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 86963c4000bd..4770273e8c4a 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -56,8 +56,6 @@ pub enum AssocOp { GreaterEqual, /// `=` Assign, - /// `<-` - Inplace, /// `?=` where ? is one of the BinOpToken AssignOp(BinOpToken), /// `as` @@ -86,7 +84,6 @@ impl AssocOp { use self::AssocOp::*; match *t { Token::BinOpEq(k) => Some(AssignOp(k)), - Token::LArrow => Some(Inplace), Token::Eq => Some(Assign), Token::BinOp(BinOpToken::Star) => Some(Multiply), Token::BinOp(BinOpToken::Slash) => Some(Divide), @@ -156,7 +153,6 @@ impl AssocOp { LAnd => 6, LOr => 5, DotDot | DotDotEq => 4, - Inplace => 3, Assign | AssignOp(_) => 2, } } @@ -166,7 +162,7 @@ impl AssocOp { use self::AssocOp::*; // NOTE: it is a bug to have an operators that has same precedence but different fixities! match *self { - Inplace | Assign | AssignOp(_) => Fixity::Right, + Assign | AssignOp(_) => Fixity::Right, As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | LAnd | LOr | Colon => Fixity::Left, @@ -178,7 +174,7 @@ impl AssocOp { use self::AssocOp::*; match *self { Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true, - Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract | + Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | DotDotEq | Colon => false } @@ -187,7 +183,7 @@ impl AssocOp { pub fn is_assign_like(&self) -> bool { use self::AssocOp::*; match *self { - Assign | AssignOp(_) | Inplace => true, + Assign | AssignOp(_) => true, Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | DotDotEq | Colon => false @@ -215,7 +211,7 @@ impl AssocOp { BitOr => Some(BinOpKind::BitOr), LAnd => Some(BinOpKind::And), LOr => Some(BinOpKind::Or), - Inplace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None + Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None } } } @@ -242,7 +238,6 @@ pub enum ExprPrecedence { Binary(BinOpKind), - InPlace, Cast, Type, @@ -310,7 +305,6 @@ impl ExprPrecedence { // Binop-like expr kinds, handled by `AssocOp`. ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8, - ExprPrecedence::InPlace => AssocOp::Inplace.precedence() as i8, ExprPrecedence::Cast => AssocOp::As.precedence() as i8, ExprPrecedence::Type => AssocOp::Colon.precedence() as i8, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5a24c61cb5aa..d8de78054ab6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -213,9 +213,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_vis(&item.vis); visitor.visit_ident(item.span, item.ident); match item.node { - ItemKind::ExternCrate(opt_name) => { - if let Some(name) = opt_name { - visitor.visit_name(item.span, name); + ItemKind::ExternCrate(orig_name) => { + if let Some(orig_name) = orig_name { + visitor.visit_name(item.span, orig_name); } } ItemKind::Use(ref use_tree) => { @@ -354,10 +354,11 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>( visitor: &mut V, use_tree: &'a UseTree, id: NodeId, ) { visitor.visit_path(&use_tree.prefix, id); - match use_tree.kind { - UseTreeKind::Simple(ident) => { - visitor.visit_ident(use_tree.span, ident); + UseTreeKind::Simple(rename) => { + if let Some(rename) = rename { + visitor.visit_ident(use_tree.span, rename); + } } UseTreeKind::Glob => {}, UseTreeKind::Nested(ref use_trees) => { @@ -653,10 +654,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Box(ref subexpression) => { visitor.visit_expr(subexpression) } - ExprKind::InPlace(ref place, ref subexpression) => { - visitor.visit_expr(place); - visitor.visit_expr(subexpression) - } ExprKind::Array(ref subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs new file mode 100644 index 000000000000..8b29e6adeb9e --- /dev/null +++ b/src/libsyntax_ext/assert.rs @@ -0,0 +1,122 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::ast::*; +use syntax::codemap::Spanned; +use syntax::ext::base::*; +use syntax::ext::build::AstBuilder; +use syntax::parse::token; +use syntax::print::pprust; +use syntax::tokenstream::{TokenStream, TokenTree}; +use syntax_pos::{Span, DUMMY_SP}; + +pub fn expand_assert<'cx>( + cx: &'cx mut ExtCtxt, + sp: Span, + tts: &[TokenTree], +) -> Box { + let mut parser = cx.new_parser_from_tts(tts); + let cond_expr = panictry!(parser.parse_expr()); + let custom_msg_args = if parser.eat(&token::Comma) { + let ts = parser.parse_tokens(); + if !ts.is_empty() { + Some(ts) + } else { + None + } + } else { + None + }; + + let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark)); + let panic_call = Mac_ { + path: Path::from_ident(sp, Ident::from_str("panic")), + tts: if let Some(ts) = custom_msg_args { + ts.into() + } else { + // `expr_to_string` escapes the string literals with `.escape_default()` + // which escapes all non-ASCII characters with `\u`. + let escaped_expr = escape_format_string(&unescape_printable_unicode( + &pprust::expr_to_string(&cond_expr), + )); + + TokenStream::from(TokenTree::Token( + DUMMY_SP, + token::Literal( + token::Lit::Str_(Name::intern(&format!("assertion failed: {}", escaped_expr))), + None, + ), + )).into() + }, + }; + let if_expr = cx.expr_if( + sp, + cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), + cx.expr( + sp, + ExprKind::Mac(Spanned { + span: sp, + node: panic_call, + }), + ), + None, + ); + MacEager::expr(if_expr) +} + +/// Escapes a string for use as a formatting string. +fn escape_format_string(s: &str) -> String { + let mut res = String::with_capacity(s.len()); + for c in s.chars() { + res.extend(c.escape_debug()); + match c { + '{' | '}' => res.push(c), + _ => {} + } + } + res +} + +#[test] +fn test_escape_format_string() { + assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\"); +} + +/// Unescapes the escaped unicodes (`\u{...}`) that are printable. +fn unescape_printable_unicode(mut s: &str) -> String { + use std::{char, u32}; + + let mut res = String::with_capacity(s.len()); + + loop { + if let Some(start) = s.find(r"\u{") { + res.push_str(&s[0..start]); + s = &s[start..]; + s.find('}') + .and_then(|end| { + let v = u32::from_str_radix(&s[3..end], 16).ok()?; + let c = char::from_u32(v)?; + // Escape unprintable characters. + res.extend(c.escape_debug()); + s = &s[end + 1..]; + Some(()) + }) + .expect("lexer should have rejected invalid escape sequences"); + } else { + res.push_str(s); + return res; + } + } +} + +#[test] +fn test_unescape_printable_unicode() { + assert!(unescape_printable_unicode(r"\u{2603}\n\u{0}") == r"☃\n\u{0}"); +} diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 8d0104e512bf..d513008f0e2d 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -44,7 +44,8 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, } } else { match *e { - TokenTree::Token(_, token::Ident(ident)) => res_str.push_str(&ident.name.as_str()), + TokenTree::Token(_, token::Ident(ident, _)) => + res_str.push_str(&ident.name.as_str()), _ => { cx.span_err(sp, "concat_idents! requires ident args."); return DummyResult::expr(sp); diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 22e78e9b426b..80557078d546 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -54,7 +54,9 @@ impl MultiItemModifier for ProcMacroDerive { let item = match item { Annotatable::Item(item) => item, Annotatable::ImplItem(_) | - Annotatable::TraitItem(_) => { + Annotatable::TraitItem(_) | + Annotatable::Stmt(_) | + Annotatable::Expr(_) => { ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 82fc09fca69a..7b23de582a79 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -70,7 +70,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P TraitDef<'a> { id: ast::DUMMY_NODE_ID, span: self.span, ident, - vis: respan(self.span.empty(), ast::VisibilityKind::Inherited), + vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, attrs: Vec::new(), generics: Generics::default(), @@ -962,7 +962,7 @@ impl<'a> MethodDef<'a> { let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); let method_ident = cx.ident_of(self.name); - let fn_decl = cx.fn_decl(args, ret_type); + let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); let unsafety = if self.is_unsafe { @@ -977,7 +977,7 @@ impl<'a> MethodDef<'a> { attrs: self.attributes.clone(), generics: fn_generics, span: trait_.span, - vis: respan(trait_.span.empty(), ast::VisibilityKind::Inherited), + vis: respan(trait_.span.shrink_to_lo(), ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, node: ast::ImplItemKind::Method(ast::MethodSig { diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index fcad065be52b..ba6d25f7a60a 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -17,7 +17,7 @@ use syntax::ast::{self, Ident}; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; -use syntax::symbol::Symbol; +use syntax::symbol::{keywords, Symbol}; use syntax_pos::Span; use syntax::tokenstream; @@ -35,14 +35,14 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark)); let e = match env::var(&*var.as_str()) { Err(..) => { + let lt = cx.lifetime(sp, keywords::StaticLifetime.ident()); cx.expr_path(cx.path_all(sp, true, cx.std_path(&["option", "Option", "None"]), Vec::new(), vec![cx.ty_rptr(sp, cx.ty_ident(sp, Ident::from_str("str")), - Some(cx.lifetime(sp, - Ident::from_str("'static"))), + Some(lt), ast::Mutability::Immutable)], Vec::new())) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 8fd95aa1ca86..d9c68e3167bd 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -149,7 +149,7 @@ fn parse_args(ecx: &mut ExtCtxt, if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) { named = true; let ident = match p.token { - token::Ident(i) => { + token::Ident(i, _) => { p.bump(); i } diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 0476d7d4fcc1..e95c6f2e1243 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -272,6 +272,11 @@ pub mod printf { self.s = tail; Some(sub) } + + fn size_hint(&self) -> (usize, Option) { + // Substitutions are at least 2 characters long. + (0, Some(self.s.len() / 2)) + } } enum State { @@ -782,6 +787,10 @@ pub mod shell { None => None, } } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.s.len())) + } } /// Parse the next substitution from the input string. diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 9605f6b5c5a9..f01a0aacb0a7 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -60,7 +60,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt, asm, ctxt: cx.backtrace(), })), - vis: respan(sp.empty(), ast::VisibilityKind::Inherited), + vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), span: sp, tokens: None, }))) diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 772dec72ab98..249a64b353f5 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -17,6 +17,7 @@ #![feature(proc_macro_internals)] #![feature(decl_macro)] +#![feature(str_escape)] extern crate fmt_macros; #[macro_use] @@ -26,6 +27,7 @@ extern crate proc_macro; extern crate rustc_data_structures; extern crate rustc_errors as errors; +mod assert; mod asm; mod cfg; mod compile_error; @@ -67,6 +69,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, def_info: None, allow_internal_unstable: false, allow_internal_unsafe: false, + unstable_feature: None, }); )* } } @@ -111,6 +114,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, log_syntax: log_syntax::expand_syntax_ext, trace_macros: trace_macros::expand_trace_macros, compile_error: compile_error::expand_compile_error, + assert: assert::expand_assert, } // format_args uses `unstable` things internally. @@ -120,6 +124,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, def_info: None, allow_internal_unstable: true, allow_internal_unsafe: false, + unstable_feature: None }); for (name, ext) in user_exts { diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index aad2155157d8..b9637b1855ef 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -11,4 +11,5 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } rustc_data_structures = { path = "../librustc_data_structures" } +scoped-tls = { version = "0.1.1", features = ["nightly"] } unicode-width = "0.1.4" diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index b7fba9fe8dfb..aba71bd04683 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -15,11 +15,11 @@ //! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216. //! DOI=10.1017/S0956796812000093 +use GLOBALS; use Span; use symbol::{Ident, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; -use std::cell::RefCell; use std::collections::HashMap; use std::fmt; @@ -119,7 +119,7 @@ impl Mark { } } -struct HygieneData { +pub struct HygieneData { marks: Vec, syntax_contexts: Vec, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, @@ -127,7 +127,7 @@ struct HygieneData { } impl HygieneData { - fn new() -> Self { + pub fn new() -> Self { HygieneData { marks: vec![MarkData { parent: Mark::root(), @@ -145,10 +145,7 @@ impl HygieneData { } fn with T>(f: F) -> T { - thread_local! { - static HYGIENE_DATA: RefCell = RefCell::new(HygieneData::new()); - } - HYGIENE_DATA.with(|data| f(&mut *data.borrow_mut())) + GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut())) } } @@ -433,7 +430,6 @@ pub enum ExpnFormat { /// The kind of compiler desugaring. #[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum CompilerDesugaringKind { - BackArrow, DotFill, QuestionMark, } @@ -442,7 +438,6 @@ impl CompilerDesugaringKind { pub fn as_symbol(&self) -> Symbol { use CompilerDesugaringKind::*; let s = match *self { - BackArrow => "<-", DotFill => "...", QuestionMark => "?", }; diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index ed9eb5d5c926..eb345200f413 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -21,13 +21,13 @@ #![feature(const_fn)] #![feature(custom_attribute)] -#![feature(i128_type)] +#![cfg_attr(stage0, feature(i128_type))] #![feature(optin_builtin_traits)] #![allow(unused_attributes)] #![feature(specialization)] use std::borrow::Cow; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::cmp::{self, Ordering}; use std::fmt; use std::hash::{Hasher, Hash}; @@ -35,10 +35,13 @@ use std::ops::{Add, Sub}; use std::path::PathBuf; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Lock}; extern crate rustc_data_structures; +#[macro_use] +extern crate scoped_tls; + use serialize::{Encodable, Decodable, Encoder, Decoder}; extern crate serialize; @@ -54,6 +57,24 @@ pub use span_encoding::{Span, DUMMY_SP}; pub mod symbol; +pub struct Globals { + symbol_interner: Lock, + span_interner: Lock, + hygiene_data: Lock, +} + +impl Globals { + pub fn new() -> Globals { + Globals { + symbol_interner: Lock::new(symbol::Interner::fresh()), + span_interner: Lock::new(span_encoding::SpanInterner::default()), + hygiene_data: Lock::new(hygiene::HygieneData::new()), + } + } +} + +scoped_thread_local!(pub static GLOBALS: Globals); + /// Differentiates between real files and common virtual files #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)] pub enum FileName { @@ -163,8 +184,12 @@ impl SpanData { } } -// The interner in thread-local, so `Span` shouldn't move between threads. +// The interner is pointed to by a thread local value which is only set on the main thread +// with parallelization is disabled. So we don't allow Span to transfer between threads +// to avoid panics and other errors, even though it would be memory safe to do so. +#[cfg(not(parallel_queries))] impl !Send for Span {} +#[cfg(not(parallel_queries))] impl !Sync for Span {} impl PartialOrd for Span { @@ -218,8 +243,15 @@ impl Span { /// Returns a new span representing an empty span at the beginning of this span #[inline] - pub fn empty(self) -> Span { - self.with_hi(self.lo()) + pub fn shrink_to_lo(self) -> Span { + let span = self.data(); + span.with_hi(span.lo) + } + /// Returns a new span representing an empty span at the end of this span + #[inline] + pub fn shrink_to_hi(self) -> Span { + let span = self.data(); + span.with_lo(span.hi) } /// Returns `self` if `self` is not the dummy span, and `other` otherwise. @@ -678,17 +710,17 @@ pub struct FileMap { pub src_hash: u128, /// The external source code (used for external crates, which will have a `None` /// value as `self.src`. - pub external_src: RefCell, + pub external_src: Lock, /// The start position of this source in the CodeMap pub start_pos: BytePos, /// The end position of this source in the CodeMap pub end_pos: BytePos, /// Locations of lines beginnings in the source code - pub lines: RefCell>, + pub lines: Lock>, /// Locations of multi-byte characters in the source code - pub multibyte_chars: RefCell>, + pub multibyte_chars: Lock>, /// Width of characters that are not narrow in the source code - pub non_narrow_chars: RefCell>, + pub non_narrow_chars: Lock>, /// A hash of the filename, used for speeding up the incr. comp. hashing. pub name_hash: u128, } @@ -818,10 +850,10 @@ impl Decodable for FileMap { end_pos, src: None, src_hash, - external_src: RefCell::new(ExternalSource::AbsentOk), - lines: RefCell::new(lines), - multibyte_chars: RefCell::new(multibyte_chars), - non_narrow_chars: RefCell::new(non_narrow_chars), + external_src: Lock::new(ExternalSource::AbsentOk), + lines: Lock::new(lines), + multibyte_chars: Lock::new(multibyte_chars), + non_narrow_chars: Lock::new(non_narrow_chars), name_hash, }) }) @@ -861,12 +893,12 @@ impl FileMap { crate_of_origin: 0, src: Some(Lrc::new(src)), src_hash, - external_src: RefCell::new(ExternalSource::Unneeded), + external_src: Lock::new(ExternalSource::Unneeded), start_pos, end_pos: Pos::from_usize(end_pos), - lines: RefCell::new(Vec::new()), - multibyte_chars: RefCell::new(Vec::new()), - non_narrow_chars: RefCell::new(Vec::new()), + lines: Lock::new(Vec::new()), + multibyte_chars: Lock::new(Vec::new()), + non_narrow_chars: Lock::new(Vec::new()), name_hash, } } @@ -898,19 +930,24 @@ impl FileMap { if *self.external_src.borrow() == ExternalSource::AbsentOk { let src = get_src(); let mut external_src = self.external_src.borrow_mut(); - if let Some(src) = src { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); + // Check that no-one else have provided the source while we were getting it + if *external_src == ExternalSource::AbsentOk { + if let Some(src) = src { + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); - if hasher.finish() == self.src_hash { - *external_src = ExternalSource::Present(src); - return true; + if hasher.finish() == self.src_hash { + *external_src = ExternalSource::Present(src); + return true; + } + } else { + *external_src = ExternalSource::AbsentErr; } - } else { - *external_src = ExternalSource::AbsentErr; - } - false + false + } else { + self.src.is_some() || external_src.get_source().is_some() + } } else { self.src.is_some() || self.external_src.borrow().get_source().is_some() } @@ -930,14 +967,16 @@ impl FileMap { } } - let lines = self.lines.borrow(); - let line = if let Some(line) = lines.get(line_number) { - line - } else { - return None; + let begin = { + let lines = self.lines.borrow(); + let line = if let Some(line) = lines.get(line_number) { + line + } else { + return None; + }; + let begin: BytePos = *line - self.start_pos; + begin.to_usize() }; - let begin: BytePos = *line - self.start_pos; - let begin = begin.to_usize(); if let Some(ref src) = self.src { Some(Cow::from(get_until_newline(src, begin))) diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs index bf9a832519ad..b55fe4bcb267 100644 --- a/src/libsyntax_pos/span_encoding.rs +++ b/src/libsyntax_pos/span_encoding.rs @@ -14,11 +14,11 @@ // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 +use GLOBALS; use {BytePos, SpanData}; use hygiene::SyntaxContext; use rustc_data_structures::fx::FxHashMap; -use std::cell::RefCell; use std::hash::{Hash, Hasher}; /// A compressed span. @@ -133,7 +133,7 @@ fn decode(span: Span) -> SpanData { } #[derive(Default)] -struct SpanInterner { +pub struct SpanInterner { spans: FxHashMap, span_data: Vec, } @@ -156,11 +156,8 @@ impl SpanInterner { } } -// If an interner exists in TLS, return it. Otherwise, prepare a fresh one. +// If an interner exists, return it. Otherwise, prepare a fresh one. #[inline] fn with_span_interner T>(f: F) -> T { - thread_local!(static INTERNER: RefCell = { - RefCell::new(SpanInterner::default()) - }); - INTERNER.with(|interner| f(&mut *interner.borrow_mut())) + GLOBALS.with(|globals| f(&mut *globals.span_interner.lock())) } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index aafdd696b747..098eafef2585 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -13,9 +13,9 @@ //! type, and vice versa. use hygiene::SyntaxContext; +use GLOBALS; use serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::cell::RefCell; use std::collections::HashMap; use std::fmt; @@ -83,8 +83,12 @@ impl Decodable for Ident { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Symbol(u32); -// The interner in thread-local, so `Symbol` shouldn't move between threads. +// The interner is pointed to by a thread local value which is only set on the main thread +// with parallelization is disabled. So we don't allow Symbol to transfer between threads +// to avoid panics and other errors, even though it would be memory safe to do so. +#[cfg(not(parallel_queries))] impl !Send for Symbol { } +#[cfg(not(parallel_queries))] impl !Sync for Symbol { } impl Symbol { @@ -247,7 +251,7 @@ macro_rules! declare_keywords {( } impl Interner { - fn fresh() -> Self { + pub fn fresh() -> Self { Interner::prefill(&[$($string,)*]) } } @@ -261,81 +265,83 @@ macro_rules! declare_keywords {( declare_keywords! { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. - (0, Invalid, "") - (1, CrateRoot, "{{root}}") - (2, DollarCrate, "$crate") + (0, Invalid, "") + (1, CrateRoot, "{{root}}") + (2, DollarCrate, "$crate") + (3, Underscore, "_") // Keywords used in the language. - (3, As, "as") - (4, Box, "box") - (5, Break, "break") - (6, Const, "const") - (7, Continue, "continue") - (8, Crate, "crate") - (9, Else, "else") - (10, Enum, "enum") - (11, Extern, "extern") - (12, False, "false") - (13, Fn, "fn") - (14, For, "for") - (15, If, "if") - (16, Impl, "impl") - (17, In, "in") - (18, Let, "let") - (19, Loop, "loop") - (20, Match, "match") - (21, Mod, "mod") - (22, Move, "move") - (23, Mut, "mut") - (24, Pub, "pub") - (25, Ref, "ref") - (26, Return, "return") - (27, SelfValue, "self") - (28, SelfType, "Self") - (29, Static, "static") - (30, Struct, "struct") - (31, Super, "super") - (32, Trait, "trait") - (33, True, "true") - (34, Type, "type") - (35, Unsafe, "unsafe") - (36, Use, "use") - (37, Where, "where") - (38, While, "while") + (4, As, "as") + (5, Box, "box") + (6, Break, "break") + (7, Const, "const") + (8, Continue, "continue") + (9, Crate, "crate") + (10, Else, "else") + (11, Enum, "enum") + (12, Extern, "extern") + (13, False, "false") + (14, Fn, "fn") + (15, For, "for") + (16, If, "if") + (17, Impl, "impl") + (18, In, "in") + (19, Let, "let") + (20, Loop, "loop") + (21, Match, "match") + (22, Mod, "mod") + (23, Move, "move") + (24, Mut, "mut") + (25, Pub, "pub") + (26, Ref, "ref") + (27, Return, "return") + (28, SelfValue, "self") + (29, SelfType, "Self") + (30, Static, "static") + (31, Struct, "struct") + (32, Super, "super") + (33, Trait, "trait") + (34, True, "true") + (35, Type, "type") + (36, Unsafe, "unsafe") + (37, Use, "use") + (38, Where, "where") + (39, While, "while") // Keywords reserved for future use. - (39, Abstract, "abstract") - (40, Alignof, "alignof") - (41, Become, "become") - (42, Do, "do") - (43, Final, "final") - (44, Macro, "macro") - (45, Offsetof, "offsetof") - (46, Override, "override") - (47, Priv, "priv") - (48, Proc, "proc") - (49, Pure, "pure") - (50, Sizeof, "sizeof") - (51, Typeof, "typeof") - (52, Unsized, "unsized") - (53, Virtual, "virtual") - (54, Yield, "yield") + (40, Abstract, "abstract") + (41, Alignof, "alignof") + (42, Become, "become") + (43, Do, "do") + (44, Final, "final") + (45, Macro, "macro") + (46, Offsetof, "offsetof") + (47, Override, "override") + (48, Priv, "priv") + (49, Proc, "proc") + (50, Pure, "pure") + (51, Sizeof, "sizeof") + (52, Typeof, "typeof") + (53, Unsized, "unsized") + (54, Virtual, "virtual") + (55, Yield, "yield") + + // Special lifetime names + (56, UnderscoreLifetime, "'_") + (57, StaticLifetime, "'static") // Weak keywords, have special meaning only in specific contexts. - (55, Auto, "auto") - (56, Catch, "catch") - (57, Default, "default") - (58, Dyn, "dyn") - (59, StaticLifetime, "'static") - (60, Union, "union") + (58, Auto, "auto") + (59, Catch, "catch") + (60, Default, "default") + (61, Dyn, "dyn") + (62, Union, "union") } -// If an interner exists in TLS, return it. Otherwise, prepare a fresh one. +// If an interner exists, return it. Otherwise, prepare a fresh one. +#[inline] fn with_interner T>(f: F) -> T { - thread_local!(static INTERNER: RefCell = { - RefCell::new(Interner::fresh()) - }); - INTERNER.with(|interner| f(&mut *interner.borrow_mut())) + GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock())) } /// Represents a string stored in the thread-local interner. Because the @@ -422,6 +428,7 @@ impl Encodable for InternedString { #[cfg(test)] mod tests { use super::*; + use Globals; #[test] fn interner_tests() { @@ -444,7 +451,9 @@ mod tests { #[test] fn without_first_quote_test() { - let i = Ident::from_str("'break"); - assert_eq!(i.without_first_quote().name, keywords::Break.name()); + GLOBALS.set(&Globals::new(), || { + let i = Ident::from_str("'break"); + assert_eq!(i.without_first_quote().name, keywords::Break.name()); + }); } } diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index d323d50f702b..89235d897bde 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -36,17 +36,12 @@ impl JsonFormatter { if let Some(extras) = extra { self.write_message(&*format!( r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#, - ty, - name, - evt, - extras + ty, name, evt, extras )) } else { self.write_message(&*format!( r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#, - ty, - name, - evt + ty, name, evt )) } } @@ -89,14 +84,12 @@ impl OutputFormatter for JsonFormatter { self.write_event("test", desc.name.as_slice(), "failed", extra_data) } - TrFailedMsg(ref m) => { - self.write_event( - "test", - desc.name.as_slice(), - "failed", - Some(format!(r#""message": "{}""#, EscapedString(m))), - ) - } + TrFailedMsg(ref m) => self.write_event( + "test", + desc.name.as_slice(), + "failed", + Some(format!(r#""message": "{}""#, EscapedString(m))), + ), TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", None), @@ -116,13 +109,10 @@ impl OutputFormatter for JsonFormatter { let line = format!( "{{ \"type\": \"bench\", \ - \"name\": \"{}\", \ - \"median\": {}, \ - \"deviation\": {}{} }}", - desc.name, - median, - deviation, - mbps + \"name\": \"{}\", \ + \"median\": {}, \ + \"deviation\": {}{} }}", + desc.name, median, deviation, mbps ); self.write_message(&*line) @@ -138,16 +128,15 @@ impl OutputFormatter for JsonFormatter { } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { - self.write_message(&*format!( "{{ \"type\": \"suite\", \ - \"event\": \"{}\", \ - \"passed\": {}, \ - \"failed\": {}, \ - \"allowed_fail\": {}, \ - \"ignored\": {}, \ - \"measured\": {}, \ - \"filtered_out\": \"{}\" }}", + \"event\": \"{}\", \ + \"passed\": {}, \ + \"failed\": {}, \ + \"allowed_fail\": {}, \ + \"ignored\": {}, \ + \"measured\": {}, \ + \"filtered_out\": \"{}\" }}", if state.failed == 0 { "ok" } else { "failed" }, state.passed, state.failed + state.allowed_fail, diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index f2064deefce6..8e5fa00b5f27 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -196,8 +196,7 @@ impl OutputFormatter for PrettyFormatter { self.write_plain(&format!( "test {} has been running for over {} seconds\n", - desc.name, - TEST_WARN_TIMEOUT_S + desc.name, TEST_WARN_TIMEOUT_S )) } @@ -232,11 +231,7 @@ impl OutputFormatter for PrettyFormatter { } else { format!( ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", - state.passed, - state.failed, - state.ignored, - state.measured, - state.filtered_out + state.passed, state.failed, state.ignored, state.measured, state.filtered_out ) }; diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 88689485144c..85286027d692 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -195,8 +195,7 @@ impl OutputFormatter for TerseFormatter { fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { self.write_plain(&format!( "test {} has been running for over {} seconds\n", - desc.name, - TEST_WARN_TIMEOUT_S + desc.name, TEST_WARN_TIMEOUT_S )) } @@ -231,11 +230,7 @@ impl OutputFormatter for TerseFormatter { } else { format!( ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n", - state.passed, - state.failed, - state.ignored, - state.measured, - state.filtered_out + state.passed, state.failed, state.ignored, state.measured, state.filtered_out ) }; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 82077bc4cd48..b8be1aeff174 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -30,10 +30,8 @@ #![unstable(feature = "test", issue = "27812")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - test(attr(deny(warnings))))] + html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![deny(warnings)] - #![feature(asm)] #![feature(fnbox)] #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))] @@ -43,10 +41,10 @@ #![feature(termination_trait_lib)] extern crate getopts; -extern crate term; #[cfg(any(unix, target_os = "cloudabi"))] extern crate libc; extern crate panic_unwind; +extern crate term; pub use self::TestFn::*; pub use self::ColorConfig::*; @@ -72,7 +70,7 @@ use std::process::Termination; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; use std::borrow::Cow; use std::process; @@ -81,16 +79,16 @@ const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in qu // to be used by rustc to compile tests in libtest pub mod test { - pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed, - TrFailedMsg, TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName, - DynTestName, DynTestFn, assert_test_result, run_test, test_main, test_main_static, - filter_tests, parse_opts, StaticBenchFn, ShouldPanic, Options}; + pub use {assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static, + Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, ShouldPanic, + StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, + TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}; } pub mod stats; mod formatters; -use formatters::{OutputFormatter, PrettyFormatter, TerseFormatter, JsonFormatter}; +use formatters::{JsonFormatter, OutputFormatter, PrettyFormatter, TerseFormatter}; // The name of a test. By convention this follows the rules for rust // paths; i.e. it should be a series of identifiers separated by double @@ -255,7 +253,9 @@ pub struct Options { impl Options { pub fn new() -> Options { - Options { display_output: false } + Options { + display_output: false, + } } pub fn display_output(mut self, display_output: bool) -> Options { @@ -272,7 +272,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Options) { Some(Err(msg)) => { eprintln!("error: {}", msg); process::exit(101); - }, + } None => return, }; @@ -289,7 +289,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Options) { Err(e) => { eprintln!("error: io error when listing tests: {:?}", e); process::exit(101); - }, + } } } } @@ -306,18 +306,14 @@ pub fn test_main_static(tests: &[TestDescAndFn]) { let owned_tests = tests .iter() .map(|t| match t.testfn { - StaticTestFn(f) => { - TestDescAndFn { - testfn: StaticTestFn(f), - desc: t.desc.clone(), - } - } - StaticBenchFn(f) => { - TestDescAndFn { - testfn: StaticBenchFn(f), - desc: t.desc.clone(), - } - } + StaticTestFn(f) => TestDescAndFn { + testfn: StaticTestFn(f), + desc: t.desc.clone(), + }, + StaticBenchFn(f) => TestDescAndFn { + testfn: StaticBenchFn(f), + desc: t.desc.clone(), + }, _ => panic!("non-static tests passed to test::test_main_static"), }) .collect(); @@ -397,34 +393,34 @@ fn optgroups() -> getopts::Options { "", "logfile", "Write logs to the specified file instead \ - of stdout", + of stdout", "PATH", ) .optflag( "", "nocapture", "don't capture stdout/stderr of each \ - task, allow printing directly", + task, allow printing directly", ) .optopt( "", "test-threads", "Number of threads used for running tests \ - in parallel", + in parallel", "n_threads", ) .optmulti( "", "skip", "Skip tests whose names contain FILTER (this flag can \ - be used multiple times)", + be used multiple times)", "FILTER", ) .optflag( "q", "quiet", "Display one character per test instead of one line. \ - Alias to --format=terse", + Alias to --format=terse", ) .optflag( "", @@ -516,8 +512,7 @@ pub fn parse_opts(args: &[String]) -> Option { if let Some(opt) = matches.opt_str("Z") { if !is_nightly() { return Some(Err( - "the option `Z` is only accepted on the nightly compiler" - .into(), + "the option `Z` is only accepted on the nightly compiler".into(), )); } @@ -562,19 +557,17 @@ pub fn parse_opts(args: &[String]) -> Option { } let test_threads = match matches.opt_str("test-threads") { - Some(n_str) => { - match n_str.parse::() { - Ok(0) => return Some(Err(format!("argument for --test-threads must not be 0"))), - Ok(n) => Some(n), - Err(e) => { - return Some(Err(format!( - "argument for --test-threads must be a number > 0 \ - (error: {})", - e - ))) - } + Some(n_str) => match n_str.parse::() { + Ok(0) => return Some(Err(format!("argument for --test-threads must not be 0"))), + Ok(n) => Some(n), + Err(e) => { + return Some(Err(format!( + "argument for --test-threads must be a number > 0 \ + (error: {})", + e + ))) } - } + }, None => None, }; @@ -586,7 +579,7 @@ pub fn parse_opts(args: &[String]) -> Option { Some(v) => { return Some(Err(format!( "argument for --color must be auto, always, or never (was \ - {})", + {})", v ))) } @@ -599,8 +592,7 @@ pub fn parse_opts(args: &[String]) -> Option { Some("json") => { if !allow_unstable { return Some(Err( - "The \"json\" format is only accepted on the nightly compiler" - .into(), + "The \"json\" format is only accepted on the nightly compiler".into(), )); } OutputFormat::Json @@ -609,7 +601,7 @@ pub fn parse_opts(args: &[String]) -> Option { Some(v) => { return Some(Err(format!( "argument for --format must be pretty, terse, or json (was \ - {})", + {})", v ))) } @@ -811,8 +803,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res ntest += 1; "test" } - StaticBenchFn(..) | - DynBenchFn(..) => { + StaticBenchFn(..) | DynBenchFn(..) => { nbench += 1; "benchmark" } @@ -834,7 +825,8 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res writeln!(output, "")?; } - writeln!(output, + writeln!( + output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark") @@ -851,7 +843,6 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu st: &mut ConsoleTestState, out: &mut OutputFormatter, ) -> io::Result<()> { - match (*event).clone() { TeFiltered(ref filtered_tests) => { st.total = filtered_tests.len(); @@ -989,8 +980,7 @@ fn use_color(opts: &TestOpts) -> bool { } } -#[cfg(any(target_os = "cloudabi", - target_os = "redox", +#[cfg(any(target_os = "cloudabi", target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten"))))] fn stdout_isatty() -> bool { // FIXME: Implement isatty on Redox @@ -1089,10 +1079,12 @@ where let now = Instant::now(); let timed_out = running_tests .iter() - .filter_map(|(desc, timeout)| if &now >= timeout { - Some(desc.clone()) - } else { - None + .filter_map(|(desc, timeout)| { + if &now >= timeout { + Some(desc.clone()) + } else { + None + } }) .collect(); for test in &timed_out { @@ -1174,12 +1166,10 @@ fn get_concurrency() -> usize { let opt_n: Option = s.parse().ok(); match opt_n { Some(n) if n > 0 => n, - _ => { - panic!( - "RUST_TEST_THREADS is `{}`, should be a positive integer.", - s - ) - } + _ => panic!( + "RUST_TEST_THREADS is `{}`, should be a positive integer.", + s + ), } } Err(..) => num_cpus(), @@ -1223,20 +1213,15 @@ fn get_concurrency() -> usize { 1 } - #[cfg(any(target_os = "android", - target_os = "cloudabi", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "solaris"))] + #[cfg(any(target_os = "android", target_os = "cloudabi", target_os = "emscripten", + target_os = "fuchsia", target_os = "ios", target_os = "linux", + target_os = "macos", target_os = "solaris"))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } } #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "bitrig", - target_os = "netbsd"))] + target_os = "netbsd"))] fn num_cpus() -> usize { use std::ptr; @@ -1294,6 +1279,12 @@ fn get_concurrency() -> usize { // FIXME: implement 1 } + + #[cfg(target_os = "l4re")] + fn num_cpus() -> usize { + // FIXME: implement + 1 + } } pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec { @@ -1302,26 +1293,28 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec filtered, - Some(ref filter) => { - filtered - .into_iter() - .filter(|test| if opts.filter_exact { + Some(ref filter) => filtered + .into_iter() + .filter(|test| { + if opts.filter_exact { test.desc.name.as_slice() == &filter[..] } else { test.desc.name.as_slice().contains(&filter[..]) - }) - .collect() - } + } + }) + .collect(), }; // Skip tests that match any of the skip filters filtered = filtered .into_iter() .filter(|t| { - !opts.skip.iter().any(|sf| if opts.filter_exact { - t.desc.name.as_slice() == &sf[..] - } else { - t.desc.name.as_slice().contains(&sf[..]) + !opts.skip.iter().any(|sf| { + if opts.filter_exact { + t.desc.name.as_slice() == &sf[..] + } else { + t.desc.name.as_slice().contains(&sf[..]) + } }) }) .collect(); @@ -1348,31 +1341,23 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec) -> Vec { // convert benchmarks to tests, if we're not benchmarking them - tests.into_iter().map(|x| { - let testfn = match x.testfn { - DynBenchFn(bench) => { - DynTestFn(Box::new(move || { - bench::run_once(|b| { - __rust_begin_short_backtrace(|| bench.run(b)) - }) - })) - } - StaticBenchFn(benchfn) => { - DynTestFn(Box::new(move || { - bench::run_once(|b| { - __rust_begin_short_backtrace(|| benchfn(b)) - }) - })) - } + tests + .into_iter() + .map(|x| { + let testfn = match x.testfn { + DynBenchFn(bench) => DynTestFn(Box::new(move || { + bench::run_once(|b| __rust_begin_short_backtrace(|| bench.run(b))) + })), + StaticBenchFn(benchfn) => DynTestFn(Box::new(move || { + bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b))) + })), f => f, }; TestDescAndFn { @@ -1389,22 +1374,22 @@ pub fn run_test( test: TestDescAndFn, monitor_ch: Sender, ) { - let TestDescAndFn { desc, testfn } = test; - let ignore_because_panic_abort = cfg!(target_arch = "wasm32") && - !cfg!(target_os = "emscripten") && - desc.should_panic != ShouldPanic::No; + let ignore_because_panic_abort = cfg!(target_arch = "wasm32") && !cfg!(target_os = "emscripten") + && desc.should_panic != ShouldPanic::No; if force_ignore || desc.ignore || ignore_because_panic_abort { monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); return; } - fn run_test_inner(desc: TestDesc, - monitor_ch: Sender, - nocapture: bool, - testfn: Box) { + fn run_test_inner( + desc: TestDesc, + monitor_ch: Sender, + nocapture: bool, + testfn: Box, + ) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); let data2 = data.clone(); @@ -1434,7 +1419,6 @@ pub fn run_test( .unwrap(); }; - // If the platform is single-threaded we're just going to run // the test synchronously, regardless of the concurrency // level. @@ -1449,27 +1433,25 @@ pub fn run_test( match testfn { DynBenchFn(bencher) => { - ::bench::benchmark(desc, - monitor_ch, - opts.nocapture, - |harness| bencher.run(harness)); + ::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + bencher.run(harness) + }); } StaticBenchFn(benchfn) => { - ::bench::benchmark(desc, - monitor_ch, - opts.nocapture, - |harness| (benchfn.clone())(harness)); + ::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + (benchfn.clone())(harness) + }); } DynTestFn(f) => { - let cb = move || { - __rust_begin_short_backtrace(f) - }; + let cb = move || __rust_begin_short_backtrace(f); run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb)) } - StaticTestFn(f) => { - run_test_inner(desc, monitor_ch, opts.nocapture, - Box::new(move || __rust_begin_short_backtrace(f))) - } + StaticTestFn(f) => run_test_inner( + desc, + monitor_ch, + opts.nocapture, + Box::new(move || __rust_begin_short_backtrace(f)), + ), } } @@ -1481,8 +1463,7 @@ fn __rust_begin_short_backtrace(f: F) { fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { match (&desc.should_panic, task_result) { - (&ShouldPanic::No, Ok(())) | - (&ShouldPanic::Yes, Err(_)) => TrOk, + (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { if err.downcast_ref::() .map(|e| &**e) @@ -1539,7 +1520,6 @@ impl MetricMap { } } - // Benchmarking /// A function that is opaque to the optimizer, to allow benchmarks to @@ -1560,7 +1540,6 @@ pub fn black_box(dummy: T) -> T { dummy } - impl Bencher { /// Callback for benchmark functions to run in their body. pub fn iter(&mut self, mut inner: F) @@ -1599,7 +1578,6 @@ where return ns_from_dur(start.elapsed()); } - pub fn iter(inner: &mut F) -> stats::Summary where F: FnMut() -> T, @@ -1643,8 +1621,8 @@ where // If we've run for 100ms and seem to have converged to a // stable median. - if loop_run > Duration::from_millis(100) && summ.median_abs_dev_pct < 1.0 && - summ.median - summ5.median < summ5.median_abs_dev + if loop_run > Duration::from_millis(100) && summ.median_abs_dev_pct < 1.0 + && summ.median - summ5.median < summ5.median_abs_dev { return summ5; } @@ -1674,7 +1652,7 @@ pub mod bench { use std::io; use std::sync::{Arc, Mutex}; use stats; - use super::{Bencher, BenchSamples, BenchMode, Sink, MonitorMsg, TestDesc, Sender, TestResult}; + use super::{BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult}; pub fn benchmark(desc: TestDesc, monitor_ch: Sender, nocapture: bool, f: F) where @@ -1705,7 +1683,8 @@ pub mod bench { io::set_panic(panicio); }; - let test_result = match result { //bs.bench(f) { + let test_result = match result { + //bs.bench(f) { Ok(Some(ns_iter_summ)) => { let ns_iter = cmp::max(ns_iter_summ.median as u64, 1); let mb_s = bs.bytes * 1000 / ns_iter; @@ -1726,9 +1705,7 @@ pub mod bench { }; TestResult::TrBench(bs) } - Err(_) => { - TestResult::TrFailed - } + Err(_) => TestResult::TrFailed, }; let stdout = data.lock().unwrap().to_vec(); @@ -1750,9 +1727,9 @@ pub mod bench { #[cfg(test)] mod tests { - use test::{TrFailed, TrFailedMsg, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc, - TestDescAndFn, TestOpts, run_test, MetricMap, StaticTestName, DynTestName, - DynTestFn, ShouldPanic}; + use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, ShouldPanic, + StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, + TrIgnored, TrOk}; use std::sync::mpsc::channel; use bench; use Bencher; @@ -1898,25 +1875,26 @@ mod tests { opts.run_tests = true; opts.run_ignored = true; - let tests = - vec![TestDescAndFn { - desc: TestDesc { - name: StaticTestName("1"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("2"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }]; + let tests = vec![ + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("1"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("2"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + ]; let filtered = filter_tests(&opts, tests); assert_eq!(filtered.len(), 1); @@ -1929,17 +1907,16 @@ mod tests { fn tests() -> Vec { vec!["base", "base::test", "base::test1", "base::test2"] .into_iter() - .map(|name| { - TestDescAndFn { - desc: TestDesc { - name: StaticTestName(name), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})) - } - }).collect() + .map(|name| TestDescAndFn { + desc: TestDesc { + name: StaticTestName(name), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }) + .collect() } let substr = filter_tests( @@ -2121,10 +2098,7 @@ mod tests { allow_fail: false, }; - ::bench::benchmark(desc, - tx, - true, - f); + ::bench::benchmark(desc, tx, true, f); rx.recv().unwrap(); } @@ -2143,10 +2117,7 @@ mod tests { allow_fail: false, }; - ::bench::benchmark(desc, - tx, - true, - f); + ::bench::benchmark(desc, tx, true, f); rx.recv().unwrap(); } } diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index e22fdf77fc17..ddb5dcf2a1cd 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -279,7 +279,6 @@ impl Stats for [f64] { } } - // Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using // linear interpolation. If samples are not sorted, return nonsensical value. fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { @@ -304,7 +303,6 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { lo + (hi - lo) * d } - /// Winsorize a set of samples, replacing values above the `100-pct` percentile /// and below the `pct` percentile with those percentiles themselves. This is a /// way of minimizing the effect of outliers, at the cost of biasing the sample. @@ -338,15 +336,18 @@ mod tests { use std::io; macro_rules! assert_approx_eq { - ($a:expr, $b:expr) => ({ + ($a: expr, $b: expr) => {{ let (a, b) = (&$a, &$b); - assert!((*a - *b).abs() < 1.0e-6, - "{} is not approximately equal to {}", *a, *b); - }) + assert!( + (*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", + *a, + *b + ); + }}; } fn check(samples: &[f64], summ: &Summary) { - let summ2 = Summary::new(samples); let mut w = io::sink(); @@ -911,14 +912,18 @@ mod bench { #[bench] pub fn sum_three_items(b: &mut Bencher) { - b.iter(|| { [1e20f64, 1.5f64, -1e20f64].sum(); }) + b.iter(|| { + [1e20f64, 1.5f64, -1e20f64].sum(); + }) } #[bench] pub fn sum_many_f64(b: &mut Bencher) { let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60]; let v = (0..500).map(|i| nums[i % 5]).collect::>(); - b.iter(|| { v.sum(); }) + b.iter(|| { + v.sum(); + }) } #[bench] diff --git a/src/llvm b/src/llvm index 0903c72cbbc3..6ceaaa4b0176 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 0903c72cbbc3dafcb5c88820e4a8a98c3a764cf3 +Subproject commit 6ceaaa4b0176a200e4bbd347d6a991ab6c776ede diff --git a/src/rustc/compiler_builtins_shim/Cargo.toml b/src/rustc/compiler_builtins_shim/Cargo.toml index 608e5f5f36d0..7d8423ca84eb 100644 --- a/src/rustc/compiler_builtins_shim/Cargo.toml +++ b/src/rustc/compiler_builtins_shim/Cargo.toml @@ -35,5 +35,6 @@ cc = "1.0.1" [features] c = [] default = ["c", "rustbuild", "compiler-builtins"] +mem = [] rustbuild = [] compiler-builtins = [] diff --git a/src/rustc/rustc.rs b/src/rustc/rustc.rs index bfd01146d2c4..9fa33f911a16 100644 --- a/src/rustc/rustc.rs +++ b/src/rustc/rustc.rs @@ -9,6 +9,16 @@ // except according to those terms. #![feature(rustc_private)] +#![feature(link_args)] + +// Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread +// for the rationale. +#[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")] +// We only build for msvc and gnu now, but we use a exhaustive condition here +// so we can expect either the stack size to be set or the build fails. +#[cfg_attr(all(windows, not(target_env = "msvc")), link_args = "-Wl,--stack,16777216")] +// Also, don't forget to set this for rustdoc. +extern {} extern crate rustc_driver; diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 06d1301d7000..382ef2cc407d 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -44,6 +44,10 @@ #include "llvm-c/Transforms/PassManagerBuilder.h" +#if LLVM_VERSION_GE(4, 0) +#define PGO_AVAILABLE +#endif + using namespace llvm; using namespace llvm::legacy; @@ -201,17 +205,13 @@ GEN_SUBTARGETS extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, const char *Feature) { -#if LLVM_RUSTLLVM +#if LLVM_VERSION_GE(6, 0) TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const FeatureBitset &Bits = MCInfo->getFeatureBits(); - const ArrayRef FeatTable = MCInfo->getFeatureTable(); - - for (auto &FeatureEntry : FeatTable) - if (!strcmp(FeatureEntry.Key, Feature)) - return (Bits & FeatureEntry.Value) == FeatureEntry.Value; -#endif + return MCInfo->checkFeatures(std::string("+") + Feature); +#else return false; +#endif } enum class LLVMRustCodeModel { @@ -428,12 +428,27 @@ extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM, extern "C" void LLVMRustConfigurePassManagerBuilder( LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel, - bool MergeFunctions, bool SLPVectorize, bool LoopVectorize) { + bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, + const char* PGOGenPath, const char* PGOUsePath) { // Ignore mergefunc for now as enabling it causes crashes. // unwrap(PMBR)->MergeFunctions = MergeFunctions; unwrap(PMBR)->SLPVectorize = SLPVectorize; unwrap(PMBR)->OptLevel = fromRust(OptLevel); unwrap(PMBR)->LoopVectorize = LoopVectorize; + +#ifdef PGO_AVAILABLE + if (PGOGenPath) { + assert(!PGOUsePath); + unwrap(PMBR)->EnablePGOInstrGen = true; + unwrap(PMBR)->PGOInstrGen = PGOGenPath; + } + if (PGOUsePath) { + assert(!PGOGenPath); + unwrap(PMBR)->PGOInstrUse = PGOUsePath; + } +#else + assert(!PGOGenPath && !PGOUsePath && "Should've caught earlier"); +#endif } // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` @@ -766,6 +781,15 @@ LLVMRustThinLTOAvailable() { #endif } +extern "C" bool +LLVMRustPGOAvailable() { +#ifdef PGO_AVAILABLE + return true; +#else + return false; +#endif +} + #if LLVM_VERSION_GE(4, 0) // Here you'll find an implementation of ThinLTO as used by the Rust compiler diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 27d5496f5762..df8602d0803a 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -21,6 +21,8 @@ #if LLVM_VERSION_GE(5, 0) #include "llvm/ADT/Optional.h" +#else +#include #endif //===----------------------------------------------------------------------=== @@ -1019,6 +1021,7 @@ enum class LLVMRustDiagnosticKind { OptimizationRemarkAnalysisAliasing, OptimizationRemarkOther, OptimizationFailure, + PGOProfile, }; static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { @@ -1041,6 +1044,8 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute; case DK_OptimizationRemarkAnalysisAliasing: return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing; + case DK_PGOProfile: + return LLVMRustDiagnosticKind::PGOProfile; default: return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark) ? LLVMRustDiagnosticKind::OptimizationRemarkOther @@ -1395,3 +1400,126 @@ LLVMRustModuleCost(LLVMModuleRef M) { auto f = unwrap(M)->functions(); return std::distance(std::begin(f), std::end(f)); } + +// Vector reductions: +#if LLVM_VERSION_GE(5, 0) +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateAddReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateMulReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateAndReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateOrReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateXorReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { + return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned)); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { + return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned)); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { + return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { + return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); +} + +#else + +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; +} +#endif + +#if LLVM_VERSION_LT(4, 0) +extern "C" LLVMValueRef +LLVMBuildExactUDiv(LLVMBuilderRef B, LLVMValueRef LHS, + LLVMValueRef RHS, const char *Name) { + return wrap(unwrap(B)->CreateExactUDiv(unwrap(LHS), unwrap(RHS), Name)); +} +#endif + +#if LLVM_VERSION_GE(6, 0) +extern "C" LLVMValueRef +LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { + return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS))); +} +extern "C" LLVMValueRef +LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { + return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS))); +} +#else +extern "C" LLVMValueRef +LLVMRustBuildMinNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { + return nullptr; +} +extern "C" LLVMValueRef +LLVMRustBuildMaxNum(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { + return nullptr; +} +#endif diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 63af7a0d538e..c4c0f1ab6e60 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-03-06 +2018-03-10 diff --git a/src/stage0.txt b/src/stage0.txt index b9578386ce5b..96ec1e6834df 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2018-02-20 +date: 2018-03-18 rustc: beta cargo: beta diff --git a/src/stdsimd b/src/stdsimd index 678cbd325c84..bcb720e55861 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 678cbd325c84070c9dbe4303969fbd2734c0b4ee +Subproject commit bcb720e55861c38db47f2ebdf26b7198338cb39d diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md index c255294e790b..8553665c0179 100644 --- a/src/test/COMPILER_TESTS.md +++ b/src/test/COMPILER_TESTS.md @@ -54,6 +54,8 @@ be compiled or run. * `ignore-test` always ignores the test * `ignore-lldb` and `ignore-gdb` will skip a debuginfo test on that debugger. +`only-X` is the opposite. The test will run only when `X` matches. + Some examples of `X` in `ignore-X`: * Architecture: `aarch64`, `arm`, `asmjs`, `mips`, `wasm32`, `x86_64`, `x86`, ... diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs index 1e02fe4befdf..367d509cadfe 100644 --- a/src/test/codegen/abi-main-signature-16bit-c-int.rs +++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs @@ -17,7 +17,9 @@ // ignore-asmjs // ignore-hexagon // ignore-mips +// ignore-mips64 // ignore-powerpc +// ignore-powerpc64 // ignore-s390x // ignore-sparc // ignore-wasm32 diff --git a/src/test/codegen/exact_div.rs b/src/test/codegen/exact_div.rs new file mode 100644 index 000000000000..9ba6c0c00063 --- /dev/null +++ b/src/test/codegen/exact_div.rs @@ -0,0 +1,30 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::intrinsics::exact_div; + +// CHECK-LABEL: @exact_sdiv +#[no_mangle] +pub unsafe fn exact_sdiv(x: i32, y: i32) -> i32 { +// CHECK: sdiv exact + exact_div(x, y) +} + +// CHECK-LABEL: @exact_udiv +#[no_mangle] +pub unsafe fn exact_udiv(x: u32, y: u32) -> u32 { +// CHECK: udiv exact + exact_div(x, y) +} diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs index b24899cc363a..d6dd3f356b5f 100644 --- a/src/test/codegen/fastcall-inreg.rs +++ b/src/test/codegen/fastcall-inreg.rs @@ -21,10 +21,10 @@ // ignore-bpfeb // ignore-hexagon // ignore-mips -// ignore-mipsel // ignore-mips64 -// ignore-mips64el // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 0e98d3f9050a..de302c69056f 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -133,6 +133,12 @@ pub fn trait_borrow(_: &Drop) { pub fn trait_box(_: Box) { } +// CHECK: { i8*, i8* } @trait_option(i8* noalias %x.0, i8* %x.1) +#[no_mangle] +pub fn trait_option(x: Option>) -> Option> { + x +} + // CHECK: { [0 x i16]*, [[USIZE]] } @return_slice([0 x i16]* noalias nonnull readonly %x.0, [[USIZE]] %x.1) #[no_mangle] pub fn return_slice(x: &[u16]) -> &[u16] { diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs index 5661592d0c7b..6b79e79fa008 100644 --- a/src/test/codegen/global_asm.rs +++ b/src/test/codegen/global_asm.rs @@ -17,10 +17,10 @@ // ignore-bpfeb // ignore-hexagon // ignore-mips -// ignore-mipsel // ignore-mips64 -// ignore-mips64el // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs index d8b5db12404a..3f73a1cabbf1 100644 --- a/src/test/codegen/global_asm_include.rs +++ b/src/test/codegen/global_asm_include.rs @@ -17,10 +17,10 @@ // ignore-bpfeb // ignore-hexagon // ignore-mips -// ignore-mipsel // ignore-mips64 -// ignore-mips64el // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs index caa0506550dd..3e118a50d454 100644 --- a/src/test/codegen/global_asm_x2.rs +++ b/src/test/codegen/global_asm_x2.rs @@ -17,10 +17,10 @@ // ignore-bpfeb // ignore-hexagon // ignore-mips -// ignore-mipsel // ignore-mips64 -// ignore-mips64el // ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index 43872f15d51e..8b3294281e96 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -15,9 +15,14 @@ use std::iter; +// CHECK: @helper([[USIZE:i[0-9]+]] %arg0) +#[no_mangle] +pub fn helper(_: usize) { +} + // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec { -// CHECK: call void @llvm.memset.p0i8 +// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}%{{[0-9]+}}, i8 42, [[USIZE]] 100000, i32 1, i1 false) iter::repeat(42).take(100000).collect() } diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs index 655e67cf7eef..2eeed2b788ce 100644 --- a/src/test/codegen/repr-transparent-aggregates-1.rs +++ b/src/test/codegen/repr-transparent-aggregates-1.rs @@ -14,6 +14,7 @@ // ignore-mips // ignore-mips64 // ignore-powerpc +// ignore-powerpc64 // See repr-transparent.rs #![crate_type="lib"] diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs index e6374928a5cb..9605ded569ef 100644 --- a/src/test/codegen/repr-transparent-aggregates-2.rs +++ b/src/test/codegen/repr-transparent-aggregates-2.rs @@ -12,6 +12,7 @@ // ignore-aarch64 // ignore-asmjs +// ignore-mips64 // ignore-s390x // ignore-wasm // ignore-x86 diff --git a/src/test/codegen/repr-transparent-aggregates-3.rs b/src/test/codegen/repr-transparent-aggregates-3.rs new file mode 100644 index 000000000000..0c90239c9de8 --- /dev/null +++ b/src/test/codegen/repr-transparent-aggregates-3.rs @@ -0,0 +1,49 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes + +// only-mips64 +// See repr-transparent.rs + +#![crate_type="lib"] +#![feature(repr_transparent)] + + +#[repr(C)] +pub struct Big([u32; 16]); + +#[repr(transparent)] +pub struct BigW(Big); + +// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], [8 x i64] +#[no_mangle] +pub extern fn test_Big(_: Big) -> Big { loop {} } + +// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], [8 x i64] +#[no_mangle] +pub extern fn test_BigW(_: BigW) -> BigW { loop {} } + + +#[repr(C)] +pub union BigU { + foo: [u32; 16], +} + +#[repr(transparent)] +pub struct BigUw(BigU); + +// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], [8 x i64] +#[no_mangle] +pub extern fn test_BigU(_: BigU) -> BigU { loop {} } + +// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], [8 x i64] +#[no_mangle] +pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} } diff --git a/src/test/codegen/simd-intrinsic-float-minmax.rs b/src/test/codegen/simd-intrinsic-float-minmax.rs new file mode 100644 index 000000000000..6663b841808f --- /dev/null +++ b/src/test/codegen/simd-intrinsic-float-minmax.rs @@ -0,0 +1,43 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten +// min-llvm-version 6.0 + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fmin(x: T, y: T) -> T; + fn simd_fmax(x: T, y: T) -> T; +} + +// CHECK-LABEL: @fmin +#[no_mangle] +pub unsafe fn fmin(a: f32x4, b: f32x4) -> f32x4 { + // CHECK: call <4 x float> @llvm.minnum.v4f32 + simd_fmin(a, b) +} + +// FIXME(49261) +// // C_HECK-LABEL: @fmax +// #[no_mangle] +// pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 { +// // C_HECK: call <4 x float> @llvm.maxnum.v4f32 +// simd_fmax(a, b) +// } diff --git a/src/test/codegen/simd-intrinsic-generic-select.rs b/src/test/codegen/simd-intrinsic-generic-select.rs new file mode 100644 index 000000000000..8a64d7437d84 --- /dev/null +++ b/src/test/codegen/simd-intrinsic-generic-select.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct b8x4(pub i8, pub i8, pub i8, pub i8); + +extern "platform-intrinsic" { + fn simd_select(x: T, a: U, b: U) -> U; +} + +// CHECK-LABEL: @select +#[no_mangle] +pub unsafe fn select(m: b8x4, a: f32x4, b: f32x4) -> f32x4 { + // CHECK: select <4 x i1> + simd_select(m, a, b) +} diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs index 4a489f1edb3b..51ebc42a0dd6 100644 --- a/src/test/codegen/stack-probes.rs +++ b/src/test/codegen/stack-probes.rs @@ -10,8 +10,10 @@ // ignore-arm // ignore-aarch64 +// ignore-mips +// ignore-mips64 // ignore-powerpc -// ignore-aarch64 +// ignore-s390x // ignore-wasm // ignore-emscripten // ignore-windows diff --git a/src/test/codegen/unchecked-float-casts.rs b/src/test/codegen/unchecked-float-casts.rs index c2fc29661709..87ebaaeec320 100644 --- a/src/test/codegen/unchecked-float-casts.rs +++ b/src/test/codegen/unchecked-float-casts.rs @@ -14,7 +14,6 @@ // -Z saturating-float-casts is not enabled. #![crate_type = "lib"] -#![feature(i128_type)] // CHECK-LABEL: @f32_to_u32 #[no_mangle] diff --git a/src/test/codegen/x86_mmx.rs b/src/test/codegen/x86_mmx.rs index dc9f63c35db2..30777c6214ec 100644 --- a/src/test/codegen/x86_mmx.rs +++ b/src/test/codegen/x86_mmx.rs @@ -11,6 +11,8 @@ // ignore-arm // ignore-aarch64 // ignore-emscripten +// ignore-mips +// ignore-mips64 // compile-flags: -O #![feature(repr_simd)] diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs index 61b1a0a0b4d2..77ea30194193 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs @@ -37,6 +37,9 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_syntax_extension( Symbol::intern("into_multi_foo"), MultiModifier(Box::new(expand_into_foo_multi))); + reg.register_syntax_extension( + Symbol::intern("noop_attribute"), + MultiModifier(Box::new(expand_noop_attribute))); reg.register_syntax_extension( Symbol::intern("duplicate"), MultiDecorator(Box::new(expand_duplicate))); @@ -90,9 +93,18 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt, } }) } + // these are covered in proc_macro/attr-stmt-expr.rs + Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item") } } +fn expand_noop_attribute(_cx: &mut ExtCtxt, + _sp: Span, + _attr: &MetaItem, + it: Annotatable) -> Annotatable { + it +} + // Create a duplicate of the annotatable, based on the MetaItem fn expand_duplicate(cx: &mut ExtCtxt, _sp: Span, @@ -135,6 +147,8 @@ fn expand_duplicate(cx: &mut ExtCtxt, new_it.ident = copy_name; push(Annotatable::TraitItem(P(new_it))); } + // covered in proc_macro/attr-stmt-expr.rs + Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item") } } diff --git a/src/test/compile-fail-fulldeps/issue-48941.rs b/src/test/compile-fail-fulldeps/issue-48941.rs new file mode 100644 index 000000000000..4be2874ed4ff --- /dev/null +++ b/src/test/compile-fail-fulldeps/issue-48941.rs @@ -0,0 +1,29 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This is a regression test against an ICE that used to occur +// on malformed attributes for a custom MultiModifier. + +// aux-build:macro_crate_test.rs +// ignore-stage1 + +#![feature(plugin)] +#![plugin(macro_crate_test)] + +#[noop_attribute"x"] //~ ERROR expected one of +fn night() { } + +#[noop_attribute("hi"), rank = 2] //~ ERROR unexpected token +fn knight() { } + +#[noop_attribute("/user", data= = " or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:attr-stmt-expr.rs +// ignore-stage1 + +//! Attributes producing expressions in invalid locations + +#![feature(proc_macro, stmt_expr_attributes)] + +extern crate attr_stmt_expr; +use attr_stmt_expr::{duplicate, no_output}; + +fn main() { + let _ = #[no_output] "Hello, world!"; + //~^ ERROR expected expression, found `` + + let _ = #[duplicate] "Hello, world!"; + //~^ ERROR macro expansion ignores token `,` and any following + + let _ = { + #[no_output] + "Hello, world!" + }; + + let _ = { + #[duplicate] + //~^ ERROR macro expansion ignores token `,` and any following + "Hello, world!" + }; +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs b/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs new file mode 100644 index 000000000000..d29bc00c663c --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:attr-stmt-expr.rs +// ignore-stage1 + +#![feature(proc_macro)] + +extern crate attr_stmt_expr; +use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr}; + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_print_expr] + //~^ ERROR attributes on expressions are experimental + //~| HELP add #![feature(stmt_expr_attributes)] to the crate attributes to enable + println!("{}", string) +} + +fn main() { + #[expect_let] + let string = "Hello, world!"; + + #[expect_print_stmt] + println!("{}", string); + + #[expect_expr] + //~^ ERROR attributes on expressions are experimental + //~| HELP add #![feature(stmt_expr_attributes)] to the crate attributes to enable + print_str("string") +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs new file mode 100644 index 000000000000..8bae1697dcbe --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs @@ -0,0 +1,59 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "let string = \"Hello, world!\";"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println!(\"{}\" , string);"); + item +} + +#[proc_macro_attribute] +pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "print_str(\"string\")"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println!(\"{}\" , string)"); + item +} + +#[proc_macro_attribute] +pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + format!("{}, {}", item, item).parse().unwrap() +} + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs index a1efbb88a4d2..d725adfec754 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs @@ -16,7 +16,7 @@ extern crate proc_macro; -use proc_macro::{TokenStream, TokenTree, TokenNode, Delimiter, Literal}; +use proc_macro::{TokenStream, TokenTree, TokenNode, Delimiter, Literal, Spacing}; #[proc_macro_attribute] pub fn foo(attr: TokenStream, input: TokenStream) -> TokenStream { @@ -65,10 +65,34 @@ fn assert_inline(slice: &mut &[TokenTree]) { fn assert_doc(slice: &mut &[TokenTree]) { match slice[0].kind { - TokenNode::Literal(_) => {} - _ => panic!("expected literal doc comment got other"), + TokenNode::Op('#', Spacing::Alone) => {} + _ => panic!("expected #"), } - *slice = &slice[1..]; + let inner = match slice[1].kind { + TokenNode::Group(Delimiter::Bracket, ref s) => s.clone(), + _ => panic!("expected brackets"), + }; + let tokens = inner.into_iter().collect::>(); + let tokens = &tokens[..]; + + if tokens.len() != 3 { + panic!("expected three tokens in doc") + } + + match tokens[0].kind { + TokenNode::Term(ref t) => assert_eq!("doc", t.as_str()), + _ => panic!("expected `doc`"), + } + match tokens[1].kind { + TokenNode::Op('=', Spacing::Alone) => {} + _ => panic!("expected equals"), + } + match tokens[2].kind { + TokenNode::Literal(_) => {} + _ => panic!("expected literal"), + } + + *slice = &slice[2..]; } fn assert_invoc(slice: &mut &[TokenTree]) { diff --git a/src/test/compile-fail/asm-bad-clobber.rs b/src/test/compile-fail/asm-bad-clobber.rs index b863e90a3b71..aa77e7f46e50 100644 --- a/src/test/compile-fail/asm-bad-clobber.rs +++ b/src/test/compile-fail/asm-bad-clobber.rs @@ -15,6 +15,8 @@ // ignore-emscripten // ignore-powerpc // ignore-sparc +// ignore-mips +// ignore-mips64 #![feature(asm, rustc_attrs)] diff --git a/src/test/compile-fail/asm-in-bad-modifier.rs b/src/test/compile-fail/asm-in-bad-modifier.rs index cae41332795d..5e9278c7c35f 100644 --- a/src/test/compile-fail/asm-in-bad-modifier.rs +++ b/src/test/compile-fail/asm-in-bad-modifier.rs @@ -12,6 +12,8 @@ // ignore-emscripten // ignore-powerpc // ignore-sparc +// ignore-mips +// ignore-mips64 #![feature(asm)] diff --git a/src/test/compile-fail/asm-misplaced-option.rs b/src/test/compile-fail/asm-misplaced-option.rs index e634238c6e17..abd55ea10118 100644 --- a/src/test/compile-fail/asm-misplaced-option.rs +++ b/src/test/compile-fail/asm-misplaced-option.rs @@ -15,6 +15,8 @@ // ignore-emscripten // ignore-powerpc // ignore-sparc +// ignore-mips +// ignore-mips64 #![feature(asm, rustc_attrs)] diff --git a/src/test/compile-fail/asm-out-no-modifier.rs b/src/test/compile-fail/asm-out-no-modifier.rs index 2e843ddac822..55d8970008f9 100644 --- a/src/test/compile-fail/asm-out-no-modifier.rs +++ b/src/test/compile-fail/asm-out-no-modifier.rs @@ -12,6 +12,8 @@ // ignore-emscripten // ignore-powerpc // ignore-sparc +// ignore-mips +// ignore-mips64 #![feature(asm)] diff --git a/src/test/compile-fail/asm-out-read-uninit.rs b/src/test/compile-fail/asm-out-read-uninit.rs index 02462bf1be7d..c606c5a80e58 100644 --- a/src/test/compile-fail/asm-out-read-uninit.rs +++ b/src/test/compile-fail/asm-out-read-uninit.rs @@ -12,6 +12,8 @@ // ignore-emscripten // ignore-powerpc // ignore-sparc +// ignore-mips +// ignore-mips64 // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir diff --git a/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs b/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs index 53e287cda208..ec7885f1f44f 100644 --- a/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs +++ b/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs @@ -12,8 +12,7 @@ // `#[oops]` is left dangling (that is, it is unattached, with no // formal binding following it). -#![feature(generic_param_attrs, rustc_attrs)] -#![allow(dead_code)] +#![feature(rustc_attrs)] struct RefIntPair<'a, 'b>(&'a u32, &'b u32); diff --git a/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs b/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs index 5e09473ab77d..efe2d5561a83 100644 --- a/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs +++ b/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs @@ -12,8 +12,7 @@ // `#[oops]` is left dangling (that is, it is unattached, with no // formal binding following it). -#![feature(generic_param_attrs, rustc_attrs)] -#![allow(dead_code)] +#![feature(rustc_attrs)] struct RefAny<'a, T>(&'a T); diff --git a/src/test/compile-fail/i128-feature-libs.rs b/src/test/compile-fail/auxiliary/unstable-macros.rs similarity index 61% rename from src/test/compile-fail/i128-feature-libs.rs rename to src/test/compile-fail/auxiliary/unstable-macros.rs index b29ac50fd377..6462c11af481 100644 --- a/src/test/compile-fail/i128-feature-libs.rs +++ b/src/test/compile-fail/auxiliary/unstable-macros.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn testl() { - ::std::u128::MAX; //~ ERROR use of unstable library feature 'i128' -} +#![feature(staged_api)] +#![stable(feature = "unit_test", since = "0.0.0")] -fn testl2() { - ::std::i128::MAX; //~ ERROR use of unstable library feature 'i128' -} +#[unstable(feature = "unstable_macros", issue = "0")] +#[macro_export] +macro_rules! unstable_macro{ () => () } diff --git a/src/test/compile-fail/borrowck/borrowck-asm.rs b/src/test/compile-fail/borrowck/borrowck-asm.rs index 6bccc8386809..9ad3a8f9fc86 100644 --- a/src/test/compile-fail/borrowck/borrowck-asm.rs +++ b/src/test/compile-fail/borrowck/borrowck-asm.rs @@ -21,7 +21,9 @@ #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", - target_arch = "aarch64"))] + target_arch = "aarch64", + target_arch = "mips", + target_arch = "mips64"))] mod test_cases { fn is_move() { let y: &mut isize; diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 1d08b8074658..fa475949b36b 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -13,7 +13,6 @@ //[mir]compile-flags: -Z borrowck=mir #![feature(slice_patterns)] -#![feature(advanced_slice_patterns)] pub struct Foo { x: u32 diff --git a/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs index 32a573911ece..30047f84041f 100644 --- a/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs +++ b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs @@ -13,8 +13,6 @@ // Test that immutable pattern bindings cannot be reassigned. -#![feature(slice_patterns)] - enum E { Foo(isize) } diff --git a/src/test/compile-fail/borrowck/borrowck-move-out-from-array.rs b/src/test/compile-fail/borrowck/borrowck-move-out-from-array.rs index e01161734623..0db31cef0ed7 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-out-from-array.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-out-from-array.rs @@ -11,7 +11,8 @@ // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir -#![feature(box_syntax, slice_patterns, advanced_slice_patterns)] +#![feature(box_syntax)] +#![feature(slice_patterns)] fn move_out_from_begin_and_end() { let a = [box 1, box 2]; diff --git a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs index df0a05dfaee0..f2e6d51d064d 100644 --- a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-test will be fixed later // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir diff --git a/src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs index eb5d69d49bd6..0fd6923326ab 100644 --- a/src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs +++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] fn a<'a>() -> &'a [isize] { diff --git a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs index 709c00ba8464..90933c6b31fa 100644 --- a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs @@ -10,10 +10,12 @@ // ignore-tidy-linelength -// revisions: lxl_beyond nll_beyond nll_target +// revisions: nll_target +// The following revisions are disabled due to missing support from two-phase beyond autorefs //[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref //[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll + //[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll // This is an important corner case pointed out by Niko: one is @@ -51,7 +53,6 @@ fn not_ok() { *y += 1; //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable //[nll_beyond]~^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable - //[nll_target]~^^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable read(z); } diff --git a/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs b/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs index dd174981fb1e..d2f4154433ab 100644 --- a/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs +++ b/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs @@ -10,9 +10,13 @@ // ignore-tidy-linelength -// revisions: lxl_beyond nll_beyond nll_target +// revisions: nll_target + +// The following revisions are disabled due to missing support for two_phase_beyond_autoref //[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref //[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref -Z nll + + //[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll // This is the second counter-example from Niko's blog post diff --git a/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs b/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs index f4c36157fe98..ef39fabda10e 100644 --- a/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs +++ b/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll g2p +// revisions: ast lxl nll +//[ast]compile-flags: //[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows //[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll + //[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll -Z two-phase-beyond-autoref +// the above revision is disabled until two-phase-beyond-autoref support is better // This is a test checking that when we limit two-phase borrows to // method receivers, we do not let other kinds of auto-ref to leak @@ -31,17 +34,14 @@ use std::ops::{Index, IndexMut}; -// This is case outlined by Niko that we want to ensure we reject -// (at least initially). - fn foo(x: &mut u32, y: u32) { *x += y; } fn deref_coercion(x: &mut u32) { foo(x, *x); - //[lxl]~^ ERROR cannot use `*x` because it was mutably borrowed [E0503] - //[nll]~^^ ERROR cannot use `*x` because it was mutably borrowed [E0503] + //[ast]~^ ERROR cannot use `*x` because it was mutably borrowed [E0503] + // Above error is a known limitation of AST borrowck } // While adding a flag to adjustments (indicating whether they @@ -70,28 +70,27 @@ fn overloaded_call_traits() { fn twice_ten_sm i32>(f: &mut F) { f(f(10)); //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time - //[lxl]~| ERROR cannot borrow `*f` as mutable more than once at a time - //[nll]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time - //[nll]~| ERROR cannot borrow `*f` as mutable more than once at a time - //[g2p]~^^^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[ast]~^^^^ ERROR cannot borrow `*f` as mutable more than once at a time } fn twice_ten_si i32>(f: &mut F) { f(f(10)); } fn twice_ten_so i32>(f: Box) { f(f(10)); - //[lxl]~^ ERROR use of moved value: `*f` - //[nll]~^^ ERROR use of moved value: `*f` - //[g2p]~^^^ ERROR use of moved value: `*f` + //[lxl]~^ ERROR use of moved value: `*f` + //[nll]~^^ ERROR use of moved value: `*f` + //[g2p]~^^^ ERROR use of moved value: `*f` + //[ast]~^^^^ ERROR use of moved value: `*f` } fn twice_ten_om(f: &mut FnMut(i32) -> i32) { f(f(10)); - //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time - //[lxl]~| ERROR cannot borrow `*f` as mutable more than once at a time - //[nll]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time - //[nll]~| ERROR cannot borrow `*f` as mutable more than once at a time - //[g2p]~^^^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[ast]~^^^^ ERROR cannot borrow `*f` as mutable more than once at a time } fn twice_ten_oi(f: &mut Fn(i32) -> i32) { f(f(10)); @@ -107,6 +106,7 @@ fn overloaded_call_traits() { //[g2p]~^^^^^^^ ERROR cannot move a value of type //[g2p]~^^^^^^^^ ERROR cannot move a value of type //[g2p]~^^^^^^^^^ ERROR use of moved value: `*f` + //[ast]~^^^^^^^^^^ ERROR use of moved value: `*f` } twice_ten_sm(&mut |x| x + 1); @@ -144,12 +144,15 @@ fn coerce_unsized() { // This is not okay. double_access(&mut a, &a); - //[lxl]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] - //[nll]~^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] - //[g2p]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[lxl]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[g2p]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[ast]~^^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] // But this is okay. a.m(a.i(10)); + //[ast]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + // Above error is an expected limitation of AST borrowck } struct I(i32); @@ -170,14 +173,16 @@ impl IndexMut for I { fn coerce_index_op() { let mut i = I(10); i[i[3]] = 4; - //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] - //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[ast]~^^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] i[3] = i[4]; i[i[3]] = i[4]; - //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] - //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[ast]~^^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] } fn main() { @@ -185,6 +190,8 @@ fn main() { // As a reminder, this is the basic case we want to ensure we handle. let mut v = vec![1, 2, 3]; v.push(v.len()); + //[ast]~^ ERROR cannot borrow `v` as immutable because it is also borrowed as mutable [E0502] + // Error above is an expected limitation of AST borrowck // (as a rule, pnkfelix does not like to write tests with dead code.) @@ -194,9 +201,13 @@ fn main() { let mut s = S; s.m(s.i(10)); + //[ast]~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable [E0502] + // Error above is an expected limitation of AST borrowck let mut t = T; t.m(t.i(10)); + //[ast]~^ ERROR cannot borrow `t` as immutable because it is also borrowed as mutable [E0502] + // Error above is an expected limitation of AST borrowck coerce_unsized(); coerce_index_op(); diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs index b5fda4985f23..058022ad588e 100644 --- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs @@ -12,8 +12,12 @@ // revisions: lxl_beyond nll_beyond nll_target +// The following revisions are disabled due to missing support from two-phase beyond autorefs //[lxl_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref +//[lxl_beyond] should-fail //[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll +//[nll_beyond] should-fail + //[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll // This is a corner case that the current implementation is (probably) @@ -31,10 +35,6 @@ // "nll_beyond" means the generalization of two-phase borrows to all // `&mut`-borrows (doing so makes it easier to write code for specific // corner cases). -// -// FIXME: in "nll_target", we currently see the same error reported -// twice. This is injected by `-Z two-phase-borrows`; not sure why as -// of yet. fn main() { let mut vec = vec![0, 1]; @@ -49,7 +49,6 @@ fn main() { //[lxl_beyond]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable //[nll_beyond]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable //[nll_target]~^^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable - //[nll_target]~| ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable shared[0]; } diff --git a/src/test/compile-fail/builtin-superkinds-double-superkind.rs b/src/test/compile-fail/builtin-superkinds-double-superkind.rs index 8d5d8e8dc9b7..261881d880bf 100644 --- a/src/test/compile-fail/builtin-superkinds-double-superkind.rs +++ b/src/test/compile-fail/builtin-superkinds-double-superkind.rs @@ -13,9 +13,11 @@ trait Foo : Send+Sync { } -impl Foo for (T,) { } //~ ERROR `T: std::marker::Send` is not satisfied +impl Foo for (T,) { } +//~^ ERROR the trait bound `T: std::marker::Send` is not satisfied in `(T,)` [E0277] -impl Foo for (T,T) { } //~ ERROR `T: std::marker::Sync` is not satisfied +impl Foo for (T,T) { } +//~^ ERROR `T` cannot be shared between threads safely [E0277] impl Foo for (T,T,T) { } // (ok) diff --git a/src/test/compile-fail/call-fn-never-arg-wrong-type.rs b/src/test/compile-fail/call-fn-never-arg-wrong-type.rs index 583befed1e82..c2f157cd35cc 100644 --- a/src/test/compile-fail/call-fn-never-arg-wrong-type.rs +++ b/src/test/compile-fail/call-fn-never-arg-wrong-type.rs @@ -10,8 +10,6 @@ // Test that we can't pass other types for ! -#![feature(never_type)] - fn foo(x: !) -> ! { x } diff --git a/src/test/compile-fail/cfg-attr-cfg-2.rs b/src/test/compile-fail/cfg-attr-cfg-2.rs index b71a3be5dcea..58a62d45ea5d 100644 --- a/src/test/compile-fail/cfg-attr-cfg-2.rs +++ b/src/test/compile-fail/cfg-attr-cfg-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // -// error-pattern: main function not found +// error-pattern: `main` function not found // compile-flags: --cfg foo // main is conditionally compiled, but the conditional compilation diff --git a/src/test/compile-fail/cfg-in-crate-1.rs b/src/test/compile-fail/cfg-in-crate-1.rs index 94ae8d89b4fc..bbccf2bcd0f8 100644 --- a/src/test/compile-fail/cfg-in-crate-1.rs +++ b/src/test/compile-fail/cfg-in-crate-1.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:main function not found +// error-pattern: `main` function not found #![cfg(bar)] diff --git a/src/test/compile-fail/closure-bounds-subtype.rs b/src/test/compile-fail/closure-bounds-subtype.rs index d3339c4845ab..db26535b004a 100644 --- a/src/test/compile-fail/closure-bounds-subtype.rs +++ b/src/test/compile-fail/closure-bounds-subtype.rs @@ -21,7 +21,7 @@ fn give_any(f: F) where F: FnOnce() { fn give_owned(f: F) where F: FnOnce() + Send { take_any(f); - take_const_owned(f); //~ ERROR `F: std::marker::Sync` is not satisfied + take_const_owned(f); //~ ERROR `F` cannot be shared between threads safely [E0277] } fn main() {} diff --git a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs index f1b198a05917..124e55ea23a0 100644 --- a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs +++ b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs @@ -10,7 +10,6 @@ // must-compile-successfully -#![feature(underscore_lifetimes)] #![allow(warnings)] type Different<'a, 'b> = &'a mut (&'a (), &'b ()); diff --git a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs index 645fd1f80bab..63284c98020f 100644 --- a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(underscore_lifetimes)] - fn with_closure_expecting_fn_with_free_region(_: F) where F: for<'a> FnOnce(fn(&'a u32), &i32) { diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs index 0d5bf6cd68cb..5efb4dadc64b 100644 --- a/src/test/compile-fail/coerce-to-bang-cast.rs +++ b/src/test/compile-fail/coerce-to-bang-cast.rs @@ -8,15 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] - fn foo(x: usize, y: !, z: usize) { } -#[deny(coerce_never)] fn cast_a() { let y = {return; 22} as !; - //~^ ERROR cannot coerce `i32` to ! - //~| hard error + //~^ ERROR non-primitive cast } fn cast_b() { diff --git a/src/test/compile-fail/coerce-to-bang.rs b/src/test/compile-fail/coerce-to-bang.rs index b804bb2981ba..15049232a4d3 100644 --- a/src/test/compile-fail/coerce-to-bang.rs +++ b/src/test/compile-fail/coerce-to-bang.rs @@ -8,18 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] -#![deny(coerce_never)] - fn foo(x: usize, y: !, z: usize) { } fn call_foo_a() { - // FIXME(#40800) -- accepted because divergence happens **before** - // the coercion to `!`, but within same expression. Not clear that - // these are the rules we want. foo(return, 22, 44); - //~^ ERROR cannot coerce `{integer}` to ! - //~| hard error + //~^ ERROR mismatched types } fn call_foo_b() { @@ -39,8 +32,7 @@ fn call_foo_d() { let b = 22; let c = 44; foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. - //~^ ERROR cannot coerce `{integer}` to ! - //~| hard error + //~^ ERROR mismatched types } fn call_foo_e() { @@ -80,8 +72,7 @@ fn tuple_a() { fn tuple_b() { // Divergence happens before coercion: OK let x: (usize, !, usize) = (return, 44, 66); - //~^ ERROR cannot coerce `{integer}` to ! - //~| hard error + //~^ ERROR mismatched types } fn tuple_c() { diff --git a/src/test/compile-fail/conservative_impl_trait.rs b/src/test/compile-fail/conservative_impl_trait.rs index 7fb0ec52f29f..30895bce357b 100644 --- a/src/test/compile-fail/conservative_impl_trait.rs +++ b/src/test/compile-fail/conservative_impl_trait.rs @@ -10,7 +10,6 @@ // #39872, #39553 -#![feature(conservative_impl_trait)] fn will_ice(something: &u32) -> impl Iterator { //~^ ERROR the trait bound `(): std::iter::Iterator` is not satisfied [E0277] } diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-never-note.rs similarity index 82% rename from src/test/compile-fail/defaulted-unit-warning.rs rename to src/test/compile-fail/defaulted-never-note.rs index 3f4e1cce548b..798544f16493 100644 --- a/src/test/compile-fail/defaulted-unit-warning.rs +++ b/src/test/compile-fail/defaulted-never-note.rs @@ -25,14 +25,17 @@ trait ImplementedForUnitButNotNever {} impl ImplementedForUnitButNotNever for () {} fn foo(_t: T) {} +//~^ NOTE required by `foo` fn smeg() { let _x = return; foo(_x); - //~^ ERROR code relies on type - //~| WARNING previously accepted + //~^ ERROR the trait bound + //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented + //~| NOTE the trait is implemented for `()` } fn main() { smeg(); } + diff --git a/src/test/compile-fail/deprecation-lint.rs b/src/test/compile-fail/deprecation-lint.rs index a058234a6492..93eb6b6b1154 100644 --- a/src/test/compile-fail/deprecation-lint.rs +++ b/src/test/compile-fail/deprecation-lint.rs @@ -180,6 +180,11 @@ mod this_crate { #[deprecated(since = "1.0.0", note = "text")] pub fn deprecated_text() {} + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future() {} + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future_text() {} + pub struct MethodTester; impl MethodTester { @@ -266,6 +271,9 @@ mod this_crate { ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text + deprecated_future(); // Fine; no error. + deprecated_future_text(); // Fine; no error. + let _ = DeprecatedStruct { //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text diff --git a/src/test/compile-fail/diverging-fn-tail-35849.rs b/src/test/compile-fail/diverging-fn-tail-35849.rs index a91c000bbf71..9ef5159cb771 100644 --- a/src/test/compile-fail/diverging-fn-tail-35849.rs +++ b/src/test/compile-fail/diverging-fn-tail-35849.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[deny(coerce_never)] fn assert_sizeof() -> ! { unsafe { ::std::mem::transmute::(panic!()) - //~^ ERROR cannot coerce `[u8; 8]` to ! - //~| hard error + //~^ ERROR mismatched types } } diff --git a/src/test/compile-fail/epoch-raw-pointer-method-2015.rs b/src/test/compile-fail/edition-raw-pointer-method-2015.rs similarity index 85% rename from src/test/compile-fail/epoch-raw-pointer-method-2015.rs rename to src/test/compile-fail/edition-raw-pointer-method-2015.rs index 6aa83a38b7ee..fdc9b4f704cd 100644 --- a/src/test/compile-fail/epoch-raw-pointer-method-2015.rs +++ b/src/test/compile-fail/edition-raw-pointer-method-2015.rs @@ -9,9 +9,9 @@ // except according to those terms. // ignore-tidy-linelength -// compile-flags: -Zepoch=2015 -Zunstable-options +// compile-flags: -Zedition=2015 -Zunstable-options -// tests that epochs work with the tyvar warning-turned-error +// tests that editions work with the tyvar warning-turned-error #[deny(warnings)] fn main() { diff --git a/src/test/compile-fail/epoch-raw-pointer-method-2018.rs b/src/test/compile-fail/edition-raw-pointer-method-2018.rs similarity index 85% rename from src/test/compile-fail/epoch-raw-pointer-method-2018.rs rename to src/test/compile-fail/edition-raw-pointer-method-2018.rs index c4815de2306e..58b34591029b 100644 --- a/src/test/compile-fail/epoch-raw-pointer-method-2018.rs +++ b/src/test/compile-fail/edition-raw-pointer-method-2018.rs @@ -9,9 +9,9 @@ // except according to those terms. // ignore-tidy-linelength -// compile-flags: -Zepoch=2018 -Zunstable-options +// compile-flags: -Zedition=2018 -Zunstable-options -// tests that epochs work with the tyvar warning-turned-error +// tests that editions work with the tyvar warning-turned-error #[deny(warnings)] fn main() { diff --git a/src/test/compile-fail/elided-test.rs b/src/test/compile-fail/elided-test.rs index b62214b12f9a..0cdd0010a745 100644 --- a/src/test/compile-fail/elided-test.rs +++ b/src/test/compile-fail/elided-test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: main function not found +// error-pattern: `main` function not found // Since we're not compiling a test runner this function should be elided // and the build will fail because main doesn't exist diff --git a/src/test/compile-fail/extern-types-not-sync-send.rs b/src/test/compile-fail/extern-types-not-sync-send.rs index 2f00cf812e47..6a7a515ba5fb 100644 --- a/src/test/compile-fail/extern-types-not-sync-send.rs +++ b/src/test/compile-fail/extern-types-not-sync-send.rs @@ -21,7 +21,7 @@ fn assert_send() { } fn main() { assert_sync::(); - //~^ ERROR the trait bound `A: std::marker::Sync` is not satisfied + //~^ ERROR `A` cannot be shared between threads safely [E0277] assert_send::(); //~^ ERROR the trait bound `A: std::marker::Send` is not satisfied diff --git a/src/test/ui/feature-gate-match_default_bindings.rs b/src/test/compile-fail/feature-gate-termination_trait_test.rs similarity index 70% rename from src/test/ui/feature-gate-match_default_bindings.rs rename to src/test/compile-fail/feature-gate-termination_trait_test.rs index 4ee2c1e2936a..4af7e9467162 100644 --- a/src/test/ui/feature-gate-match_default_bindings.rs +++ b/src/test/compile-fail/feature-gate-termination_trait_test.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn main() { - match &Some(3) { - Some(n) => {}, - //~^ ERROR non-reference pattern used to match a reference - _ => panic!(), +// compile-flags: --test + +fn main() {} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() -> Result<(), ()> { + //~^ ERROR functions used as tests must have signature fn() -> () + Ok(()) } } diff --git a/src/test/compile-fail/impl-trait/impl-generic-mismatch-ab.rs b/src/test/compile-fail/impl-trait/impl-generic-mismatch-ab.rs index 43b47e9e915f..23549918ff1b 100644 --- a/src/test/compile-fail/impl-trait/impl-generic-mismatch-ab.rs +++ b/src/test/compile-fail/impl-trait/impl-generic-mismatch-ab.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] use std::fmt::Debug; trait Foo { diff --git a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs index a95da61aa4c0..eea7ca209578 100644 --- a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs +++ b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] use std::fmt::Debug; trait Foo { diff --git a/src/test/compile-fail/impl-trait/infinite-impl-trait-issue-38064.rs b/src/test/compile-fail/impl-trait/infinite-impl-trait-issue-38064.rs index abde9689bd6b..653ef1723e0b 100644 --- a/src/test/compile-fail/impl-trait/infinite-impl-trait-issue-38064.rs +++ b/src/test/compile-fail/impl-trait/infinite-impl-trait-issue-38064.rs @@ -15,8 +15,6 @@ // error-pattern:overflow evaluating the requirement `impl Quux` -#![feature(conservative_impl_trait)] - trait Quux {} fn foo() -> impl Quux { diff --git a/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs index 0eb99ca0fc3f..537fc975bcf9 100644 --- a/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - use std::fmt::Debug; fn elided(x: &i32) -> impl Copy { x } diff --git a/src/test/compile-fail/impl-trait/needs_least_region_or_bound.rs b/src/test/compile-fail/impl-trait/needs_least_region_or_bound.rs index 2a06580fe605..6c0a0b800ce3 100644 --- a/src/test/compile-fail/impl-trait/needs_least_region_or_bound.rs +++ b/src/test/compile-fail/impl-trait/needs_least_region_or_bound.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - use std::fmt::Debug; trait MultiRegionTrait<'a, 'b> {} diff --git a/src/test/compile-fail/impl-trait/no-trait.rs b/src/test/compile-fail/impl-trait/no-trait.rs index ce61c5bf63d8..5299ba297d0a 100644 --- a/src/test/compile-fail/impl-trait/no-trait.rs +++ b/src/test/compile-fail/impl-trait/no-trait.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - fn f() -> impl 'static {} //~ ERROR at least one trait must be specified fn main() {} diff --git a/src/test/compile-fail/impl-trait/type_parameters_captured.rs b/src/test/compile-fail/impl-trait/type_parameters_captured.rs index c6ff762b9050..7c3430ab90e5 100644 --- a/src/test/compile-fail/impl-trait/type_parameters_captured.rs +++ b/src/test/compile-fail/impl-trait/type_parameters_captured.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - use std::fmt::Debug; trait Any {} diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs index 52c5471681df..038eacaf1103 100644 --- a/src/test/compile-fail/impl-trait/where-allowed.rs +++ b/src/test/compile-fail/impl-trait/where-allowed.rs @@ -10,7 +10,7 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait -#![feature(conservative_impl_trait, universal_impl_trait, dyn_trait)] +#![feature(dyn_trait)] use std::fmt::Debug; // Allowed diff --git a/src/test/compile-fail/inhabitedness-infinite-loop.rs b/src/test/compile-fail/inhabitedness-infinite-loop.rs index 91b85d7510a2..b9741e0add61 100644 --- a/src/test/compile-fail/inhabitedness-infinite-loop.rs +++ b/src/test/compile-fail/inhabitedness-infinite-loop.rs @@ -10,7 +10,7 @@ // error-pattern:reached recursion limit -#![feature(never_type)] +#![feature(exhaustive_patterns)] struct Foo<'a, T: 'a> { ph: std::marker::PhantomData, diff --git a/src/test/compile-fail/issue-12369.rs b/src/test/compile-fail/issue-12369.rs index 4df1e24dcfbd..1b9af393ccce 100644 --- a/src/test/compile-fail/issue-12369.rs +++ b/src/test/compile-fail/issue-12369.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(slice_patterns)] -#![allow(unused_variables)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/compile-fail/issue-13482-2.rs b/src/test/compile-fail/issue-13482-2.rs index 6885c8d94c6b..fe7fbb176cc5 100644 --- a/src/test/compile-fail/issue-13482-2.rs +++ b/src/test/compile-fail/issue-13482-2.rs @@ -10,8 +10,6 @@ // compile-flags:-Z verbose -#![feature(slice_patterns)] - fn main() { let x = [1,2]; let y = match x { diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs index 82e82df31861..32a63b79a32d 100644 --- a/src/test/compile-fail/issue-13482.rs +++ b/src/test/compile-fail/issue-13482.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - fn main() { let x = [1,2]; let y = match x { diff --git a/src/test/compile-fail/issue-15381.rs b/src/test/compile-fail/issue-15381.rs index d0964d2aabea..1cdd803971b4 100644 --- a/src/test/compile-fail/issue-15381.rs +++ b/src/test/compile-fail/issue-15381.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - fn main() { let values: Vec = vec![1,2,3,4,5,6,7,8]; diff --git a/src/test/compile-fail/issue-16338.rs b/src/test/compile-fail/issue-16338.rs index 6fdf8802e385..438073e3b2f8 100644 --- a/src/test/compile-fail/issue-16338.rs +++ b/src/test/compile-fail/issue-16338.rs @@ -17,5 +17,4 @@ fn main() { let Slice { data: data, len: len } = "foo"; //~^ ERROR mismatched types //~| found type `Slice<_>` - //~| ERROR non-reference pattern used to match a reference } diff --git a/src/test/compile-fail/issue-16538.rs b/src/test/compile-fail/issue-16538.rs index 08c3f7a7c154..7df445c676c9 100644 --- a/src/test/compile-fail/issue-16538.rs +++ b/src/test/compile-fail/issue-16538.rs @@ -21,7 +21,7 @@ mod Y { } static foo: *const Y::X = Y::foo(Y::x as *const Y::X); -//~^ ERROR `*const usize: std::marker::Sync` is not satisfied +//~^ ERROR `*const usize` cannot be shared between threads safely [E0277] //~| ERROR cannot refer to other statics by value, use the address-of operator or a constant instead //~| ERROR E0015 diff --git a/src/test/compile-fail/issue-17718-static-sync.rs b/src/test/compile-fail/issue-17718-static-sync.rs index 790329cd2e42..c5349d4e82b4 100644 --- a/src/test/compile-fail/issue-17718-static-sync.rs +++ b/src/test/compile-fail/issue-17718-static-sync.rs @@ -17,6 +17,6 @@ impl !Sync for Foo {} static FOO: usize = 3; static BAR: Foo = Foo; -//~^ ERROR: `Foo: std::marker::Sync` is not satisfied +//~^ ERROR: `Foo` cannot be shared between threads safely [E0277] fn main() {} diff --git a/src/test/compile-fail/issue-17994.rs b/src/test/compile-fail/issue-17994.rs index 0f30e2461cf3..25141b9b8255 100644 --- a/src/test/compile-fail/issue-17994.rs +++ b/src/test/compile-fail/issue-17994.rs @@ -10,5 +10,4 @@ trait Tr {} type Huh where T: Tr = isize; //~ ERROR type parameter `T` is unused - //~| WARNING where clauses are ignored in type aliases fn main() {} diff --git a/src/test/compile-fail/issue-20261.rs b/src/test/compile-fail/issue-20261.rs index 092aaa769550..bb4dbdcd0cba 100644 --- a/src/test/compile-fail/issue-20261.rs +++ b/src/test/compile-fail/issue-20261.rs @@ -11,7 +11,7 @@ fn main() { // NB: this (almost) typechecks when default binding modes are enabled. for (ref i,) in [].iter() { - //~^ ERROR non-reference pattern used to match a reference i.clone(); + //~^ ERROR type annotations needed } } diff --git a/src/test/compile-fail/issue-32995-2.rs b/src/test/compile-fail/issue-32995-2.rs index 0e917ad95d95..18424fcc9e0a 100644 --- a/src/test/compile-fail/issue-32995-2.rs +++ b/src/test/compile-fail/issue-32995-2.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] #![allow(unused)] fn main() { diff --git a/src/test/compile-fail/issue-35668.rs b/src/test/compile-fail/issue-35668.rs index c9323db054c8..17fd77b6df3a 100644 --- a/src/test/compile-fail/issue-35668.rs +++ b/src/test/compile-fail/issue-35668.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - fn func<'a, T>(a: &'a [T]) -> impl Iterator { a.iter().map(|a| a*a) //~^ ERROR binary operation `*` cannot be applied to type `&T` diff --git a/src/test/compile-fail/issue-36379.rs b/src/test/compile-fail/issue-36379.rs index 2f513b034c36..b20765815e0b 100644 --- a/src/test/compile-fail/issue-36379.rs +++ b/src/test/compile-fail/issue-36379.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, rustc_attrs)] +#![feature(rustc_attrs)] fn _test() -> impl Default { } diff --git a/src/test/compile-fail/issue-41255.rs b/src/test/compile-fail/issue-41255.rs index ac85e43cf4f0..bdd502d44203 100644 --- a/src/test/compile-fail/issue-41255.rs +++ b/src/test/compile-fail/issue-41255.rs @@ -10,7 +10,6 @@ // Matching against float literals should result in a linter error -#![feature(slice_patterns)] #![feature(exclusive_range_pattern)] #![allow(unused)] #![forbid(illegal_floating_point_literal_pattern)] diff --git a/src/test/compile-fail/issue-43733-2.rs b/src/test/compile-fail/issue-43733-2.rs index 0fd31454596e..a5ba9ef9bd35 100644 --- a/src/test/compile-fail/issue-43733-2.rs +++ b/src/test/compile-fail/issue-43733-2.rs @@ -33,7 +33,7 @@ impl Key { use std::thread::__FastLocalKeyInner as Key; static __KEY: Key<()> = Key::new(); -//~^ ERROR `std::cell::UnsafeCell>: std::marker::Sync` is not satisfied -//~| ERROR `std::cell::Cell: std::marker::Sync` is not satisfied +//~^ ERROR `std::cell::UnsafeCell>` cannot be shared between threads +//~| ERROR `std::cell::Cell` cannot be shared between threads safely [E0277] fn main() {} diff --git a/src/test/compile-fail/issue-43988.rs b/src/test/compile-fail/issue-43988.rs new file mode 100644 index 000000000000..ff1fdaef416c --- /dev/null +++ b/src/test/compile-fail/issue-43988.rs @@ -0,0 +1,48 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(stmt_expr_attributes)] + +fn main() { + + #[inline] + let _a = 4; + //~^^ ERROR attribute should be applied to function + + + #[inline(XYZ)] + let _b = 4; + //~^^ ERROR attribute should be applied to function + + #[repr(nothing)] + let _x = 0; + //~^^ ERROR attribute should not be applied to a statement + + #[repr(something_not_real)] + loop { + () + }; + //~^^^^ ERROR attribute should not be applied to an expression + + #[repr] + let _y = "123"; + //~^^ ERROR attribute should not be applied to a statement + + + fn foo() {} + + #[inline(ABC)] + foo(); + //~^^ ERROR attribute should be applied to function + + let _z = #[repr] 1; + //~^ ERROR attribute should not be applied to an expression + +} diff --git a/src/test/compile-fail/issue-47309.rs b/src/test/compile-fail/issue-47309.rs new file mode 100644 index 000000000000..7141bd62dc0d --- /dev/null +++ b/src/test/compile-fail/issue-47309.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure that the mono-item collector does not crash when trying to +// instantiate a default impl of a method with lifetime parameters. +// See https://github.com/rust-lang/rust/issues/47309 + +// compile-flags:-Clink-dead-code +// must-compile-successfully + +#![crate_type="rlib"] + +pub trait EnvFuture { + type Item; + + fn boxed_result<'a>(self) where Self: Sized, Self::Item: 'a, { + } +} + +struct Foo; + +impl<'a> EnvFuture for &'a Foo { + type Item = (); +} diff --git a/src/test/compile-fail/issue-6804.rs b/src/test/compile-fail/issue-6804.rs index 9191dfa155c6..fffa27ab842a 100644 --- a/src/test/compile-fail/issue-6804.rs +++ b/src/test/compile-fail/issue-6804.rs @@ -10,7 +10,6 @@ // Matching against NaN should result in a warning -#![feature(slice_patterns)] #![allow(unused)] #![deny(illegal_floating_point_literal_pattern)] diff --git a/src/test/compile-fail/issue-7364.rs b/src/test/compile-fail/issue-7364.rs index 16138c992ff7..801a1301ad77 100644 --- a/src/test/compile-fail/issue-7364.rs +++ b/src/test/compile-fail/issue-7364.rs @@ -15,6 +15,6 @@ use std::cell::RefCell; // Regression test for issue 7364 static boxed: Box> = box RefCell::new(0); //~^ ERROR allocations are not allowed in statics -//~| ERROR `std::cell::RefCell: std::marker::Sync` is not satisfied +//~| ERROR `std::cell::RefCell` cannot be shared between threads safely [E0277] fn main() { } diff --git a/src/test/compile-fail/kindck-send-object.rs b/src/test/compile-fail/kindck-send-object.rs index bd0e5642b9cc..a84eae0bfdae 100644 --- a/src/test/compile-fail/kindck-send-object.rs +++ b/src/test/compile-fail/kindck-send-object.rs @@ -20,7 +20,7 @@ trait Message : Send { } fn object_ref_with_static_bound_not_ok() { assert_send::<&'static (Dummy+'static)>(); - //~^ ERROR : std::marker::Sync` is not satisfied + //~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277] } fn box_object_with_no_bound_not_ok<'a>() { diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs index da56fccde2d4..66865bbcc7ee 100644 --- a/src/test/compile-fail/kindck-send-object1.rs +++ b/src/test/compile-fail/kindck-send-object1.rs @@ -18,7 +18,7 @@ trait Dummy { } // careful with object types, who knows what they close over... fn test51<'a>() { assert_send::<&'a Dummy>(); - //~^ ERROR : std::marker::Sync` is not satisfied + //~^ ERROR `Dummy + 'a` cannot be shared between threads safely [E0277] } fn test52<'a>() { assert_send::<&'a (Dummy+Sync)>(); diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs index e52a6e12efc9..51bc587d74ff 100644 --- a/src/test/compile-fail/kindck-send-object2.rs +++ b/src/test/compile-fail/kindck-send-object2.rs @@ -14,7 +14,8 @@ fn assert_send() { } trait Dummy { } fn test50() { - assert_send::<&'static Dummy>(); //~ ERROR : std::marker::Sync` is not satisfied + assert_send::<&'static Dummy>(); + //~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277] } fn test53() { diff --git a/src/test/compile-fail/lint-unnecessary-import-braces.rs b/src/test/compile-fail/lint-unnecessary-import-braces.rs index 1c0401ec56b8..214a03c13f4e 100644 --- a/src/test/compile-fail/lint-unnecessary-import-braces.rs +++ b/src/test/compile-fail/lint-unnecessary-import-braces.rs @@ -9,12 +9,12 @@ // except according to those terms. #![deny(unused_import_braces)] -#![allow(dead_code)] -#![allow(unused_imports)] use test::{A}; //~ ERROR braces around A is unnecessary mod test { + use test::{self}; // OK + use test::{self as rename}; // OK pub struct A; } diff --git a/src/test/compile-fail/loop-break-value.rs b/src/test/compile-fail/loop-break-value.rs index 938f7fba2a03..5ef46bb27fd6 100644 --- a/src/test/compile-fail/loop-break-value.rs +++ b/src/test/compile-fail/loop-break-value.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] - fn main() { let val: ! = loop { break break; }; //~^ ERROR mismatched types diff --git a/src/test/compile-fail/placement-expr-unstable.rs b/src/test/compile-fail/macro-stability.rs similarity index 54% rename from src/test/compile-fail/placement-expr-unstable.rs rename to src/test/compile-fail/macro-stability.rs index 35695efe1a9b..a4b922c0fe19 100644 --- a/src/test/compile-fail/placement-expr-unstable.rs +++ b/src/test/compile-fail/macro-stability.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,14 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that placement in respects unstable code checks. +// aux-build:unstable-macros.rs -#![feature(placement_in_syntax)] +#![feature(staged_api)] +#[macro_use] extern crate unstable_macros; + +#[unstable(feature = "local_unstable", issue = "0")] +macro_rules! local_unstable { () => () } fn main() { - use std::boxed::HEAP; //~ ERROR use of unstable library feature - - let _ = HEAP <- { //~ ERROR use of unstable library feature - HEAP //~ ERROR use of unstable library feature - }; + local_unstable!(); + unstable_macro!(); //~ ERROR: macro unstable_macro! is unstable } diff --git a/src/test/compile-fail/match-byte-array-patterns-2.rs b/src/test/compile-fail/match-byte-array-patterns-2.rs index ad7e931a0ec9..abb770df107f 100644 --- a/src/test/compile-fail/match-byte-array-patterns-2.rs +++ b/src/test/compile-fail/match-byte-array-patterns-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns, slice_patterns)] - fn main() { let buf = &[0, 1, 2, 3]; diff --git a/src/test/compile-fail/match-byte-array-patterns.rs b/src/test/compile-fail/match-byte-array-patterns.rs index 1ff07eae1c9c..9db4319b7868 100644 --- a/src/test/compile-fail/match-byte-array-patterns.rs +++ b/src/test/compile-fail/match-byte-array-patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns, slice_patterns)] +#![feature(slice_patterns)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/compile-fail/match-privately-empty.rs b/src/test/compile-fail/match-privately-empty.rs index 3affb1c03e95..e18c7d77ce36 100644 --- a/src/test/compile-fail/match-privately-empty.rs +++ b/src/test/compile-fail/match-privately-empty.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] +#![feature(exhaustive_patterns)] mod private { pub struct Private { diff --git a/src/test/compile-fail/match-range-fail.rs b/src/test/compile-fail/match-range-fail.rs index 355ff6404cea..f89b3e39390d 100644 --- a/src/test/compile-fail/match-range-fail.rs +++ b/src/test/compile-fail/match-range-fail.rs @@ -15,7 +15,6 @@ fn main() { //~^^ ERROR only char and numeric types are allowed in range //~| start type: &'static str //~| end type: &'static str - //~| ERROR non-reference pattern used to match a reference match "wow" { 10 ... "what" => () @@ -23,7 +22,6 @@ fn main() { //~^^ ERROR only char and numeric types are allowed in range //~| start type: {integer} //~| end type: &'static str - //~| ERROR non-reference pattern used to match a reference match 5 { 'c' ... 100 => { } diff --git a/src/test/compile-fail/match-ref-ice.rs b/src/test/compile-fail/match-ref-ice.rs index 1cdbba17f658..cb8f8fad532f 100644 --- a/src/test/compile-fail/match-ref-ice.rs +++ b/src/test/compile-fail/match-ref-ice.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] #![deny(unreachable_patterns)] // The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose diff --git a/src/test/compile-fail/match-slice-patterns.rs b/src/test/compile-fail/match-slice-patterns.rs index fd4bd1c7b944..a8ec95da3d87 100644 --- a/src/test/compile-fail/match-slice-patterns.rs +++ b/src/test/compile-fail/match-slice-patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns, slice_patterns)] +#![feature(slice_patterns)] fn check(list: &[Option<()>]) { match list { diff --git a/src/test/compile-fail/match-vec-fixed.rs b/src/test/compile-fail/match-vec-fixed.rs index dd9379c756d1..05971d70167b 100644 --- a/src/test/compile-fail/match-vec-fixed.rs +++ b/src/test/compile-fail/match-vec-fixed.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] #![deny(unreachable_patterns)] fn a() { diff --git a/src/test/compile-fail/match-vec-mismatch-2.rs b/src/test/compile-fail/match-vec-mismatch-2.rs index 375d855d1fd3..52c5375f4e7d 100644 --- a/src/test/compile-fail/match-vec-mismatch-2.rs +++ b/src/test/compile-fail/match-vec-mismatch-2.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - fn main() { match () { [()] => { } diff --git a/src/test/compile-fail/match-vec-mismatch.rs b/src/test/compile-fail/match-vec-mismatch.rs index 998c11979953..d737aa0029bf 100644 --- a/src/test/compile-fail/match-vec-mismatch.rs +++ b/src/test/compile-fail/match-vec-mismatch.rs @@ -19,7 +19,7 @@ fn main() { // Note that this one works with default binding modes. match &[0, 1, 2] { - [..] => {} //~ ERROR non-reference pattern used to match a reference + [..] => {} }; match &[0, 1, 2] { diff --git a/src/test/compile-fail/match-vec-unreachable.rs b/src/test/compile-fail/match-vec-unreachable.rs index 472b054b0877..d6e3fdbe0884 100644 --- a/src/test/compile-fail/match-vec-unreachable.rs +++ b/src/test/compile-fail/match-vec-unreachable.rs @@ -10,7 +10,6 @@ #![feature(slice_patterns)] #![deny(unreachable_patterns)] -#![allow(unused_variables)] fn main() { let x: Vec<(isize, isize)> = Vec::new(); diff --git a/src/test/compile-fail/missing-main.rs b/src/test/compile-fail/missing-main.rs index 4bfdaf69480e..2788a5c2d585 100644 --- a/src/test/compile-fail/missing-main.rs +++ b/src/test/compile-fail/missing-main.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:main function not found +// error-pattern: `main` function not found fn mian() { } diff --git a/src/test/compile-fail/move-guard-same-consts.rs b/src/test/compile-fail/move-guard-same-consts.rs new file mode 100644 index 000000000000..05fe48e0199d --- /dev/null +++ b/src/test/compile-fail/move-guard-same-consts.rs @@ -0,0 +1,35 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// #47295: We used to have a hack of special-casing adjacent amtch +// arms whose patterns were composed solely of constants to not have +// them linked in the cfg. +// +// THis was broken for various reasons. In particular, that hack was +// originally authored under the assunption that other checks +// elsewhere would ensure that the two patterns did not overlap. But +// that assumption did not hold, at least not in the long run (namely, +// overlapping patterns were turned into warnings rather than errors). + +#![feature(box_syntax)] + +fn main() { + let x: Box<_> = box 1; + + let v = (1, 2); + + match v { + (1, 2) if take(x) => (), + (1, 2) if take(x) => (), //~ ERROR use of moved value: `x` + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/src/test/compile-fail/move-out-of-slice-1.rs b/src/test/compile-fail/move-out-of-slice-1.rs index 9ca9e0984e47..5efbef549ddc 100644 --- a/src/test/compile-fail/move-out-of-slice-1.rs +++ b/src/test/compile-fail/move-out-of-slice-1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns, box_patterns)] +#![feature(box_patterns)] struct A; diff --git a/src/test/compile-fail/mutable-enum-indirect.rs b/src/test/compile-fail/mutable-enum-indirect.rs index cafcabe6279b..9107745b0e9c 100644 --- a/src/test/compile-fail/mutable-enum-indirect.rs +++ b/src/test/compile-fail/mutable-enum-indirect.rs @@ -24,5 +24,6 @@ fn bar(_: T) {} fn main() { let x = Foo::A(NoSync); - bar(&x); //~ ERROR `NoSync: std::marker::Sync` is not satisfied + bar(&x); + //~^ ERROR `NoSync` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/mutexguard-sync.rs b/src/test/compile-fail/mutexguard-sync.rs index 861714720c57..2d4b50eb7b23 100644 --- a/src/test/compile-fail/mutexguard-sync.rs +++ b/src/test/compile-fail/mutexguard-sync.rs @@ -18,5 +18,6 @@ fn main() { let m = Mutex::new(Cell::new(0i32)); let guard = m.lock().unwrap(); - test_sync(guard); //~ ERROR the trait bound + test_sync(guard); + //~^ ERROR `std::cell::Cell` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/never-assign-dead-code.rs b/src/test/compile-fail/never-assign-dead-code.rs index 1e0cc0f5357f..4e987d1ddce5 100644 --- a/src/test/compile-fail/never-assign-dead-code.rs +++ b/src/test/compile-fail/never-assign-dead-code.rs @@ -10,7 +10,7 @@ // Test that an assignment of type ! makes the rest of the block dead code. -#![feature(never_type, rustc_attrs)] +#![feature(rustc_attrs)] #![warn(unused)] #[rustc_error] diff --git a/src/test/compile-fail/never-assign-wrong-type.rs b/src/test/compile-fail/never-assign-wrong-type.rs index c0dd2cab749f..8c2de7d68d3d 100644 --- a/src/test/compile-fail/never-assign-wrong-type.rs +++ b/src/test/compile-fail/never-assign-wrong-type.rs @@ -10,7 +10,6 @@ // Test that we can't use another type in place of ! -#![feature(never_type)] #![deny(warnings)] fn main() { diff --git a/src/test/compile-fail/no_share-enum.rs b/src/test/compile-fail/no_share-enum.rs index ae9a25a95b4e..77a7012b3b03 100644 --- a/src/test/compile-fail/no_share-enum.rs +++ b/src/test/compile-fail/no_share-enum.rs @@ -22,5 +22,5 @@ fn bar(_: T) {} fn main() { let x = Foo::A(NoSync); bar(x); - //~^ ERROR `NoSync: std::marker::Sync` is not satisfied + //~^ ERROR `NoSync` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/no_share-struct.rs b/src/test/compile-fail/no_share-struct.rs index d64d37a2f6c3..34e43e9f2aae 100644 --- a/src/test/compile-fail/no_share-struct.rs +++ b/src/test/compile-fail/no_share-struct.rs @@ -20,5 +20,5 @@ fn bar(_: T) {} fn main() { let x = Foo { a: 5 }; bar(x); - //~^ ERROR `Foo: std::marker::Sync` is not satisfied + //~^ ERROR `Foo` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/not-clone-closure.rs b/src/test/compile-fail/not-clone-closure.rs index 2a30dc4fdd49..967cb3610ca5 100644 --- a/src/test/compile-fail/not-clone-closure.rs +++ b/src/test/compile-fail/not-clone-closure.rs @@ -10,8 +10,6 @@ // Check that closures do not implement `Clone` if their environment is not `Clone`. -#![feature(clone_closures)] - struct S(i32); fn main() { diff --git a/src/test/compile-fail/not-copy-closure.rs b/src/test/compile-fail/not-copy-closure.rs index 271e6d5fc90f..10567c5c961a 100644 --- a/src/test/compile-fail/not-copy-closure.rs +++ b/src/test/compile-fail/not-copy-closure.rs @@ -10,9 +10,6 @@ // Check that closures do not implement `Copy` if their environment is not `Copy`. -#![feature(copy_closures)] -#![feature(clone_closures)] - fn main() { let mut a = 5; let hello = || { diff --git a/src/test/compile-fail/not-sync.rs b/src/test/compile-fail/not-sync.rs index 12c292791789..a383244f415c 100644 --- a/src/test/compile-fail/not-sync.rs +++ b/src/test/compile-fail/not-sync.rs @@ -16,17 +16,17 @@ fn test() {} fn main() { test::>(); - //~^ ERROR `std::cell::Cell: std::marker::Sync` is not satisfied + //~^ ERROR `std::cell::Cell` cannot be shared between threads safely [E0277] test::>(); - //~^ ERROR `std::cell::RefCell: std::marker::Sync` is not satisfied + //~^ ERROR `std::cell::RefCell` cannot be shared between threads safely [E0277] test::>(); - //~^ ERROR `std::rc::Rc: std::marker::Sync` is not satisfied + //~^ ERROR `std::rc::Rc` cannot be shared between threads safely [E0277] test::>(); - //~^ ERROR `std::rc::Weak: std::marker::Sync` is not satisfied + //~^ ERROR `std::rc::Weak` cannot be shared between threads safely [E0277] test::>(); - //~^ ERROR `std::sync::mpsc::Receiver: std::marker::Sync` is not satisfied + //~^ ERROR `std::sync::mpsc::Receiver` cannot be shared between threads safely [E0277] test::>(); - //~^ ERROR `std::sync::mpsc::Sender: std::marker::Sync` is not satisfied + //~^ ERROR `std::sync::mpsc::Sender` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/phantom-oibit.rs b/src/test/compile-fail/phantom-oibit.rs index e36c4835ca1c..51e7d5da98f4 100644 --- a/src/test/compile-fail/phantom-oibit.rs +++ b/src/test/compile-fail/phantom-oibit.rs @@ -28,11 +28,13 @@ struct Nested(T); fn is_zen(_: T) {} fn not_sync(x: Guard) { - is_zen(x) //~ error: `T: std::marker::Sync` is not satisfied + is_zen(x) + //~^ ERROR `T` cannot be shared between threads safely [E0277] } fn nested_not_sync(x: Nested>) { - is_zen(x) //~ error: `T: std::marker::Sync` is not satisfied + is_zen(x) + //~^ ERROR `T` cannot be shared between threads safely [E0277] } fn main() {} diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs index cc9eed7e6542..6eeb14638e75 100644 --- a/src/test/compile-fail/private-in-public-warn.rs +++ b/src/test/compile-fail/private-in-public-warn.rs @@ -58,7 +58,6 @@ mod traits { pub trait PubTr {} pub type Alias = T; //~ ERROR private trait `traits::PrivTr` in public interface - //~^ WARNING bounds on generic parameters are ignored //~| WARNING hard error pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error @@ -85,7 +84,6 @@ mod traits_where { pub type Alias where T: PrivTr = T; //~^ ERROR private trait `traits_where::PrivTr` in public interface //~| WARNING hard error - //~| WARNING where clauses are ignored in type aliases pub trait Tr2 where T: PrivTr {} //~^ ERROR private trait `traits_where::PrivTr` in public interface //~| WARNING hard error diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs index 351dc6b776b2..5af8b063c162 100644 --- a/src/test/compile-fail/private-inferred-type.rs +++ b/src/test/compile-fail/private-inferred-type.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(associated_consts)] -#![feature(conservative_impl_trait)] #![feature(decl_macro)] #![allow(private_in_public)] diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs index eb8c40a7dd5e..1842790a1405 100644 --- a/src/test/compile-fail/private-type-in-interface.rs +++ b/src/test/compile-fail/private-type-in-interface.rs @@ -10,7 +10,6 @@ // aux-build:private-inferred-type.rs -#![feature(conservative_impl_trait)] #![allow(warnings)] extern crate private_inferred_type as ext; diff --git a/src/test/compile-fail/range_inclusive_gate.rs b/src/test/compile-fail/range_inclusive_gate.rs deleted file mode 100644 index 5b063dc1137c..000000000000 --- a/src/test/compile-fail/range_inclusive_gate.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Make sure that #![feature(inclusive_range)] is required. - -#![feature(inclusive_range_syntax)] -// #![feature(inclusive_range)] - -pub fn main() { - let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ..= { use std::intrinsics; 2 }; - //~^ ERROR use of unstable library feature 'inclusive_range' - //~| ERROR core_intrinsics - //~| ERROR core_intrinsics -} diff --git a/src/test/compile-fail/range_traits-1.rs b/src/test/compile-fail/range_traits-1.rs index f1ea8b04e5ac..7645dbb1a6de 100644 --- a/src/test/compile-fail/range_traits-1.rs +++ b/src/test/compile-fail/range_traits-1.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(inclusive_range)] - use std::ops::*; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] diff --git a/src/test/compile-fail/range_traits-6.rs b/src/test/compile-fail/range_traits-6.rs index 7c62711feaee..f9510b5061ca 100644 --- a/src/test/compile-fail/range_traits-6.rs +++ b/src/test/compile-fail/range_traits-6.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(inclusive_range)] - use std::ops::*; #[derive(Copy, Clone)] //~ ERROR Copy diff --git a/src/test/compile-fail/range_traits-7.rs b/src/test/compile-fail/range_traits-7.rs index b6fec773a777..871b55b85cf8 100644 --- a/src/test/compile-fail/range_traits-7.rs +++ b/src/test/compile-fail/range_traits-7.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs, inclusive_range)] +#![feature(rustc_attrs)] use std::ops::*; diff --git a/src/test/compile-fail/recursive-types-are-not-uninhabited.rs b/src/test/compile-fail/recursive-types-are-not-uninhabited.rs index f8d6c3de2ab0..fa9366970722 100644 --- a/src/test/compile-fail/recursive-types-are-not-uninhabited.rs +++ b/src/test/compile-fail/recursive-types-are-not-uninhabited.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//#![feature(never_type)] - struct R<'a> { r: &'a R<'a>, } diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19552.rs b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs index 8e83177090bb..3401dd1becdd 100644 --- a/src/test/compile-fail/regions-pattern-typing-issue-19552.rs +++ b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - fn assert_static(_t: T) {} fn main() { diff --git a/src/test/ui/feature-gate-copy-closures.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs similarity index 70% rename from src/test/ui/feature-gate-copy-closures.rs rename to src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs index b11b09eb9fd9..49f5621de1b2 100644 --- a/src/test/ui/feature-gate-copy-closures.rs +++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let a = 5; - let hello = || { - println!("Hello {}", a); - }; - - let b = hello; - let c = hello; //~ ERROR use of moved value: `hello` [E0382] +fn main() -> i32 { +//~^ ERROR `main` has invalid return type `i32` +//~| NOTE `main` can only return types that implement `std::process::Termination` +//~| HELP consider using `()`, or a `Result` + 0 } diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs index e87e0ceebf1b..b5f5472b4929 100644 --- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs +++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - struct ReturnType {} -fn main() -> ReturnType { //~ ERROR `ReturnType: std::process::Termination` is not satisfied +fn main() -> ReturnType { //~ ERROR `main` has invalid return type `ReturnType` ReturnType {} } diff --git a/src/test/ui/feature-gate-never_type.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs similarity index 53% rename from src/test/ui/feature-gate-never_type.rs rename to src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs index 11b9f412957e..e48d989c01d6 100644 --- a/src/test/ui/feature-gate-never_type.rs +++ b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs @@ -8,21 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that ! errors when used in illegal positions with feature(never_type) disabled +#![feature(non_exhaustive)] -trait Foo { - type Wub; -} - -type Ma = (u32, !, i32); //~ ERROR type is experimental -type Meeshka = Vec; //~ ERROR type is experimental -type Mow = &fn(!) -> !; //~ ERROR type is experimental -type Skwoz = &mut !; //~ ERROR type is experimental - -impl Foo for Meeshka { - type Wub = !; //~ ERROR type is experimental -} - -fn main() { +#[non_exhaustive(anything)] +//~^ ERROR attribute should be empty [E0911] +struct Foo; + +#[non_exhaustive] +//~^ ERROR attribute can only be applied to a struct or enum [E0910] +trait Bar { } + +#[non_exhaustive] +//~^ ERROR attribute can only be applied to a struct or enum [E0910] +union Baz { + f1: u16, + f2: u16 } +fn main() { } diff --git a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs new file mode 100644 index 000000000000..57e4bb76a6ce --- /dev/null +++ b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs @@ -0,0 +1,82 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// min-llvm-version 5.0 +// ignore-emscripten + +// Test that the simd_reduce_{op} intrinsics produce ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + + +extern "platform-intrinsic" { + fn simd_reduce_add_ordered(x: T, y: U) -> U; + fn simd_reduce_mul_ordered(x: T, y: U) -> U; + fn simd_reduce_and(x: T) -> U; + fn simd_reduce_or(x: T) -> U; + fn simd_reduce_xor(x: T) -> U; + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +fn main() { + let x = u32x4(0, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_reduce_add_ordered(z, 0_f32); + simd_reduce_mul_ordered(z, 1_f32); + + simd_reduce_add_ordered(z, 2_f32); + //~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0 + simd_reduce_mul_ordered(z, 3_f32); + //~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0 + + let _: f32 = simd_reduce_and(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + let _: f32 = simd_reduce_or(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + let _: f32 = simd_reduce_xor(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + + let _: f32 = simd_reduce_and(z); + //~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` + let _: f32 = simd_reduce_or(z); + //~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` + let _: f32 = simd_reduce_xor(z); + //~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` + + let _: bool = simd_reduce_all(z); + //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` + let _: bool = simd_reduce_any(z); + //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` + + foo(0_f32); + } +} + +#[inline(never)] +unsafe fn foo(x: f32) { + let z = f32x4(0.0, 0.0, 0.0, 0.0); + simd_reduce_add_ordered(z, x); + //~^ ERROR accumulator of simd_reduce_add_ordered is not a constant + simd_reduce_mul_ordered(z, x); + //~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant +} diff --git a/src/test/compile-fail/simd-intrinsic-generic-select.rs b/src/test/compile-fail/simd-intrinsic-generic-select.rs new file mode 100644 index 000000000000..d74d6815d5f5 --- /dev/null +++ b/src/test/compile-fail/simd-intrinsic-generic-select.rs @@ -0,0 +1,56 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the simd_select intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq)] +struct b8x8(pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8); + +extern "platform-intrinsic" { + fn simd_select(x: T, a: U, b: U) -> U; +} + +fn main() { + let m4 = b8x4(0, 0, 0, 0); + let m8 = b8x8(0, 0, 0, 0, 0, 0, 0, 0); + let x = u32x4(0, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_select(m4, x, x); + + simd_select(m8, x, x); + //~^ ERROR mismatched lengths: mask length `8` != other vector length `4` + + simd_select(x, x, x); + //~^ ERROR mask element type is `u32`, expected `i_` + + simd_select(z, z, z); + //~^ ERROR mask element type is `f32`, expected `i_` + } +} diff --git a/src/test/compile-fail/struct-pat-derived-error.rs b/src/test/compile-fail/struct-pat-derived-error.rs index f525ec373753..d3130c4e831f 100644 --- a/src/test/compile-fail/struct-pat-derived-error.rs +++ b/src/test/compile-fail/struct-pat-derived-error.rs @@ -16,10 +16,8 @@ struct a { impl a { fn foo(&self) { let a { x, y } = self.d; //~ ERROR no field `d` on type `&a` - //~^ ERROR struct `a` does not have a field named `x` - //~^^ ERROR struct `a` does not have a field named `y` - //~^^^ ERROR pattern does not mention field `b` - //~^^^^ ERROR pattern does not mention field `c` + //~^ ERROR struct `a` does not have fields named `x`, `y` + //~| ERROR pattern does not mention fields `b`, `c` } } diff --git a/src/test/compile-fail/synthetic-param.rs b/src/test/compile-fail/synthetic-param.rs index a9762e383fe4..337cae1369ee 100644 --- a/src/test/compile-fail/synthetic-param.rs +++ b/src/test/compile-fail/synthetic-param.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs, rustc_attrs)] +#![feature(rustc_attrs)] fn func<#[rustc_synthetic] T>(_: T) {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs index cdf787a60ad4..c829ba3dcc35 100644 --- a/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs @@ -43,11 +43,11 @@ fn is_sync() {} fn main() { is_sync::(); is_sync::(); - //~^ ERROR `MyNotSync: std::marker::Sync` is not satisfied + //~^ ERROR `MyNotSync` cannot be shared between threads safely [E0277] is_sync::(); - //~^ ERROR `std::cell::UnsafeCell: std::marker::Sync` is not satisfied + //~^ ERROR `std::cell::UnsafeCell` cannot be shared between threads safely [E0277] is_sync::(); - //~^ ERROR `Managed: std::marker::Sync` is not satisfied + //~^ ERROR `Managed` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs index f0172777cdab..fcfc8574b213 100644 --- a/src/test/compile-fail/typeck-unsafe-always-share.rs +++ b/src/test/compile-fail/typeck-unsafe-always-share.rs @@ -27,16 +27,16 @@ fn test(s: T) {} fn main() { let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0)}); test(us); - //~^ ERROR `std::cell::UnsafeCell>: std::marker::Sync` is not satisfied + //~^ ERROR `std::cell::UnsafeCell>` cannot be shared between threads safely let uns = UnsafeCell::new(NoSync); test(uns); - //~^ ERROR `std::cell::UnsafeCell: std::marker::Sync` is not satisfied + //~^ ERROR `std::cell::UnsafeCell` cannot be shared between threads safely [E0277] let ms = MySync{u: uns}; test(ms); - //~^ ERROR `std::cell::UnsafeCell: std::marker::Sync` is not satisfied + //~^ ERROR `std::cell::UnsafeCell` cannot be shared between threads safely [E0277] test(NoSync); - //~^ ERROR `NoSync: std::marker::Sync` is not satisfied + //~^ ERROR `NoSync` cannot be shared between threads safely [E0277] } diff --git a/src/test/compile-fail/underscore-lifetime-binders.rs b/src/test/compile-fail/underscore-lifetime-binders.rs index 99b6e036f33e..eb00ab5f67af 100644 --- a/src/test/compile-fail/underscore-lifetime-binders.rs +++ b/src/test/compile-fail/underscore-lifetime-binders.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(underscore_lifetimes)] - struct Foo<'a>(&'a u8); struct Baz<'a>(&'_ &'a u8); //~ ERROR missing lifetime specifier diff --git a/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs b/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs index a1c4e4a1fd93..b36c8eb324e1 100644 --- a/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs +++ b/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(underscore_lifetimes)] - fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } //~ ERROR lifetime mismatch fn main() {} diff --git a/src/test/compile-fail/uninhabited-irrefutable.rs b/src/test/compile-fail/uninhabited-irrefutable.rs index 4755fdd4fd5e..72b0afa6bd3e 100644 --- a/src/test/compile-fail/uninhabited-irrefutable.rs +++ b/src/test/compile-fail/uninhabited-irrefutable.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] +#![feature(exhaustive_patterns)] mod foo { pub struct SecretlyEmpty { diff --git a/src/test/compile-fail/uninhabited-matches-feature-gated.rs b/src/test/compile-fail/uninhabited-matches-feature-gated.rs index 0c3ea53a903a..1d3f8ff12d86 100644 --- a/src/test/compile-fail/uninhabited-matches-feature-gated.rs +++ b/src/test/compile-fail/uninhabited-matches-feature-gated.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - enum Void {} fn main() { diff --git a/src/test/compile-fail/uninhabited-patterns.rs b/src/test/compile-fail/uninhabited-patterns.rs index 4c894b0bdd3d..e130df5c845b 100644 --- a/src/test/compile-fail/uninhabited-patterns.rs +++ b/src/test/compile-fail/uninhabited-patterns.rs @@ -9,9 +9,9 @@ // except according to those terms. #![feature(box_patterns)] -#![feature(slice_patterns)] #![feature(box_syntax)] -#![feature(never_type)] +#![feature(exhaustive_patterns)] +#![feature(slice_patterns)] #![deny(unreachable_patterns)] mod foo { diff --git a/src/test/compile-fail/unreachable-loop-patterns.rs b/src/test/compile-fail/unreachable-loop-patterns.rs index 6147692658f9..dca79bdfb87f 100644 --- a/src/test/compile-fail/unreachable-loop-patterns.rs +++ b/src/test/compile-fail/unreachable-loop-patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] +#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/compile-fail/unreachable-try-pattern.rs b/src/test/compile-fail/unreachable-try-pattern.rs index 46ea4a06a3bd..0caf7d512349 100644 --- a/src/test/compile-fail/unreachable-try-pattern.rs +++ b/src/test/compile-fail/unreachable-try-pattern.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type, rustc_attrs)] +#![feature(exhaustive_patterns, rustc_attrs)] #![warn(unreachable_code)] #![warn(unreachable_patterns)] diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index eb5798dc7cc4..32d775168692 100644 --- a/src/test/debuginfo/lexical-scope-with-macro.rs +++ b/src/test/debuginfo/lexical-scope-with-macro.rs @@ -9,6 +9,7 @@ // except according to those terms. // min-lldb-version: 310 +// ignore-macos FIXME #48807 // compile-flags:-g -Zdebug-macros diff --git a/src/test/incremental/extern_static/issue-49153.rs b/src/test/incremental/extern_static/issue-49153.rs new file mode 100644 index 000000000000..e0538e09c647 --- /dev/null +++ b/src/test/incremental/extern_static/issue-49153.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// https://github.com/rust-lang/rust/issues/49153 + +// revisions:rpass1 rpass2 + +extern "C" { + pub static __ImageBase: u8; +} + +pub static FOO: &'static u8 = unsafe { &__ImageBase }; + +fn main() {} diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index abe0586efcd7..6c4e11be1e43 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -22,7 +22,6 @@ #![allow(warnings)] -#![feature(conservative_impl_trait)] #![feature(intrinsics)] #![feature(linkage)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index e66e239b33c9..fb63aa857aa3 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -23,7 +23,6 @@ #![allow(warnings)] #![feature(rustc_attrs)] #![crate_type="rlib"] -#![feature(inclusive_range_syntax)] // Change simple index --------------------------------------------------------- #[cfg(cfail1)] diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 851b13c70551..2f49500c3910 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -49,7 +49,7 @@ pub fn add_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,TypeckTables")] + except="HirBody,TypeckTables,MirValidated")] #[rustc_clean(cfg="cfail3")] pub fn add_type() { let _x: u32 = 2u32; diff --git a/src/test/ui/pat-slice-old-style.rs b/src/test/incremental/issue-49043.rs similarity index 52% rename from src/test/ui/pat-slice-old-style.rs rename to src/test/incremental/issue-49043.rs index 4ff1e94b0872..118027b190e2 100644 --- a/src/test/ui/pat-slice-old-style.rs +++ b/src/test/incremental/issue-49043.rs @@ -8,20 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] +// Regression test for hashing involving canonical variables. In this +// test -- which has an intensional error -- the type of the value +// being dropped winds up including a type variable. Canonicalization +// would then produce a `?0` which -- in turn -- triggered an ICE in +// hashing. -// NB: this test was introduced in #23121 and will have to change when default match binding modes -// stabilizes. - -fn slice_pat(x: &[u8]) { - // OLD! - match x { - [a, b..] => {}, - //~^ ERROR non-reference pattern used to match a reference - _ => panic!(), - } -} +// revisions:cfail1 fn main() { - slice_pat("foo".as_bytes()); + println!("Hello, world! {}",*thread_rng().choose(&[0, 1, 2, 3]).unwrap()); + //[cfail1]~^ ERROR cannot find function `thread_rng` } diff --git a/src/test/ui/feature-gate-i128_type.rs b/src/test/incremental/static_refering_to_other_static/issue-49081.rs similarity index 66% rename from src/test/ui/feature-gate-i128_type.rs rename to src/test/incremental/static_refering_to_other_static/issue-49081.rs index ddb49a3e5d92..6345b456523e 100644 --- a/src/test/ui/feature-gate-i128_type.rs +++ b/src/test/incremental/static_refering_to_other_static/issue-49081.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn test2() { - 0i128; //~ ERROR 128-bit integers are not stable -} +// https://github.com/rust-lang/rust/issues/49081 -fn test2_2() { - 0u128; //~ ERROR 128-bit integers are not stable -} +// revisions:rpass1 rpass2 +pub static A: i32 = 42; +pub static B: &i32 = &A; + +fn main() {} diff --git a/src/test/incremental/static_refering_to_other_static2/issue.rs b/src/test/incremental/static_refering_to_other_static2/issue.rs new file mode 100644 index 000000000000..558478668951 --- /dev/null +++ b/src/test/incremental/static_refering_to_other_static2/issue.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// revisions:rpass1 rpass2 + +#[cfg(rpass1)] +pub static A: i32 = 42; +#[cfg(rpass2)] +pub static A: i32 = 43; + +pub static B: &i32 = &A; + +fn main() {} diff --git a/src/test/incremental/static_stable_hash/issue-49301.rs b/src/test/incremental/static_stable_hash/issue-49301.rs new file mode 100644 index 000000000000..3e421b27c11b --- /dev/null +++ b/src/test/incremental/static_stable_hash/issue-49301.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// https://github.com/rust-lang/rust/issues/49081 + +// revisions:rpass1 rpass2 + +#[cfg(rpass1)] +pub static A: &str = "hello"; +#[cfg(rpass2)] +pub static A: &str = "xxxxx"; + +#[cfg(rpass1)] +fn main() { + assert_eq!(A, "hello"); +} + +#[cfg(rpass2)] +fn main() { + assert_eq!(A, "xxxxx"); +} diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index 321c05c49035..3c236ddcf040 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -23,6 +23,8 @@ // tend to be absent in simple code, so subtle breakage in them can // leave a quite hard-to-find trail of destruction. +// ignore-tidy-linelength + fn main() { let nodrop_x = false; let nodrop_y; @@ -46,6 +48,7 @@ fn main() { // _2 = move _3; // StorageDead(_3); // StorageLive(_4); +// UserAssertTy(Canonical { variables: Slice([]), value: std::option::Option> }, _4); // _4 = std::option::Option>::None; // StorageLive(_5); // StorageLive(_6); diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index 405864aba943..d621cdb4d58f 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -36,7 +36,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _2: &'21_1rs D; // ... // let mut _3: (); -// let mut _4: [closure@NodeId(22) r:&'21_1rs D]; +// let mut _4: [closure@NodeId(22) r:&'19s D]; // let mut _5: &'21_1rs D; // bb0: { // StorageLive(_1); @@ -54,6 +54,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb2: { +// EndRegion('19s); // StorageDead(_4); // _0 = (); // EndRegion('21_1rs); @@ -61,6 +62,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { +// EndRegion('19s); // EndRegion('21_1rs); // drop(_1) -> bb1; // } @@ -72,7 +74,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'21_1rs D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'19s D]) -> i32 { // let mut _0: i32; // let mut _2: i32; // diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs index 69c5cdccf49d..e189f2e3b34a 100644 --- a/src/test/mir-opt/end_region_destruction_extents_1.rs +++ b/src/test/mir-opt/end_region_destruction_extents_1.rs @@ -14,7 +14,6 @@ // A scenario with significant destruction code extents (which have // suffix "dce" in current `-Z identify_regions` rendering). -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] fn main() { diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs index 1752445a141c..d7586b1aa4b1 100644 --- a/src/test/mir-opt/lower_128bit_debug_test.rs +++ b/src/test/mir-opt/lower_128bit_debug_test.rs @@ -15,7 +15,6 @@ // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes -#![feature(i128_type)] #![feature(const_fn)] static TEST_SIGNED: i128 = const_signed(-222); diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs index 4058eaef9b0a..341682debeb3 100644 --- a/src/test/mir-opt/lower_128bit_test.rs +++ b/src/test/mir-opt/lower_128bit_test.rs @@ -15,7 +15,6 @@ // compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -#![feature(i128_type)] #![feature(const_fn)] static TEST_SIGNED: i128 = const_signed(-222); diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs index f69c51c3562d..92e42a73bbb6 100644 --- a/src/test/mir-opt/nll/reborrow-basic.rs +++ b/src/test/mir-opt/nll/reborrow-basic.rs @@ -28,9 +28,9 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#7r | {bb0[6..=14]} +// | '_#7r | {bb0[4], bb0[8..=17]} // ... -// | '_#9r | {bb0[11..=14]} +// | '_#9r | {bb0[10], bb0[14..=17]} // ... // let _2: &'_#7r mut i32; // ... diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs index 482b69a59ddb..fa5f62f89f63 100644 --- a/src/test/mir-opt/uniform_array_move_out.rs +++ b/src/test/mir-opt/uniform_array_move_out.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax, slice_patterns, advanced_slice_patterns)] +#![feature(box_syntax)] +#![feature(slice_patterns)] fn move_out_from_end() { let a = [box 1, box 2]; diff --git a/src/test/parse-fail/assoc-oddities-1.rs b/src/test/parse-fail/assoc-oddities-1.rs index 5c0c47de58ae..63408b76b153 100644 --- a/src/test/parse-fail/assoc-oddities-1.rs +++ b/src/test/parse-fail/assoc-oddities-1.rs @@ -13,10 +13,9 @@ fn that_odd_parse() { // following lines below parse and must not fail x = if c { a } else { b }(); - x <- if c { a } else { b }[n]; x = if true { 1 } else { 0 } as *mut _; // however this does not parse and probably should fail to retain compat? - // NB: `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=` or `<-` + // NB: `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=` // see assoc-oddities-2 and assoc-oddities-3 ..if c { a } else { b }[n]; //~ ERROR expected one of } diff --git a/src/test/parse-fail/issue-32501.rs b/src/test/parse-fail/issue-32501.rs index f29c1fa27940..21db2f505170 100644 --- a/src/test/parse-fail/issue-32501.rs +++ b/src/test/parse-fail/issue-32501.rs @@ -16,7 +16,5 @@ fn main() { let _ = 0; let mut b = 0; let mut _b = 0; - let mut _ = 0; //~ ERROR expected identifier, found `_` - //~^ NOTE `_` is a wildcard pattern, not an identifier - //~| NOTE expected identifier + let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_` } diff --git a/src/test/parse-fail/range_inclusive.rs b/src/test/parse-fail/range_inclusive.rs index cc32b9903b5a..2aa7d6d6cd79 100644 --- a/src/test/parse-fail/range_inclusive.rs +++ b/src/test/parse-fail/range_inclusive.rs @@ -10,8 +10,6 @@ // Make sure that inclusive ranges with no end point don't parse. -#![feature(inclusive_range_syntax, inclusive_range)] - pub fn main() { for _ in 1..= {} //~ERROR inclusive range with no end //~^HELP bounded at the end diff --git a/src/test/parse-fail/range_inclusive_dotdotdot.rs b/src/test/parse-fail/range_inclusive_dotdotdot.rs index a4c36a2f0ba8..fa6474717d3f 100644 --- a/src/test/parse-fail/range_inclusive_dotdotdot.rs +++ b/src/test/parse-fail/range_inclusive_dotdotdot.rs @@ -12,8 +12,6 @@ // Make sure that inclusive ranges with `...` syntax don't parse. -#![feature(inclusive_range_syntax, inclusive_range)] - use std::ops::RangeToInclusive; fn return_range_to() -> RangeToInclusive { diff --git a/src/test/parse-fail/range_inclusive_gate.rs b/src/test/parse-fail/range_inclusive_gate.rs deleted file mode 100644 index 6b6afc504e15..000000000000 --- a/src/test/parse-fail/range_inclusive_gate.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// gate-test-inclusive_range_syntax - -// Make sure that #![feature(inclusive_range_syntax)] is required. - -// #![feature(inclusive_range_syntax, inclusive_range)] - -macro_rules! m { - () => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental -} - -#[cfg(nope)] -fn f() {} -#[cfg(not(nope))] -fn f() { - for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental -} - -#[cfg(nope)] -macro_rules! n { () => {} } -#[cfg(not(nope))] -macro_rules! n { - () => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental -} - -macro_rules! o { - () => {{ - #[cfg(nope)] - fn g() {} - #[cfg(not(nope))] - fn g() { - for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental - } - - g(); - }} -} - -#[cfg(nope)] -macro_rules! p { () => {} } -#[cfg(not(nope))] -macro_rules! p { - () => {{ - #[cfg(nope)] - fn h() {} - #[cfg(not(nope))] - fn h() { - for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental - } - - h(); - }} -} - -pub fn main() { - for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental - for _ in ..=10 {} //~ ERROR inclusive range syntax is experimental - - f(); // not allowed in cfg'ed functions - - m!(); // not allowed in macros - n!(); // not allowed in cfg'ed macros - o!(); // not allowed in macros that output cfgs - p!(); // not allowed in cfg'ed macros that output cfgs -} diff --git a/src/test/parse-fail/raw-str-delim.rs b/src/test/parse-fail/raw-str-delim.rs index 3fc5f8aae187..8c0027287dec 100644 --- a/src/test/parse-fail/raw-str-delim.rs +++ b/src/test/parse-fail/raw-str-delim.rs @@ -11,5 +11,5 @@ // compile-flags: -Z parse-only static s: &'static str = - r#x"#"x# //~ ERROR found invalid character; only `#` is allowed in raw string delimitation + r#~"#"~# //~ ERROR found invalid character; only `#` is allowed in raw string delimitation ; diff --git a/src/test/parse-fail/recover-enum2.rs b/src/test/parse-fail/recover-enum2.rs index 49380a03e156..6fd32f842f13 100644 --- a/src/test/parse-fail/recover-enum2.rs +++ b/src/test/parse-fail/recover-enum2.rs @@ -39,5 +39,5 @@ fn main() { } } // still recover later - let bad_syntax = _; //~ ERROR: found `_` + let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_` } diff --git a/src/test/parse-fail/underscore-suffix-for-float.rs b/src/test/parse-fail/underscore-suffix-for-float.rs index df7d9aa374dc..8327217e6f28 100644 --- a/src/test/parse-fail/underscore-suffix-for-float.rs +++ b/src/test/parse-fail/underscore-suffix-for-float.rs @@ -9,5 +9,6 @@ // except according to those terms. fn main() { - let a = 42._; //~ ERROR unexpected token: `_` + let a = 42._; //~ ERROR expected identifier, found reserved identifier `_` + //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields } diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 17e6119f968a..b34e18520793 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -12,7 +12,6 @@ #![feature(custom_attribute)] #![feature(box_syntax)] -#![feature(placement_in_syntax)] #![feature(stmt_expr_attributes)] fn main() { } diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs index 27b9e27be438..c8c80b7759c9 100644 --- a/src/test/run-fail-fulldeps/qquote.rs +++ b/src/test/run-fail-fulldeps/qquote.rs @@ -24,6 +24,10 @@ use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; fn main() { + syntax::with_globals(|| run()); +} + +fn run() { let ps = syntax::parse::ParseSess::new(codemap::FilePathMapping::empty()); let mut resolver = syntax::ext::base::DummyResolver; let mut cx = syntax::ext::base::ExtCtxt::new( diff --git a/src/test/run-fail/adjust_never.rs b/src/test/run-fail/adjust_never.rs index ccdb1ca15bba..7a4b5e59eeb7 100644 --- a/src/test/run-fail/adjust_never.rs +++ b/src/test/run-fail/adjust_never.rs @@ -10,8 +10,6 @@ // Test that a variable of type ! can coerce to another type. -#![feature(never_type)] - // error-pattern:explicit fn main() { let x: ! = panic!(); diff --git a/src/test/run-fail/call-fn-never-arg.rs b/src/test/run-fail/call-fn-never-arg.rs index 95101e70db95..56454586bb95 100644 --- a/src/test/run-fail/call-fn-never-arg.rs +++ b/src/test/run-fail/call-fn-never-arg.rs @@ -12,7 +12,6 @@ // error-pattern:wowzers! -#![feature(never_type)] #![allow(unreachable_code)] fn foo(x: !) -> ! { diff --git a/src/test/run-fail/cast-never.rs b/src/test/run-fail/cast-never.rs index acd002494f4e..0155332c51d1 100644 --- a/src/test/run-fail/cast-never.rs +++ b/src/test/run-fail/cast-never.rs @@ -10,8 +10,6 @@ // Test that we can explicitly cast ! to another type -#![feature(never_type)] - // error-pattern:explicit fn main() { let x: ! = panic!(); diff --git a/src/test/run-fail/never-associated-type.rs b/src/test/run-fail/never-associated-type.rs index 345674f3f522..d9b8461a1d07 100644 --- a/src/test/run-fail/never-associated-type.rs +++ b/src/test/run-fail/never-associated-type.rs @@ -10,8 +10,6 @@ // Test that we can use ! as an associated type. -#![feature(never_type)] - // error-pattern:kapow! trait Foo { diff --git a/src/test/run-fail/never-type-arg.rs b/src/test/run-fail/never-type-arg.rs index 826ca3a08c0e..0fe10d43910b 100644 --- a/src/test/run-fail/never-type-arg.rs +++ b/src/test/run-fail/never-type-arg.rs @@ -12,8 +12,6 @@ // error-pattern:oh no! -#![feature(never_type)] - struct Wub; impl PartialEq for Wub { diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs index c1dd44a91765..863de85af88f 100644 --- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs +++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - // error-pattern:oh, dear fn main() -> ! { diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs index 8ce27c0a0625..0c6cb4de9567 100644 --- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs +++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs @@ -11,8 +11,6 @@ // must-compile-successfully // failure-status: 1 -#![feature(termination_trait)] - use std::io::{Error, ErrorKind}; fn main() -> Result<(), Box> { diff --git a/src/test/run-fail/simd-intrinsic-float-minmax.rs b/src/test/run-fail/simd-intrinsic-float-minmax.rs new file mode 100644 index 000000000000..f4fb8e12250b --- /dev/null +++ b/src/test/run-fail/simd-intrinsic-float-minmax.rs @@ -0,0 +1,57 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten +// min-llvm-version 6.0 +// error-pattern: panicked + +// Test that the simd_f{min,max} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fmin(x: T, y: T) -> T; + fn simd_fmax(x: T, y: T) -> T; +} + +fn main() { + let x = f32x4(1.0, 2.0, 3.0, 4.0); + let y = f32x4(2.0, 1.0, 4.0, 3.0); + let nan = ::std::f32::NAN; + let n = f32x4(nan, nan, nan, nan); + + unsafe { + let min0 = simd_fmin(x, y); + let min1 = simd_fmin(y, x); + assert_eq!(min0, min1); + let e = f32x4(1.0, 1.0, 3.0, 3.0); + assert_eq!(min0, e); + let minn = simd_fmin(x, n); + assert_eq!(minn, x); + let minn = simd_fmin(y, n); + assert_eq!(minn, y); + + // FIXME(49261) + let max0 = simd_fmax(x, y); + let max1 = simd_fmax(y, x); + assert_eq!(max0, max1); + let e = f32x4(2.0, 2.0, 4.0, 4.0); + assert_eq!(max0, e); + let maxn = simd_fmax(x, n); + assert_eq!(maxn, x); + let maxn = simd_fmax(y, n); + assert_eq!(maxn, y); + } +} diff --git a/src/test/run-make/a-b-a-linker-guard/Makefile b/src/test/run-make-fulldeps/a-b-a-linker-guard/Makefile similarity index 100% rename from src/test/run-make/a-b-a-linker-guard/Makefile rename to src/test/run-make-fulldeps/a-b-a-linker-guard/Makefile diff --git a/src/test/run-make/a-b-a-linker-guard/a.rs b/src/test/run-make-fulldeps/a-b-a-linker-guard/a.rs similarity index 100% rename from src/test/run-make/a-b-a-linker-guard/a.rs rename to src/test/run-make-fulldeps/a-b-a-linker-guard/a.rs diff --git a/src/test/run-make/a-b-a-linker-guard/b.rs b/src/test/run-make-fulldeps/a-b-a-linker-guard/b.rs similarity index 100% rename from src/test/run-make/a-b-a-linker-guard/b.rs rename to src/test/run-make-fulldeps/a-b-a-linker-guard/b.rs diff --git a/src/test/run-make/alloc-extern-crates/Makefile b/src/test/run-make-fulldeps/alloc-extern-crates/Makefile similarity index 100% rename from src/test/run-make/alloc-extern-crates/Makefile rename to src/test/run-make-fulldeps/alloc-extern-crates/Makefile diff --git a/src/test/run-make/alloc-extern-crates/fakealloc.rs b/src/test/run-make-fulldeps/alloc-extern-crates/fakealloc.rs similarity index 100% rename from src/test/run-make/alloc-extern-crates/fakealloc.rs rename to src/test/run-make-fulldeps/alloc-extern-crates/fakealloc.rs diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile b/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/Makefile similarity index 100% rename from src/test/run-make/allow-non-lint-warnings-cmdline/Makefile rename to src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/Makefile diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs b/src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/foo.rs similarity index 100% rename from src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs rename to src/test/run-make-fulldeps/allow-non-lint-warnings-cmdline/foo.rs diff --git a/src/test/run-make/allow-warnings-cmdline-stability/Makefile b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/Makefile similarity index 100% rename from src/test/run-make/allow-warnings-cmdline-stability/Makefile rename to src/test/run-make-fulldeps/allow-warnings-cmdline-stability/Makefile diff --git a/src/test/run-make/allow-warnings-cmdline-stability/bar.rs b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs similarity index 100% rename from src/test/run-make/allow-warnings-cmdline-stability/bar.rs rename to src/test/run-make-fulldeps/allow-warnings-cmdline-stability/bar.rs diff --git a/src/test/run-make/allow-warnings-cmdline-stability/foo.rs b/src/test/run-make-fulldeps/allow-warnings-cmdline-stability/foo.rs similarity index 100% rename from src/test/run-make/allow-warnings-cmdline-stability/foo.rs rename to src/test/run-make-fulldeps/allow-warnings-cmdline-stability/foo.rs diff --git a/src/test/run-make/archive-duplicate-names/Makefile b/src/test/run-make-fulldeps/archive-duplicate-names/Makefile similarity index 100% rename from src/test/run-make/archive-duplicate-names/Makefile rename to src/test/run-make-fulldeps/archive-duplicate-names/Makefile diff --git a/src/test/run-make/archive-duplicate-names/bar.c b/src/test/run-make-fulldeps/archive-duplicate-names/bar.c similarity index 100% rename from src/test/run-make/archive-duplicate-names/bar.c rename to src/test/run-make-fulldeps/archive-duplicate-names/bar.c diff --git a/src/test/run-make/archive-duplicate-names/bar.rs b/src/test/run-make-fulldeps/archive-duplicate-names/bar.rs similarity index 100% rename from src/test/run-make/archive-duplicate-names/bar.rs rename to src/test/run-make-fulldeps/archive-duplicate-names/bar.rs diff --git a/src/test/run-make/archive-duplicate-names/foo.c b/src/test/run-make-fulldeps/archive-duplicate-names/foo.c similarity index 100% rename from src/test/run-make/archive-duplicate-names/foo.c rename to src/test/run-make-fulldeps/archive-duplicate-names/foo.c diff --git a/src/test/run-make/archive-duplicate-names/foo.rs b/src/test/run-make-fulldeps/archive-duplicate-names/foo.rs similarity index 100% rename from src/test/run-make/archive-duplicate-names/foo.rs rename to src/test/run-make-fulldeps/archive-duplicate-names/foo.rs diff --git a/src/test/run-make/atomic-lock-free/Makefile b/src/test/run-make-fulldeps/atomic-lock-free/Makefile similarity index 100% rename from src/test/run-make/atomic-lock-free/Makefile rename to src/test/run-make-fulldeps/atomic-lock-free/Makefile diff --git a/src/test/run-make/atomic-lock-free/atomic_lock_free.rs b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs similarity index 97% rename from src/test/run-make/atomic-lock-free/atomic_lock_free.rs rename to src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs index b41e8e9226b3..54f888b3796a 100644 --- a/src/test/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/src/test/run-make-fulldeps/atomic-lock-free/atomic_lock_free.rs @@ -23,6 +23,8 @@ trait Copy {} #[lang = "freeze"] trait Freeze {} +impl Copy for *mut T {} + #[cfg(target_has_atomic = "8")] pub unsafe fn atomic_u8(x: *mut u8) { atomic_xadd(x, 1); diff --git a/src/test/run-make/bare-outfile/Makefile b/src/test/run-make-fulldeps/bare-outfile/Makefile similarity index 100% rename from src/test/run-make/bare-outfile/Makefile rename to src/test/run-make-fulldeps/bare-outfile/Makefile diff --git a/src/test/run-make/bare-outfile/foo.rs b/src/test/run-make-fulldeps/bare-outfile/foo.rs similarity index 100% rename from src/test/run-make/bare-outfile/foo.rs rename to src/test/run-make-fulldeps/bare-outfile/foo.rs diff --git a/src/test/run-make/c-dynamic-dylib/Makefile b/src/test/run-make-fulldeps/c-dynamic-dylib/Makefile similarity index 100% rename from src/test/run-make/c-dynamic-dylib/Makefile rename to src/test/run-make-fulldeps/c-dynamic-dylib/Makefile diff --git a/src/test/run-make/c-dynamic-dylib/bar.rs b/src/test/run-make-fulldeps/c-dynamic-dylib/bar.rs similarity index 100% rename from src/test/run-make/c-dynamic-dylib/bar.rs rename to src/test/run-make-fulldeps/c-dynamic-dylib/bar.rs diff --git a/src/test/run-make/c-dynamic-dylib/cfoo.c b/src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c similarity index 100% rename from src/test/run-make/c-dynamic-dylib/cfoo.c rename to src/test/run-make-fulldeps/c-dynamic-dylib/cfoo.c diff --git a/src/test/run-make/c-dynamic-dylib/foo.rs b/src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs similarity index 100% rename from src/test/run-make/c-dynamic-dylib/foo.rs rename to src/test/run-make-fulldeps/c-dynamic-dylib/foo.rs diff --git a/src/test/run-make/c-dynamic-rlib/Makefile b/src/test/run-make-fulldeps/c-dynamic-rlib/Makefile similarity index 100% rename from src/test/run-make/c-dynamic-rlib/Makefile rename to src/test/run-make-fulldeps/c-dynamic-rlib/Makefile diff --git a/src/test/run-make/c-dynamic-rlib/bar.rs b/src/test/run-make-fulldeps/c-dynamic-rlib/bar.rs similarity index 100% rename from src/test/run-make/c-dynamic-rlib/bar.rs rename to src/test/run-make-fulldeps/c-dynamic-rlib/bar.rs diff --git a/src/test/run-make/c-dynamic-rlib/cfoo.c b/src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c similarity index 100% rename from src/test/run-make/c-dynamic-rlib/cfoo.c rename to src/test/run-make-fulldeps/c-dynamic-rlib/cfoo.c diff --git a/src/test/run-make/c-dynamic-rlib/foo.rs b/src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs similarity index 100% rename from src/test/run-make/c-dynamic-rlib/foo.rs rename to src/test/run-make-fulldeps/c-dynamic-rlib/foo.rs diff --git a/src/test/run-make/c-link-to-rust-dylib/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-dylib/Makefile similarity index 100% rename from src/test/run-make/c-link-to-rust-dylib/Makefile rename to src/test/run-make-fulldeps/c-link-to-rust-dylib/Makefile diff --git a/src/test/run-make/c-link-to-rust-dylib/bar.c b/src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c similarity index 100% rename from src/test/run-make/c-link-to-rust-dylib/bar.c rename to src/test/run-make-fulldeps/c-link-to-rust-dylib/bar.c diff --git a/src/test/run-make/c-link-to-rust-dylib/foo.rs b/src/test/run-make-fulldeps/c-link-to-rust-dylib/foo.rs similarity index 100% rename from src/test/run-make/c-link-to-rust-dylib/foo.rs rename to src/test/run-make-fulldeps/c-link-to-rust-dylib/foo.rs diff --git a/src/test/run-make/c-link-to-rust-staticlib/Makefile b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/Makefile similarity index 100% rename from src/test/run-make/c-link-to-rust-staticlib/Makefile rename to src/test/run-make-fulldeps/c-link-to-rust-staticlib/Makefile diff --git a/src/test/run-make/c-link-to-rust-staticlib/bar.c b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c similarity index 100% rename from src/test/run-make/c-link-to-rust-staticlib/bar.c rename to src/test/run-make-fulldeps/c-link-to-rust-staticlib/bar.c diff --git a/src/test/run-make/c-link-to-rust-staticlib/foo.rs b/src/test/run-make-fulldeps/c-link-to-rust-staticlib/foo.rs similarity index 100% rename from src/test/run-make/c-link-to-rust-staticlib/foo.rs rename to src/test/run-make-fulldeps/c-link-to-rust-staticlib/foo.rs diff --git a/src/test/run-make/c-static-dylib/Makefile b/src/test/run-make-fulldeps/c-static-dylib/Makefile similarity index 100% rename from src/test/run-make/c-static-dylib/Makefile rename to src/test/run-make-fulldeps/c-static-dylib/Makefile diff --git a/src/test/run-make/c-static-dylib/bar.rs b/src/test/run-make-fulldeps/c-static-dylib/bar.rs similarity index 100% rename from src/test/run-make/c-static-dylib/bar.rs rename to src/test/run-make-fulldeps/c-static-dylib/bar.rs diff --git a/src/test/run-make/c-static-dylib/cfoo.c b/src/test/run-make-fulldeps/c-static-dylib/cfoo.c similarity index 100% rename from src/test/run-make/c-static-dylib/cfoo.c rename to src/test/run-make-fulldeps/c-static-dylib/cfoo.c diff --git a/src/test/run-make/c-static-dylib/foo.rs b/src/test/run-make-fulldeps/c-static-dylib/foo.rs similarity index 100% rename from src/test/run-make/c-static-dylib/foo.rs rename to src/test/run-make-fulldeps/c-static-dylib/foo.rs diff --git a/src/test/run-make/c-static-rlib/Makefile b/src/test/run-make-fulldeps/c-static-rlib/Makefile similarity index 100% rename from src/test/run-make/c-static-rlib/Makefile rename to src/test/run-make-fulldeps/c-static-rlib/Makefile diff --git a/src/test/run-make/c-static-rlib/bar.rs b/src/test/run-make-fulldeps/c-static-rlib/bar.rs similarity index 100% rename from src/test/run-make/c-static-rlib/bar.rs rename to src/test/run-make-fulldeps/c-static-rlib/bar.rs diff --git a/src/test/run-make/c-static-rlib/cfoo.c b/src/test/run-make-fulldeps/c-static-rlib/cfoo.c similarity index 100% rename from src/test/run-make/c-static-rlib/cfoo.c rename to src/test/run-make-fulldeps/c-static-rlib/cfoo.c diff --git a/src/test/run-make/c-static-rlib/foo.rs b/src/test/run-make-fulldeps/c-static-rlib/foo.rs similarity index 100% rename from src/test/run-make/c-static-rlib/foo.rs rename to src/test/run-make-fulldeps/c-static-rlib/foo.rs diff --git a/src/test/run-make/cat-and-grep-sanity-check/Makefile b/src/test/run-make-fulldeps/cat-and-grep-sanity-check/Makefile similarity index 100% rename from src/test/run-make/cat-and-grep-sanity-check/Makefile rename to src/test/run-make-fulldeps/cat-and-grep-sanity-check/Makefile diff --git a/src/test/run-make/cdylib-fewer-symbols/Makefile b/src/test/run-make-fulldeps/cdylib-fewer-symbols/Makefile similarity index 100% rename from src/test/run-make/cdylib-fewer-symbols/Makefile rename to src/test/run-make-fulldeps/cdylib-fewer-symbols/Makefile diff --git a/src/test/run-make/cdylib-fewer-symbols/foo.rs b/src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs similarity index 100% rename from src/test/run-make/cdylib-fewer-symbols/foo.rs rename to src/test/run-make-fulldeps/cdylib-fewer-symbols/foo.rs diff --git a/src/test/run-make/cdylib/Makefile b/src/test/run-make-fulldeps/cdylib/Makefile similarity index 100% rename from src/test/run-make/cdylib/Makefile rename to src/test/run-make-fulldeps/cdylib/Makefile diff --git a/src/test/run-make/cdylib/bar.rs b/src/test/run-make-fulldeps/cdylib/bar.rs similarity index 100% rename from src/test/run-make/cdylib/bar.rs rename to src/test/run-make-fulldeps/cdylib/bar.rs diff --git a/src/test/run-make/cdylib/foo.c b/src/test/run-make-fulldeps/cdylib/foo.c similarity index 100% rename from src/test/run-make/cdylib/foo.c rename to src/test/run-make-fulldeps/cdylib/foo.c diff --git a/src/test/run-make/cdylib/foo.rs b/src/test/run-make-fulldeps/cdylib/foo.rs similarity index 100% rename from src/test/run-make/cdylib/foo.rs rename to src/test/run-make-fulldeps/cdylib/foo.rs diff --git a/src/test/run-make/codegen-options-parsing/Makefile b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile similarity index 100% rename from src/test/run-make/codegen-options-parsing/Makefile rename to src/test/run-make-fulldeps/codegen-options-parsing/Makefile diff --git a/src/test/run-make/codegen-options-parsing/dummy.rs b/src/test/run-make-fulldeps/codegen-options-parsing/dummy.rs similarity index 100% rename from src/test/run-make/codegen-options-parsing/dummy.rs rename to src/test/run-make-fulldeps/codegen-options-parsing/dummy.rs diff --git a/src/test/run-make/compile-stdin/Makefile b/src/test/run-make-fulldeps/compile-stdin/Makefile similarity index 100% rename from src/test/run-make/compile-stdin/Makefile rename to src/test/run-make-fulldeps/compile-stdin/Makefile diff --git a/src/test/run-make/compiler-lookup-paths-2/Makefile b/src/test/run-make-fulldeps/compiler-lookup-paths-2/Makefile similarity index 100% rename from src/test/run-make/compiler-lookup-paths-2/Makefile rename to src/test/run-make-fulldeps/compiler-lookup-paths-2/Makefile diff --git a/src/test/run-make/compiler-lookup-paths-2/a.rs b/src/test/run-make-fulldeps/compiler-lookup-paths-2/a.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths-2/a.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths-2/a.rs diff --git a/src/test/run-make/compiler-lookup-paths-2/b.rs b/src/test/run-make-fulldeps/compiler-lookup-paths-2/b.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths-2/b.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths-2/b.rs diff --git a/src/test/run-make/compiler-lookup-paths-2/c.rs b/src/test/run-make-fulldeps/compiler-lookup-paths-2/c.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths-2/c.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths-2/c.rs diff --git a/src/test/run-make/compiler-lookup-paths/Makefile b/src/test/run-make-fulldeps/compiler-lookup-paths/Makefile similarity index 100% rename from src/test/run-make/compiler-lookup-paths/Makefile rename to src/test/run-make-fulldeps/compiler-lookup-paths/Makefile diff --git a/src/test/run-make/compiler-lookup-paths/a.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/a.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/a.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/a.rs diff --git a/src/test/run-make/compiler-lookup-paths/b.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/b.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/b.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/b.rs diff --git a/src/test/run-make/compiler-lookup-paths/c.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/c.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/c.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/c.rs diff --git a/src/test/run-make/compiler-lookup-paths/d.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/d.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/d.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/d.rs diff --git a/src/test/run-make/compiler-lookup-paths/e.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/e.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/e.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/e.rs diff --git a/src/test/run-make/compiler-lookup-paths/e2.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/e2.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/e2.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/e2.rs diff --git a/src/test/run-make/compiler-lookup-paths/f.rs b/src/test/run-make-fulldeps/compiler-lookup-paths/f.rs similarity index 100% rename from src/test/run-make/compiler-lookup-paths/f.rs rename to src/test/run-make-fulldeps/compiler-lookup-paths/f.rs diff --git a/src/test/run-make/compiler-lookup-paths/native.c b/src/test/run-make-fulldeps/compiler-lookup-paths/native.c similarity index 100% rename from src/test/run-make/compiler-lookup-paths/native.c rename to src/test/run-make-fulldeps/compiler-lookup-paths/native.c diff --git a/src/test/run-make/compiler-rt-works-on-mingw/Makefile b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile similarity index 100% rename from src/test/run-make/compiler-rt-works-on-mingw/Makefile rename to src/test/run-make-fulldeps/compiler-rt-works-on-mingw/Makefile diff --git a/src/test/run-make/compiler-rt-works-on-mingw/foo.cpp b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp similarity index 100% rename from src/test/run-make/compiler-rt-works-on-mingw/foo.cpp rename to src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.cpp diff --git a/src/test/run-make/compiler-rt-works-on-mingw/foo.rs b/src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs similarity index 100% rename from src/test/run-make/compiler-rt-works-on-mingw/foo.rs rename to src/test/run-make-fulldeps/compiler-rt-works-on-mingw/foo.rs diff --git a/src/test/run-make/crate-data-smoke/Makefile b/src/test/run-make-fulldeps/crate-data-smoke/Makefile similarity index 100% rename from src/test/run-make/crate-data-smoke/Makefile rename to src/test/run-make-fulldeps/crate-data-smoke/Makefile diff --git a/src/test/run-make/crate-data-smoke/crate.rs b/src/test/run-make-fulldeps/crate-data-smoke/crate.rs similarity index 100% rename from src/test/run-make/crate-data-smoke/crate.rs rename to src/test/run-make-fulldeps/crate-data-smoke/crate.rs diff --git a/src/test/run-make/crate-data-smoke/lib.rs b/src/test/run-make-fulldeps/crate-data-smoke/lib.rs similarity index 100% rename from src/test/run-make/crate-data-smoke/lib.rs rename to src/test/run-make-fulldeps/crate-data-smoke/lib.rs diff --git a/src/test/run-make/crate-data-smoke/rlib.rs b/src/test/run-make-fulldeps/crate-data-smoke/rlib.rs similarity index 100% rename from src/test/run-make/crate-data-smoke/rlib.rs rename to src/test/run-make-fulldeps/crate-data-smoke/rlib.rs diff --git a/src/test/run-make/crate-name-priority/Makefile b/src/test/run-make-fulldeps/crate-name-priority/Makefile similarity index 100% rename from src/test/run-make/crate-name-priority/Makefile rename to src/test/run-make-fulldeps/crate-name-priority/Makefile diff --git a/src/test/run-make/crate-name-priority/foo.rs b/src/test/run-make-fulldeps/crate-name-priority/foo.rs similarity index 100% rename from src/test/run-make/crate-name-priority/foo.rs rename to src/test/run-make-fulldeps/crate-name-priority/foo.rs diff --git a/src/test/run-make/crate-name-priority/foo1.rs b/src/test/run-make-fulldeps/crate-name-priority/foo1.rs similarity index 100% rename from src/test/run-make/crate-name-priority/foo1.rs rename to src/test/run-make-fulldeps/crate-name-priority/foo1.rs diff --git a/src/test/run-make/debug-assertions/Makefile b/src/test/run-make-fulldeps/debug-assertions/Makefile similarity index 100% rename from src/test/run-make/debug-assertions/Makefile rename to src/test/run-make-fulldeps/debug-assertions/Makefile diff --git a/src/test/run-make/debug-assertions/debug.rs b/src/test/run-make-fulldeps/debug-assertions/debug.rs similarity index 100% rename from src/test/run-make/debug-assertions/debug.rs rename to src/test/run-make-fulldeps/debug-assertions/debug.rs diff --git a/src/test/run-make/dep-info-doesnt-run-much/Makefile b/src/test/run-make-fulldeps/dep-info-doesnt-run-much/Makefile similarity index 100% rename from src/test/run-make/dep-info-doesnt-run-much/Makefile rename to src/test/run-make-fulldeps/dep-info-doesnt-run-much/Makefile diff --git a/src/test/run-make/dep-info-doesnt-run-much/foo.rs b/src/test/run-make-fulldeps/dep-info-doesnt-run-much/foo.rs similarity index 100% rename from src/test/run-make/dep-info-doesnt-run-much/foo.rs rename to src/test/run-make-fulldeps/dep-info-doesnt-run-much/foo.rs diff --git a/src/test/run-make/dep-info-spaces/Makefile b/src/test/run-make-fulldeps/dep-info-spaces/Makefile similarity index 100% rename from src/test/run-make/dep-info-spaces/Makefile rename to src/test/run-make-fulldeps/dep-info-spaces/Makefile diff --git a/src/test/run-make/dep-info-spaces/Makefile.foo b/src/test/run-make-fulldeps/dep-info-spaces/Makefile.foo similarity index 100% rename from src/test/run-make/dep-info-spaces/Makefile.foo rename to src/test/run-make-fulldeps/dep-info-spaces/Makefile.foo diff --git a/src/test/run-make/dep-info-spaces/bar.rs b/src/test/run-make-fulldeps/dep-info-spaces/bar.rs similarity index 100% rename from src/test/run-make/dep-info-spaces/bar.rs rename to src/test/run-make-fulldeps/dep-info-spaces/bar.rs diff --git a/src/test/run-make/dep-info-spaces/foo foo.rs b/src/test/run-make-fulldeps/dep-info-spaces/foo foo.rs similarity index 100% rename from src/test/run-make/dep-info-spaces/foo foo.rs rename to src/test/run-make-fulldeps/dep-info-spaces/foo foo.rs diff --git a/src/test/run-make/dep-info-spaces/lib.rs b/src/test/run-make-fulldeps/dep-info-spaces/lib.rs similarity index 100% rename from src/test/run-make/dep-info-spaces/lib.rs rename to src/test/run-make-fulldeps/dep-info-spaces/lib.rs diff --git a/src/test/run-make/dep-info/Makefile b/src/test/run-make-fulldeps/dep-info/Makefile similarity index 100% rename from src/test/run-make/dep-info/Makefile rename to src/test/run-make-fulldeps/dep-info/Makefile diff --git a/src/test/run-make/dep-info/Makefile.foo b/src/test/run-make-fulldeps/dep-info/Makefile.foo similarity index 100% rename from src/test/run-make/dep-info/Makefile.foo rename to src/test/run-make-fulldeps/dep-info/Makefile.foo diff --git a/src/test/run-make/dep-info/bar.rs b/src/test/run-make-fulldeps/dep-info/bar.rs similarity index 100% rename from src/test/run-make/dep-info/bar.rs rename to src/test/run-make-fulldeps/dep-info/bar.rs diff --git a/src/test/run-make/dep-info/foo.rs b/src/test/run-make-fulldeps/dep-info/foo.rs similarity index 100% rename from src/test/run-make/dep-info/foo.rs rename to src/test/run-make-fulldeps/dep-info/foo.rs diff --git a/src/test/run-make/dep-info/lib.rs b/src/test/run-make-fulldeps/dep-info/lib.rs similarity index 100% rename from src/test/run-make/dep-info/lib.rs rename to src/test/run-make-fulldeps/dep-info/lib.rs diff --git a/src/test/run-make/dep-info/lib2.rs b/src/test/run-make-fulldeps/dep-info/lib2.rs similarity index 100% rename from src/test/run-make/dep-info/lib2.rs rename to src/test/run-make-fulldeps/dep-info/lib2.rs diff --git a/src/test/run-make/duplicate-output-flavors/Makefile b/src/test/run-make-fulldeps/duplicate-output-flavors/Makefile similarity index 100% rename from src/test/run-make/duplicate-output-flavors/Makefile rename to src/test/run-make-fulldeps/duplicate-output-flavors/Makefile diff --git a/src/test/run-make/duplicate-output-flavors/foo.rs b/src/test/run-make-fulldeps/duplicate-output-flavors/foo.rs similarity index 100% rename from src/test/run-make/duplicate-output-flavors/foo.rs rename to src/test/run-make-fulldeps/duplicate-output-flavors/foo.rs diff --git a/src/test/run-make/dylib-chain/Makefile b/src/test/run-make-fulldeps/dylib-chain/Makefile similarity index 100% rename from src/test/run-make/dylib-chain/Makefile rename to src/test/run-make-fulldeps/dylib-chain/Makefile diff --git a/src/test/run-make/dylib-chain/m1.rs b/src/test/run-make-fulldeps/dylib-chain/m1.rs similarity index 100% rename from src/test/run-make/dylib-chain/m1.rs rename to src/test/run-make-fulldeps/dylib-chain/m1.rs diff --git a/src/test/run-make/dylib-chain/m2.rs b/src/test/run-make-fulldeps/dylib-chain/m2.rs similarity index 100% rename from src/test/run-make/dylib-chain/m2.rs rename to src/test/run-make-fulldeps/dylib-chain/m2.rs diff --git a/src/test/run-make/dylib-chain/m3.rs b/src/test/run-make-fulldeps/dylib-chain/m3.rs similarity index 100% rename from src/test/run-make/dylib-chain/m3.rs rename to src/test/run-make-fulldeps/dylib-chain/m3.rs diff --git a/src/test/run-make/dylib-chain/m4.rs b/src/test/run-make-fulldeps/dylib-chain/m4.rs similarity index 100% rename from src/test/run-make/dylib-chain/m4.rs rename to src/test/run-make-fulldeps/dylib-chain/m4.rs diff --git a/src/test/run-make/emit/Makefile b/src/test/run-make-fulldeps/emit/Makefile similarity index 100% rename from src/test/run-make/emit/Makefile rename to src/test/run-make-fulldeps/emit/Makefile diff --git a/src/test/run-make/emit/test-24876.rs b/src/test/run-make-fulldeps/emit/test-24876.rs similarity index 100% rename from src/test/run-make/emit/test-24876.rs rename to src/test/run-make-fulldeps/emit/test-24876.rs diff --git a/src/test/run-make/emit/test-26235.rs b/src/test/run-make-fulldeps/emit/test-26235.rs similarity index 100% rename from src/test/run-make/emit/test-26235.rs rename to src/test/run-make-fulldeps/emit/test-26235.rs diff --git a/src/test/run-make/error-found-staticlib-instead-crate/Makefile b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/Makefile similarity index 100% rename from src/test/run-make/error-found-staticlib-instead-crate/Makefile rename to src/test/run-make-fulldeps/error-found-staticlib-instead-crate/Makefile diff --git a/src/test/run-make/error-found-staticlib-instead-crate/bar.rs b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/bar.rs similarity index 100% rename from src/test/run-make/error-found-staticlib-instead-crate/bar.rs rename to src/test/run-make-fulldeps/error-found-staticlib-instead-crate/bar.rs diff --git a/src/test/run-make/error-found-staticlib-instead-crate/foo.rs b/src/test/run-make-fulldeps/error-found-staticlib-instead-crate/foo.rs similarity index 100% rename from src/test/run-make/error-found-staticlib-instead-crate/foo.rs rename to src/test/run-make-fulldeps/error-found-staticlib-instead-crate/foo.rs diff --git a/src/test/run-make/error-writing-dependencies/Makefile b/src/test/run-make-fulldeps/error-writing-dependencies/Makefile similarity index 100% rename from src/test/run-make/error-writing-dependencies/Makefile rename to src/test/run-make-fulldeps/error-writing-dependencies/Makefile diff --git a/src/test/run-make/error-writing-dependencies/foo.rs b/src/test/run-make-fulldeps/error-writing-dependencies/foo.rs similarity index 100% rename from src/test/run-make/error-writing-dependencies/foo.rs rename to src/test/run-make-fulldeps/error-writing-dependencies/foo.rs diff --git a/src/test/run-make/extern-diff-internal-name/Makefile b/src/test/run-make-fulldeps/extern-diff-internal-name/Makefile similarity index 100% rename from src/test/run-make/extern-diff-internal-name/Makefile rename to src/test/run-make-fulldeps/extern-diff-internal-name/Makefile diff --git a/src/test/run-make/extern-diff-internal-name/lib.rs b/src/test/run-make-fulldeps/extern-diff-internal-name/lib.rs similarity index 100% rename from src/test/run-make/extern-diff-internal-name/lib.rs rename to src/test/run-make-fulldeps/extern-diff-internal-name/lib.rs diff --git a/src/test/run-make/extern-diff-internal-name/test.rs b/src/test/run-make-fulldeps/extern-diff-internal-name/test.rs similarity index 100% rename from src/test/run-make/extern-diff-internal-name/test.rs rename to src/test/run-make-fulldeps/extern-diff-internal-name/test.rs diff --git a/src/test/run-make/extern-flag-disambiguates/Makefile b/src/test/run-make-fulldeps/extern-flag-disambiguates/Makefile similarity index 100% rename from src/test/run-make/extern-flag-disambiguates/Makefile rename to src/test/run-make-fulldeps/extern-flag-disambiguates/Makefile diff --git a/src/test/run-make/extern-flag-disambiguates/a.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/a.rs similarity index 100% rename from src/test/run-make/extern-flag-disambiguates/a.rs rename to src/test/run-make-fulldeps/extern-flag-disambiguates/a.rs diff --git a/src/test/run-make/extern-flag-disambiguates/b.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/b.rs similarity index 100% rename from src/test/run-make/extern-flag-disambiguates/b.rs rename to src/test/run-make-fulldeps/extern-flag-disambiguates/b.rs diff --git a/src/test/run-make/extern-flag-disambiguates/c.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/c.rs similarity index 100% rename from src/test/run-make/extern-flag-disambiguates/c.rs rename to src/test/run-make-fulldeps/extern-flag-disambiguates/c.rs diff --git a/src/test/run-make/extern-flag-disambiguates/d.rs b/src/test/run-make-fulldeps/extern-flag-disambiguates/d.rs similarity index 100% rename from src/test/run-make/extern-flag-disambiguates/d.rs rename to src/test/run-make-fulldeps/extern-flag-disambiguates/d.rs diff --git a/src/test/run-make/extern-flag-fun/Makefile b/src/test/run-make-fulldeps/extern-flag-fun/Makefile similarity index 100% rename from src/test/run-make/extern-flag-fun/Makefile rename to src/test/run-make-fulldeps/extern-flag-fun/Makefile diff --git a/src/test/run-make/extern-flag-fun/bar-alt.rs b/src/test/run-make-fulldeps/extern-flag-fun/bar-alt.rs similarity index 100% rename from src/test/run-make/extern-flag-fun/bar-alt.rs rename to src/test/run-make-fulldeps/extern-flag-fun/bar-alt.rs diff --git a/src/test/run-make/extern-flag-fun/bar.rs b/src/test/run-make-fulldeps/extern-flag-fun/bar.rs similarity index 100% rename from src/test/run-make/extern-flag-fun/bar.rs rename to src/test/run-make-fulldeps/extern-flag-fun/bar.rs diff --git a/src/test/run-make/extern-flag-fun/foo.rs b/src/test/run-make-fulldeps/extern-flag-fun/foo.rs similarity index 100% rename from src/test/run-make/extern-flag-fun/foo.rs rename to src/test/run-make-fulldeps/extern-flag-fun/foo.rs diff --git a/src/test/run-make/extern-fn-generic/Makefile b/src/test/run-make-fulldeps/extern-fn-generic/Makefile similarity index 100% rename from src/test/run-make/extern-fn-generic/Makefile rename to src/test/run-make-fulldeps/extern-fn-generic/Makefile diff --git a/src/test/run-make/extern-fn-generic/test.c b/src/test/run-make-fulldeps/extern-fn-generic/test.c similarity index 100% rename from src/test/run-make/extern-fn-generic/test.c rename to src/test/run-make-fulldeps/extern-fn-generic/test.c diff --git a/src/test/run-make/extern-fn-generic/test.rs b/src/test/run-make-fulldeps/extern-fn-generic/test.rs similarity index 100% rename from src/test/run-make/extern-fn-generic/test.rs rename to src/test/run-make-fulldeps/extern-fn-generic/test.rs diff --git a/src/test/run-make/extern-fn-generic/testcrate.rs b/src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs similarity index 100% rename from src/test/run-make/extern-fn-generic/testcrate.rs rename to src/test/run-make-fulldeps/extern-fn-generic/testcrate.rs diff --git a/src/test/run-make/extern-fn-mangle/Makefile b/src/test/run-make-fulldeps/extern-fn-mangle/Makefile similarity index 100% rename from src/test/run-make/extern-fn-mangle/Makefile rename to src/test/run-make-fulldeps/extern-fn-mangle/Makefile diff --git a/src/test/run-make/extern-fn-mangle/test.c b/src/test/run-make-fulldeps/extern-fn-mangle/test.c similarity index 100% rename from src/test/run-make/extern-fn-mangle/test.c rename to src/test/run-make-fulldeps/extern-fn-mangle/test.c diff --git a/src/test/run-make/extern-fn-mangle/test.rs b/src/test/run-make-fulldeps/extern-fn-mangle/test.rs similarity index 100% rename from src/test/run-make/extern-fn-mangle/test.rs rename to src/test/run-make-fulldeps/extern-fn-mangle/test.rs diff --git a/src/test/run-make/extern-fn-reachable/Makefile b/src/test/run-make-fulldeps/extern-fn-reachable/Makefile similarity index 100% rename from src/test/run-make/extern-fn-reachable/Makefile rename to src/test/run-make-fulldeps/extern-fn-reachable/Makefile diff --git a/src/test/run-make/extern-fn-reachable/dylib.rs b/src/test/run-make-fulldeps/extern-fn-reachable/dylib.rs similarity index 100% rename from src/test/run-make/extern-fn-reachable/dylib.rs rename to src/test/run-make-fulldeps/extern-fn-reachable/dylib.rs diff --git a/src/test/run-make/extern-fn-reachable/main.rs b/src/test/run-make-fulldeps/extern-fn-reachable/main.rs similarity index 100% rename from src/test/run-make/extern-fn-reachable/main.rs rename to src/test/run-make-fulldeps/extern-fn-reachable/main.rs diff --git a/src/test/run-make/extern-fn-struct-passing-abi/Makefile b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/Makefile similarity index 100% rename from src/test/run-make/extern-fn-struct-passing-abi/Makefile rename to src/test/run-make-fulldeps/extern-fn-struct-passing-abi/Makefile diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.c b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.c similarity index 100% rename from src/test/run-make/extern-fn-struct-passing-abi/test.c rename to src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.c diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.rs b/src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs similarity index 100% rename from src/test/run-make/extern-fn-struct-passing-abi/test.rs rename to src/test/run-make-fulldeps/extern-fn-struct-passing-abi/test.rs diff --git a/src/test/run-make/extern-fn-with-extern-types/Makefile b/src/test/run-make-fulldeps/extern-fn-with-extern-types/Makefile similarity index 100% rename from src/test/run-make/extern-fn-with-extern-types/Makefile rename to src/test/run-make-fulldeps/extern-fn-with-extern-types/Makefile diff --git a/src/test/run-make/extern-fn-with-extern-types/ctest.c b/src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c similarity index 100% rename from src/test/run-make/extern-fn-with-extern-types/ctest.c rename to src/test/run-make-fulldeps/extern-fn-with-extern-types/ctest.c diff --git a/src/test/run-make/extern-fn-with-extern-types/test.rs b/src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs similarity index 100% rename from src/test/run-make/extern-fn-with-extern-types/test.rs rename to src/test/run-make-fulldeps/extern-fn-with-extern-types/test.rs diff --git a/src/test/run-make/extern-fn-with-packed-struct/Makefile b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/Makefile similarity index 100% rename from src/test/run-make/extern-fn-with-packed-struct/Makefile rename to src/test/run-make-fulldeps/extern-fn-with-packed-struct/Makefile diff --git a/src/test/run-make/extern-fn-with-packed-struct/test.c b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c similarity index 100% rename from src/test/run-make/extern-fn-with-packed-struct/test.c rename to src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.c diff --git a/src/test/run-make/extern-fn-with-packed-struct/test.rs b/src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs similarity index 100% rename from src/test/run-make/extern-fn-with-packed-struct/test.rs rename to src/test/run-make-fulldeps/extern-fn-with-packed-struct/test.rs diff --git a/src/test/run-make/extern-fn-with-union/Makefile b/src/test/run-make-fulldeps/extern-fn-with-union/Makefile similarity index 100% rename from src/test/run-make/extern-fn-with-union/Makefile rename to src/test/run-make-fulldeps/extern-fn-with-union/Makefile diff --git a/src/test/run-make/extern-fn-with-union/ctest.c b/src/test/run-make-fulldeps/extern-fn-with-union/ctest.c similarity index 100% rename from src/test/run-make/extern-fn-with-union/ctest.c rename to src/test/run-make-fulldeps/extern-fn-with-union/ctest.c diff --git a/src/test/run-make/extern-fn-with-union/test.rs b/src/test/run-make-fulldeps/extern-fn-with-union/test.rs similarity index 100% rename from src/test/run-make/extern-fn-with-union/test.rs rename to src/test/run-make-fulldeps/extern-fn-with-union/test.rs diff --git a/src/test/run-make/extern-fn-with-union/testcrate.rs b/src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs similarity index 100% rename from src/test/run-make/extern-fn-with-union/testcrate.rs rename to src/test/run-make-fulldeps/extern-fn-with-union/testcrate.rs diff --git a/src/test/run-make/extern-multiple-copies/Makefile b/src/test/run-make-fulldeps/extern-multiple-copies/Makefile similarity index 100% rename from src/test/run-make/extern-multiple-copies/Makefile rename to src/test/run-make-fulldeps/extern-multiple-copies/Makefile diff --git a/src/test/run-make/extern-multiple-copies/bar.rs b/src/test/run-make-fulldeps/extern-multiple-copies/bar.rs similarity index 100% rename from src/test/run-make/extern-multiple-copies/bar.rs rename to src/test/run-make-fulldeps/extern-multiple-copies/bar.rs diff --git a/src/test/run-make/extern-multiple-copies/foo1.rs b/src/test/run-make-fulldeps/extern-multiple-copies/foo1.rs similarity index 100% rename from src/test/run-make/extern-multiple-copies/foo1.rs rename to src/test/run-make-fulldeps/extern-multiple-copies/foo1.rs diff --git a/src/test/run-make/extern-multiple-copies/foo2.rs b/src/test/run-make-fulldeps/extern-multiple-copies/foo2.rs similarity index 100% rename from src/test/run-make/extern-multiple-copies/foo2.rs rename to src/test/run-make-fulldeps/extern-multiple-copies/foo2.rs diff --git a/src/test/run-make/extern-multiple-copies2/Makefile b/src/test/run-make-fulldeps/extern-multiple-copies2/Makefile similarity index 100% rename from src/test/run-make/extern-multiple-copies2/Makefile rename to src/test/run-make-fulldeps/extern-multiple-copies2/Makefile diff --git a/src/test/run-make/extern-multiple-copies2/bar.rs b/src/test/run-make-fulldeps/extern-multiple-copies2/bar.rs similarity index 100% rename from src/test/run-make/extern-multiple-copies2/bar.rs rename to src/test/run-make-fulldeps/extern-multiple-copies2/bar.rs diff --git a/src/test/run-make/extern-multiple-copies2/foo1.rs b/src/test/run-make-fulldeps/extern-multiple-copies2/foo1.rs similarity index 100% rename from src/test/run-make/extern-multiple-copies2/foo1.rs rename to src/test/run-make-fulldeps/extern-multiple-copies2/foo1.rs diff --git a/src/test/run-make/extern-multiple-copies2/foo2.rs b/src/test/run-make-fulldeps/extern-multiple-copies2/foo2.rs similarity index 100% rename from src/test/run-make/extern-multiple-copies2/foo2.rs rename to src/test/run-make-fulldeps/extern-multiple-copies2/foo2.rs diff --git a/src/test/run-make/extern-overrides-distribution/Makefile b/src/test/run-make-fulldeps/extern-overrides-distribution/Makefile similarity index 100% rename from src/test/run-make/extern-overrides-distribution/Makefile rename to src/test/run-make-fulldeps/extern-overrides-distribution/Makefile diff --git a/src/test/run-make/extern-overrides-distribution/libc.rs b/src/test/run-make-fulldeps/extern-overrides-distribution/libc.rs similarity index 100% rename from src/test/run-make/extern-overrides-distribution/libc.rs rename to src/test/run-make-fulldeps/extern-overrides-distribution/libc.rs diff --git a/src/test/run-make/extern-overrides-distribution/main.rs b/src/test/run-make-fulldeps/extern-overrides-distribution/main.rs similarity index 100% rename from src/test/run-make/extern-overrides-distribution/main.rs rename to src/test/run-make-fulldeps/extern-overrides-distribution/main.rs diff --git a/src/test/run-make/extra-filename-with-temp-outputs/Makefile b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile similarity index 100% rename from src/test/run-make/extra-filename-with-temp-outputs/Makefile rename to src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile diff --git a/src/test/run-make/extra-filename-with-temp-outputs/foo.rs b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/foo.rs similarity index 100% rename from src/test/run-make/extra-filename-with-temp-outputs/foo.rs rename to src/test/run-make-fulldeps/extra-filename-with-temp-outputs/foo.rs diff --git a/src/test/run-make/fpic/Makefile b/src/test/run-make-fulldeps/fpic/Makefile similarity index 100% rename from src/test/run-make/fpic/Makefile rename to src/test/run-make-fulldeps/fpic/Makefile diff --git a/src/test/run-make/fpic/hello.rs b/src/test/run-make-fulldeps/fpic/hello.rs similarity index 100% rename from src/test/run-make/fpic/hello.rs rename to src/test/run-make-fulldeps/fpic/hello.rs diff --git a/src/test/run-make/hir-tree/Makefile b/src/test/run-make-fulldeps/hir-tree/Makefile similarity index 100% rename from src/test/run-make/hir-tree/Makefile rename to src/test/run-make-fulldeps/hir-tree/Makefile diff --git a/src/test/run-make/hir-tree/input.rs b/src/test/run-make-fulldeps/hir-tree/input.rs similarity index 100% rename from src/test/run-make/hir-tree/input.rs rename to src/test/run-make-fulldeps/hir-tree/input.rs diff --git a/src/test/run-make/hotplug_codegen_backend/Makefile b/src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile similarity index 100% rename from src/test/run-make/hotplug_codegen_backend/Makefile rename to src/test/run-make-fulldeps/hotplug_codegen_backend/Makefile diff --git a/src/test/run-make/hotplug_codegen_backend/some_crate.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs similarity index 100% rename from src/test/run-make/hotplug_codegen_backend/some_crate.rs rename to src/test/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs diff --git a/src/test/run-make/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs similarity index 97% rename from src/test/run-make/hotplug_codegen_backend/the_backend.rs rename to src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 9e87268e6999..e266b0f5e834 100644 --- a/src/test/run-make/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -28,7 +28,7 @@ use rustc_trans_utils::trans_crate::{TransCrate, MetadataOnlyTransCrate}; struct TheBackend(Box); impl TransCrate for TheBackend { - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { self.0.metadata_loader() } diff --git a/src/test/run-make/include_bytes_deps/Makefile b/src/test/run-make-fulldeps/include_bytes_deps/Makefile similarity index 100% rename from src/test/run-make/include_bytes_deps/Makefile rename to src/test/run-make-fulldeps/include_bytes_deps/Makefile diff --git a/src/test/run-make/include_bytes_deps/input.bin b/src/test/run-make-fulldeps/include_bytes_deps/input.bin similarity index 100% rename from src/test/run-make/include_bytes_deps/input.bin rename to src/test/run-make-fulldeps/include_bytes_deps/input.bin diff --git a/src/test/run-make/include_bytes_deps/input.md b/src/test/run-make-fulldeps/include_bytes_deps/input.md similarity index 100% rename from src/test/run-make/include_bytes_deps/input.md rename to src/test/run-make-fulldeps/include_bytes_deps/input.md diff --git a/src/test/run-make/include_bytes_deps/input.txt b/src/test/run-make-fulldeps/include_bytes_deps/input.txt similarity index 100% rename from src/test/run-make/include_bytes_deps/input.txt rename to src/test/run-make-fulldeps/include_bytes_deps/input.txt diff --git a/src/test/run-make/include_bytes_deps/main.rs b/src/test/run-make-fulldeps/include_bytes_deps/main.rs similarity index 100% rename from src/test/run-make/include_bytes_deps/main.rs rename to src/test/run-make-fulldeps/include_bytes_deps/main.rs diff --git a/src/test/run-make/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile similarity index 100% rename from src/test/run-make/inline-always-many-cgu/Makefile rename to src/test/run-make-fulldeps/inline-always-many-cgu/Makefile diff --git a/src/test/run-make/inline-always-many-cgu/foo.rs b/src/test/run-make-fulldeps/inline-always-many-cgu/foo.rs similarity index 100% rename from src/test/run-make/inline-always-many-cgu/foo.rs rename to src/test/run-make-fulldeps/inline-always-many-cgu/foo.rs diff --git a/src/test/run-make/interdependent-c-libraries/Makefile b/src/test/run-make-fulldeps/interdependent-c-libraries/Makefile similarity index 100% rename from src/test/run-make/interdependent-c-libraries/Makefile rename to src/test/run-make-fulldeps/interdependent-c-libraries/Makefile diff --git a/src/test/run-make/interdependent-c-libraries/bar.c b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.c similarity index 100% rename from src/test/run-make/interdependent-c-libraries/bar.c rename to src/test/run-make-fulldeps/interdependent-c-libraries/bar.c diff --git a/src/test/run-make/interdependent-c-libraries/bar.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs similarity index 100% rename from src/test/run-make/interdependent-c-libraries/bar.rs rename to src/test/run-make-fulldeps/interdependent-c-libraries/bar.rs diff --git a/src/test/run-make/interdependent-c-libraries/foo.c b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.c similarity index 100% rename from src/test/run-make/interdependent-c-libraries/foo.c rename to src/test/run-make-fulldeps/interdependent-c-libraries/foo.c diff --git a/src/test/run-make/interdependent-c-libraries/foo.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs similarity index 100% rename from src/test/run-make/interdependent-c-libraries/foo.rs rename to src/test/run-make-fulldeps/interdependent-c-libraries/foo.rs diff --git a/src/test/run-make/interdependent-c-libraries/main.rs b/src/test/run-make-fulldeps/interdependent-c-libraries/main.rs similarity index 100% rename from src/test/run-make/interdependent-c-libraries/main.rs rename to src/test/run-make-fulldeps/interdependent-c-libraries/main.rs diff --git a/src/test/run-make/intrinsic-unreachable/Makefile b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile similarity index 100% rename from src/test/run-make/intrinsic-unreachable/Makefile rename to src/test/run-make-fulldeps/intrinsic-unreachable/Makefile diff --git a/src/test/run-make/intrinsic-unreachable/exit-ret.rs b/src/test/run-make-fulldeps/intrinsic-unreachable/exit-ret.rs similarity index 100% rename from src/test/run-make/intrinsic-unreachable/exit-ret.rs rename to src/test/run-make-fulldeps/intrinsic-unreachable/exit-ret.rs diff --git a/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs b/src/test/run-make-fulldeps/intrinsic-unreachable/exit-unreachable.rs similarity index 100% rename from src/test/run-make/intrinsic-unreachable/exit-unreachable.rs rename to src/test/run-make-fulldeps/intrinsic-unreachable/exit-unreachable.rs diff --git a/src/test/run-make/invalid-library/Makefile b/src/test/run-make-fulldeps/invalid-library/Makefile similarity index 100% rename from src/test/run-make/invalid-library/Makefile rename to src/test/run-make-fulldeps/invalid-library/Makefile diff --git a/src/test/run-make/invalid-library/foo.rs b/src/test/run-make-fulldeps/invalid-library/foo.rs similarity index 100% rename from src/test/run-make/invalid-library/foo.rs rename to src/test/run-make-fulldeps/invalid-library/foo.rs diff --git a/src/test/run-make/invalid-staticlib/Makefile b/src/test/run-make-fulldeps/invalid-staticlib/Makefile similarity index 100% rename from src/test/run-make/invalid-staticlib/Makefile rename to src/test/run-make-fulldeps/invalid-staticlib/Makefile diff --git a/src/test/run-make/issue-11908/Makefile b/src/test/run-make-fulldeps/issue-11908/Makefile similarity index 100% rename from src/test/run-make/issue-11908/Makefile rename to src/test/run-make-fulldeps/issue-11908/Makefile diff --git a/src/test/run-make/issue-11908/bar.rs b/src/test/run-make-fulldeps/issue-11908/bar.rs similarity index 100% rename from src/test/run-make/issue-11908/bar.rs rename to src/test/run-make-fulldeps/issue-11908/bar.rs diff --git a/src/test/run-make/issue-11908/foo.rs b/src/test/run-make-fulldeps/issue-11908/foo.rs similarity index 100% rename from src/test/run-make/issue-11908/foo.rs rename to src/test/run-make-fulldeps/issue-11908/foo.rs diff --git a/src/test/run-make/issue-14500/Makefile b/src/test/run-make-fulldeps/issue-14500/Makefile similarity index 100% rename from src/test/run-make/issue-14500/Makefile rename to src/test/run-make-fulldeps/issue-14500/Makefile diff --git a/src/test/run-make/issue-14500/bar.rs b/src/test/run-make-fulldeps/issue-14500/bar.rs similarity index 100% rename from src/test/run-make/issue-14500/bar.rs rename to src/test/run-make-fulldeps/issue-14500/bar.rs diff --git a/src/test/run-make/issue-14500/foo.c b/src/test/run-make-fulldeps/issue-14500/foo.c similarity index 100% rename from src/test/run-make/issue-14500/foo.c rename to src/test/run-make-fulldeps/issue-14500/foo.c diff --git a/src/test/run-make/issue-14500/foo.rs b/src/test/run-make-fulldeps/issue-14500/foo.rs similarity index 100% rename from src/test/run-make/issue-14500/foo.rs rename to src/test/run-make-fulldeps/issue-14500/foo.rs diff --git a/src/test/run-make/issue-14698/Makefile b/src/test/run-make-fulldeps/issue-14698/Makefile similarity index 100% rename from src/test/run-make/issue-14698/Makefile rename to src/test/run-make-fulldeps/issue-14698/Makefile diff --git a/src/test/run-make/issue-14698/foo.rs b/src/test/run-make-fulldeps/issue-14698/foo.rs similarity index 100% rename from src/test/run-make/issue-14698/foo.rs rename to src/test/run-make-fulldeps/issue-14698/foo.rs diff --git a/src/test/run-make/issue-15460/Makefile b/src/test/run-make-fulldeps/issue-15460/Makefile similarity index 100% rename from src/test/run-make/issue-15460/Makefile rename to src/test/run-make-fulldeps/issue-15460/Makefile diff --git a/src/test/run-make/issue-15460/bar.rs b/src/test/run-make-fulldeps/issue-15460/bar.rs similarity index 100% rename from src/test/run-make/issue-15460/bar.rs rename to src/test/run-make-fulldeps/issue-15460/bar.rs diff --git a/src/test/run-make/issue-15460/foo.c b/src/test/run-make-fulldeps/issue-15460/foo.c similarity index 100% rename from src/test/run-make/issue-15460/foo.c rename to src/test/run-make-fulldeps/issue-15460/foo.c diff --git a/src/test/run-make/issue-15460/foo.rs b/src/test/run-make-fulldeps/issue-15460/foo.rs similarity index 100% rename from src/test/run-make/issue-15460/foo.rs rename to src/test/run-make-fulldeps/issue-15460/foo.rs diff --git a/src/test/run-make/issue-18943/Makefile b/src/test/run-make-fulldeps/issue-18943/Makefile similarity index 100% rename from src/test/run-make/issue-18943/Makefile rename to src/test/run-make-fulldeps/issue-18943/Makefile diff --git a/src/test/run-make/issue-18943/foo.rs b/src/test/run-make-fulldeps/issue-18943/foo.rs similarity index 100% rename from src/test/run-make/issue-18943/foo.rs rename to src/test/run-make-fulldeps/issue-18943/foo.rs diff --git a/src/test/run-make/issue-19371/Makefile b/src/test/run-make-fulldeps/issue-19371/Makefile similarity index 100% rename from src/test/run-make/issue-19371/Makefile rename to src/test/run-make-fulldeps/issue-19371/Makefile diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs similarity index 83% rename from src/test/run-make/issue-19371/foo.rs rename to src/test/run-make-fulldeps/issue-19371/foo.rs index b4b29e15ce17..e0db2627d853 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -69,18 +69,20 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc, Box) { } fn compile(code: String, output: PathBuf, sysroot: PathBuf) { - let (sess, cstore, trans) = basic_sess(sysroot); - let control = CompileController::basic(); - let input = Input::Str { name: FileName::Anon, input: code }; - let _ = compile_input( - trans, - &sess, - &cstore, - &None, - &input, - &None, - &Some(output), - None, - &control - ); + syntax::with_globals(|| { + let (sess, cstore, trans) = basic_sess(sysroot); + let control = CompileController::basic(); + let input = Input::Str { name: FileName::Anon, input: code }; + let _ = compile_input( + trans, + &sess, + &cstore, + &None, + &input, + &None, + &Some(output), + None, + &control + ); + }); } diff --git a/src/test/run-make/issue-20626/Makefile b/src/test/run-make-fulldeps/issue-20626/Makefile similarity index 100% rename from src/test/run-make/issue-20626/Makefile rename to src/test/run-make-fulldeps/issue-20626/Makefile diff --git a/src/test/run-make/issue-20626/foo.rs b/src/test/run-make-fulldeps/issue-20626/foo.rs similarity index 100% rename from src/test/run-make/issue-20626/foo.rs rename to src/test/run-make-fulldeps/issue-20626/foo.rs diff --git a/src/test/run-make/issue-22131/Makefile b/src/test/run-make-fulldeps/issue-22131/Makefile similarity index 100% rename from src/test/run-make/issue-22131/Makefile rename to src/test/run-make-fulldeps/issue-22131/Makefile diff --git a/src/test/run-make/issue-22131/foo.rs b/src/test/run-make-fulldeps/issue-22131/foo.rs similarity index 100% rename from src/test/run-make/issue-22131/foo.rs rename to src/test/run-make-fulldeps/issue-22131/foo.rs diff --git a/src/test/run-make/issue-24445/Makefile b/src/test/run-make-fulldeps/issue-24445/Makefile similarity index 100% rename from src/test/run-make/issue-24445/Makefile rename to src/test/run-make-fulldeps/issue-24445/Makefile diff --git a/src/test/run-make/issue-24445/foo.c b/src/test/run-make-fulldeps/issue-24445/foo.c similarity index 100% rename from src/test/run-make/issue-24445/foo.c rename to src/test/run-make-fulldeps/issue-24445/foo.c diff --git a/src/test/run-make/issue-24445/foo.rs b/src/test/run-make-fulldeps/issue-24445/foo.rs similarity index 100% rename from src/test/run-make/issue-24445/foo.rs rename to src/test/run-make-fulldeps/issue-24445/foo.rs diff --git a/src/test/run-make/issue-25581/Makefile b/src/test/run-make-fulldeps/issue-25581/Makefile similarity index 100% rename from src/test/run-make/issue-25581/Makefile rename to src/test/run-make-fulldeps/issue-25581/Makefile diff --git a/src/test/run-make/issue-25581/test.c b/src/test/run-make-fulldeps/issue-25581/test.c similarity index 100% rename from src/test/run-make/issue-25581/test.c rename to src/test/run-make-fulldeps/issue-25581/test.c diff --git a/src/test/run-make/issue-25581/test.rs b/src/test/run-make-fulldeps/issue-25581/test.rs similarity index 100% rename from src/test/run-make/issue-25581/test.rs rename to src/test/run-make-fulldeps/issue-25581/test.rs diff --git a/src/test/run-make/issue-26006/Makefile b/src/test/run-make-fulldeps/issue-26006/Makefile similarity index 100% rename from src/test/run-make/issue-26006/Makefile rename to src/test/run-make-fulldeps/issue-26006/Makefile diff --git a/src/test/run-make/issue-26006/in/libc/lib.rs b/src/test/run-make-fulldeps/issue-26006/in/libc/lib.rs similarity index 100% rename from src/test/run-make/issue-26006/in/libc/lib.rs rename to src/test/run-make-fulldeps/issue-26006/in/libc/lib.rs diff --git a/src/test/run-make/issue-26006/in/time/lib.rs b/src/test/run-make-fulldeps/issue-26006/in/time/lib.rs similarity index 100% rename from src/test/run-make/issue-26006/in/time/lib.rs rename to src/test/run-make-fulldeps/issue-26006/in/time/lib.rs diff --git a/src/test/run-make/issue-26092/Makefile b/src/test/run-make-fulldeps/issue-26092/Makefile similarity index 100% rename from src/test/run-make/issue-26092/Makefile rename to src/test/run-make-fulldeps/issue-26092/Makefile diff --git a/src/test/run-make/issue-26092/blank.rs b/src/test/run-make-fulldeps/issue-26092/blank.rs similarity index 100% rename from src/test/run-make/issue-26092/blank.rs rename to src/test/run-make-fulldeps/issue-26092/blank.rs diff --git a/src/test/run-make/issue-28595/Makefile b/src/test/run-make-fulldeps/issue-28595/Makefile similarity index 100% rename from src/test/run-make/issue-28595/Makefile rename to src/test/run-make-fulldeps/issue-28595/Makefile diff --git a/src/test/run-make/issue-28595/a.c b/src/test/run-make-fulldeps/issue-28595/a.c similarity index 100% rename from src/test/run-make/issue-28595/a.c rename to src/test/run-make-fulldeps/issue-28595/a.c diff --git a/src/test/run-make/issue-28595/a.rs b/src/test/run-make-fulldeps/issue-28595/a.rs similarity index 100% rename from src/test/run-make/issue-28595/a.rs rename to src/test/run-make-fulldeps/issue-28595/a.rs diff --git a/src/test/run-make/issue-28595/b.c b/src/test/run-make-fulldeps/issue-28595/b.c similarity index 100% rename from src/test/run-make/issue-28595/b.c rename to src/test/run-make-fulldeps/issue-28595/b.c diff --git a/src/test/run-make/issue-28595/b.rs b/src/test/run-make-fulldeps/issue-28595/b.rs similarity index 100% rename from src/test/run-make/issue-28595/b.rs rename to src/test/run-make-fulldeps/issue-28595/b.rs diff --git a/src/test/run-make/issue-28766/Makefile b/src/test/run-make-fulldeps/issue-28766/Makefile similarity index 100% rename from src/test/run-make/issue-28766/Makefile rename to src/test/run-make-fulldeps/issue-28766/Makefile diff --git a/src/test/run-make/issue-28766/foo.rs b/src/test/run-make-fulldeps/issue-28766/foo.rs similarity index 100% rename from src/test/run-make/issue-28766/foo.rs rename to src/test/run-make-fulldeps/issue-28766/foo.rs diff --git a/src/test/run-make/issue-28766/main.rs b/src/test/run-make-fulldeps/issue-28766/main.rs similarity index 100% rename from src/test/run-make/issue-28766/main.rs rename to src/test/run-make-fulldeps/issue-28766/main.rs diff --git a/src/test/run-make/issue-30063/Makefile b/src/test/run-make-fulldeps/issue-30063/Makefile similarity index 100% rename from src/test/run-make/issue-30063/Makefile rename to src/test/run-make-fulldeps/issue-30063/Makefile diff --git a/src/test/run-make/issue-30063/foo.rs b/src/test/run-make-fulldeps/issue-30063/foo.rs similarity index 100% rename from src/test/run-make/issue-30063/foo.rs rename to src/test/run-make-fulldeps/issue-30063/foo.rs diff --git a/src/test/run-make/issue-33329/Makefile b/src/test/run-make-fulldeps/issue-33329/Makefile similarity index 100% rename from src/test/run-make/issue-33329/Makefile rename to src/test/run-make-fulldeps/issue-33329/Makefile diff --git a/src/test/run-make/issue-33329/main.rs b/src/test/run-make-fulldeps/issue-33329/main.rs similarity index 100% rename from src/test/run-make/issue-33329/main.rs rename to src/test/run-make-fulldeps/issue-33329/main.rs diff --git a/src/test/run-make/issue-35164/Makefile b/src/test/run-make-fulldeps/issue-35164/Makefile similarity index 100% rename from src/test/run-make/issue-35164/Makefile rename to src/test/run-make-fulldeps/issue-35164/Makefile diff --git a/src/test/run-make/issue-35164/main.rs b/src/test/run-make-fulldeps/issue-35164/main.rs similarity index 100% rename from src/test/run-make/issue-35164/main.rs rename to src/test/run-make-fulldeps/issue-35164/main.rs diff --git a/src/test/run-make/issue-35164/submodule/mod.rs b/src/test/run-make-fulldeps/issue-35164/submodule/mod.rs similarity index 100% rename from src/test/run-make/issue-35164/submodule/mod.rs rename to src/test/run-make-fulldeps/issue-35164/submodule/mod.rs diff --git a/src/test/run-make/issue-37839/Makefile b/src/test/run-make-fulldeps/issue-37839/Makefile similarity index 100% rename from src/test/run-make/issue-37839/Makefile rename to src/test/run-make-fulldeps/issue-37839/Makefile diff --git a/src/test/run-make/issue-37839/a.rs b/src/test/run-make-fulldeps/issue-37839/a.rs similarity index 100% rename from src/test/run-make/issue-37839/a.rs rename to src/test/run-make-fulldeps/issue-37839/a.rs diff --git a/src/test/run-make/issue-37839/b.rs b/src/test/run-make-fulldeps/issue-37839/b.rs similarity index 100% rename from src/test/run-make/issue-37839/b.rs rename to src/test/run-make-fulldeps/issue-37839/b.rs diff --git a/src/test/run-make/issue-37839/c.rs b/src/test/run-make-fulldeps/issue-37839/c.rs similarity index 100% rename from src/test/run-make/issue-37839/c.rs rename to src/test/run-make-fulldeps/issue-37839/c.rs diff --git a/src/test/run-make/issue-37893/Makefile b/src/test/run-make-fulldeps/issue-37893/Makefile similarity index 100% rename from src/test/run-make/issue-37893/Makefile rename to src/test/run-make-fulldeps/issue-37893/Makefile diff --git a/src/test/run-make/issue-37893/a.rs b/src/test/run-make-fulldeps/issue-37893/a.rs similarity index 100% rename from src/test/run-make/issue-37893/a.rs rename to src/test/run-make-fulldeps/issue-37893/a.rs diff --git a/src/test/run-make/issue-37893/b.rs b/src/test/run-make-fulldeps/issue-37893/b.rs similarity index 100% rename from src/test/run-make/issue-37893/b.rs rename to src/test/run-make-fulldeps/issue-37893/b.rs diff --git a/src/test/run-make/issue-37893/c.rs b/src/test/run-make-fulldeps/issue-37893/c.rs similarity index 100% rename from src/test/run-make/issue-37893/c.rs rename to src/test/run-make-fulldeps/issue-37893/c.rs diff --git a/src/test/run-make/issue-38237/Makefile b/src/test/run-make-fulldeps/issue-38237/Makefile similarity index 100% rename from src/test/run-make/issue-38237/Makefile rename to src/test/run-make-fulldeps/issue-38237/Makefile diff --git a/src/test/run-make/issue-38237/bar.rs b/src/test/run-make-fulldeps/issue-38237/bar.rs similarity index 100% rename from src/test/run-make/issue-38237/bar.rs rename to src/test/run-make-fulldeps/issue-38237/bar.rs diff --git a/src/test/run-make/issue-38237/baz.rs b/src/test/run-make-fulldeps/issue-38237/baz.rs similarity index 100% rename from src/test/run-make/issue-38237/baz.rs rename to src/test/run-make-fulldeps/issue-38237/baz.rs diff --git a/src/test/run-make/issue-38237/foo.rs b/src/test/run-make-fulldeps/issue-38237/foo.rs similarity index 100% rename from src/test/run-make/issue-38237/foo.rs rename to src/test/run-make-fulldeps/issue-38237/foo.rs diff --git a/src/test/run-make/issue-40535/Makefile b/src/test/run-make-fulldeps/issue-40535/Makefile similarity index 100% rename from src/test/run-make/issue-40535/Makefile rename to src/test/run-make-fulldeps/issue-40535/Makefile diff --git a/src/test/run-make/issue-40535/bar.rs b/src/test/run-make-fulldeps/issue-40535/bar.rs similarity index 100% rename from src/test/run-make/issue-40535/bar.rs rename to src/test/run-make-fulldeps/issue-40535/bar.rs diff --git a/src/test/run-make/issue-40535/baz.rs b/src/test/run-make-fulldeps/issue-40535/baz.rs similarity index 100% rename from src/test/run-make/issue-40535/baz.rs rename to src/test/run-make-fulldeps/issue-40535/baz.rs diff --git a/src/test/run-make/issue-40535/foo.rs b/src/test/run-make-fulldeps/issue-40535/foo.rs similarity index 100% rename from src/test/run-make/issue-40535/foo.rs rename to src/test/run-make-fulldeps/issue-40535/foo.rs diff --git a/src/test/run-make/issue-46239/Makefile b/src/test/run-make-fulldeps/issue-46239/Makefile similarity index 100% rename from src/test/run-make/issue-46239/Makefile rename to src/test/run-make-fulldeps/issue-46239/Makefile diff --git a/src/test/run-make/issue-46239/main.rs b/src/test/run-make-fulldeps/issue-46239/main.rs similarity index 100% rename from src/test/run-make/issue-46239/main.rs rename to src/test/run-make-fulldeps/issue-46239/main.rs diff --git a/src/test/run-make/issue-7349/Makefile b/src/test/run-make-fulldeps/issue-7349/Makefile similarity index 100% rename from src/test/run-make/issue-7349/Makefile rename to src/test/run-make-fulldeps/issue-7349/Makefile diff --git a/src/test/run-make/issue-7349/foo.rs b/src/test/run-make-fulldeps/issue-7349/foo.rs similarity index 100% rename from src/test/run-make/issue-7349/foo.rs rename to src/test/run-make-fulldeps/issue-7349/foo.rs diff --git a/src/test/run-make/issues-41478-43796/Makefile b/src/test/run-make-fulldeps/issues-41478-43796/Makefile similarity index 100% rename from src/test/run-make/issues-41478-43796/Makefile rename to src/test/run-make-fulldeps/issues-41478-43796/Makefile diff --git a/src/test/run-make/issues-41478-43796/a.rs b/src/test/run-make-fulldeps/issues-41478-43796/a.rs similarity index 100% rename from src/test/run-make/issues-41478-43796/a.rs rename to src/test/run-make-fulldeps/issues-41478-43796/a.rs diff --git a/src/test/run-make/libs-and-bins/Makefile b/src/test/run-make-fulldeps/libs-and-bins/Makefile similarity index 100% rename from src/test/run-make/libs-and-bins/Makefile rename to src/test/run-make-fulldeps/libs-and-bins/Makefile diff --git a/src/test/run-make/libs-and-bins/foo.rs b/src/test/run-make-fulldeps/libs-and-bins/foo.rs similarity index 100% rename from src/test/run-make/libs-and-bins/foo.rs rename to src/test/run-make-fulldeps/libs-and-bins/foo.rs diff --git a/src/test/run-make/libs-through-symlinks/Makefile b/src/test/run-make-fulldeps/libs-through-symlinks/Makefile similarity index 100% rename from src/test/run-make/libs-through-symlinks/Makefile rename to src/test/run-make-fulldeps/libs-through-symlinks/Makefile diff --git a/src/test/run-make/libs-through-symlinks/bar.rs b/src/test/run-make-fulldeps/libs-through-symlinks/bar.rs similarity index 100% rename from src/test/run-make/libs-through-symlinks/bar.rs rename to src/test/run-make-fulldeps/libs-through-symlinks/bar.rs diff --git a/src/test/run-make/libs-through-symlinks/foo.rs b/src/test/run-make-fulldeps/libs-through-symlinks/foo.rs similarity index 100% rename from src/test/run-make/libs-through-symlinks/foo.rs rename to src/test/run-make-fulldeps/libs-through-symlinks/foo.rs diff --git a/src/test/run-make/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile similarity index 100% rename from src/test/run-make/libtest-json/Makefile rename to src/test/run-make-fulldeps/libtest-json/Makefile diff --git a/src/test/run-make/libtest-json/f.rs b/src/test/run-make-fulldeps/libtest-json/f.rs similarity index 100% rename from src/test/run-make/libtest-json/f.rs rename to src/test/run-make-fulldeps/libtest-json/f.rs diff --git a/src/test/run-make/libtest-json/output.json b/src/test/run-make-fulldeps/libtest-json/output.json similarity index 100% rename from src/test/run-make/libtest-json/output.json rename to src/test/run-make-fulldeps/libtest-json/output.json diff --git a/src/test/run-make/libtest-json/validate_json.py b/src/test/run-make-fulldeps/libtest-json/validate_json.py similarity index 100% rename from src/test/run-make/libtest-json/validate_json.py rename to src/test/run-make-fulldeps/libtest-json/validate_json.py diff --git a/src/test/run-make/link-arg/Makefile b/src/test/run-make-fulldeps/link-arg/Makefile similarity index 100% rename from src/test/run-make/link-arg/Makefile rename to src/test/run-make-fulldeps/link-arg/Makefile diff --git a/src/test/run-make/link-arg/empty.rs b/src/test/run-make-fulldeps/link-arg/empty.rs similarity index 100% rename from src/test/run-make/link-arg/empty.rs rename to src/test/run-make-fulldeps/link-arg/empty.rs diff --git a/src/test/run-make/link-cfg/Makefile b/src/test/run-make-fulldeps/link-cfg/Makefile similarity index 100% rename from src/test/run-make/link-cfg/Makefile rename to src/test/run-make-fulldeps/link-cfg/Makefile diff --git a/src/test/run-make/link-cfg/dep-with-staticlib.rs b/src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs similarity index 100% rename from src/test/run-make/link-cfg/dep-with-staticlib.rs rename to src/test/run-make-fulldeps/link-cfg/dep-with-staticlib.rs diff --git a/src/test/run-make/link-cfg/dep.rs b/src/test/run-make-fulldeps/link-cfg/dep.rs similarity index 100% rename from src/test/run-make/link-cfg/dep.rs rename to src/test/run-make-fulldeps/link-cfg/dep.rs diff --git a/src/test/run-make/link-cfg/no-deps.rs b/src/test/run-make-fulldeps/link-cfg/no-deps.rs similarity index 100% rename from src/test/run-make/link-cfg/no-deps.rs rename to src/test/run-make-fulldeps/link-cfg/no-deps.rs diff --git a/src/test/run-make/link-cfg/return1.c b/src/test/run-make-fulldeps/link-cfg/return1.c similarity index 100% rename from src/test/run-make/link-cfg/return1.c rename to src/test/run-make-fulldeps/link-cfg/return1.c diff --git a/src/test/run-make/link-cfg/return2.c b/src/test/run-make-fulldeps/link-cfg/return2.c similarity index 100% rename from src/test/run-make/link-cfg/return2.c rename to src/test/run-make-fulldeps/link-cfg/return2.c diff --git a/src/test/run-make/link-cfg/return3.c b/src/test/run-make-fulldeps/link-cfg/return3.c similarity index 100% rename from src/test/run-make/link-cfg/return3.c rename to src/test/run-make-fulldeps/link-cfg/return3.c diff --git a/src/test/run-make/link-cfg/with-deps.rs b/src/test/run-make-fulldeps/link-cfg/with-deps.rs similarity index 100% rename from src/test/run-make/link-cfg/with-deps.rs rename to src/test/run-make-fulldeps/link-cfg/with-deps.rs diff --git a/src/test/run-make/link-cfg/with-staticlib-deps.rs b/src/test/run-make-fulldeps/link-cfg/with-staticlib-deps.rs similarity index 100% rename from src/test/run-make/link-cfg/with-staticlib-deps.rs rename to src/test/run-make-fulldeps/link-cfg/with-staticlib-deps.rs diff --git a/src/test/run-make/link-path-order/Makefile b/src/test/run-make-fulldeps/link-path-order/Makefile similarity index 100% rename from src/test/run-make/link-path-order/Makefile rename to src/test/run-make-fulldeps/link-path-order/Makefile diff --git a/src/test/run-make/link-path-order/correct.c b/src/test/run-make-fulldeps/link-path-order/correct.c similarity index 100% rename from src/test/run-make/link-path-order/correct.c rename to src/test/run-make-fulldeps/link-path-order/correct.c diff --git a/src/test/run-make/link-path-order/main.rs b/src/test/run-make-fulldeps/link-path-order/main.rs similarity index 100% rename from src/test/run-make/link-path-order/main.rs rename to src/test/run-make-fulldeps/link-path-order/main.rs diff --git a/src/test/run-make/link-path-order/wrong.c b/src/test/run-make-fulldeps/link-path-order/wrong.c similarity index 100% rename from src/test/run-make/link-path-order/wrong.c rename to src/test/run-make-fulldeps/link-path-order/wrong.c diff --git a/src/test/run-make/linkage-attr-on-static/Makefile b/src/test/run-make-fulldeps/linkage-attr-on-static/Makefile similarity index 100% rename from src/test/run-make/linkage-attr-on-static/Makefile rename to src/test/run-make-fulldeps/linkage-attr-on-static/Makefile diff --git a/src/test/run-make/linkage-attr-on-static/bar.rs b/src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs similarity index 100% rename from src/test/run-make/linkage-attr-on-static/bar.rs rename to src/test/run-make-fulldeps/linkage-attr-on-static/bar.rs diff --git a/src/test/run-make/linkage-attr-on-static/foo.c b/src/test/run-make-fulldeps/linkage-attr-on-static/foo.c similarity index 100% rename from src/test/run-make/linkage-attr-on-static/foo.c rename to src/test/run-make-fulldeps/linkage-attr-on-static/foo.c diff --git a/src/test/run-make/linker-output-non-utf8/Makefile b/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile similarity index 100% rename from src/test/run-make/linker-output-non-utf8/Makefile rename to src/test/run-make-fulldeps/linker-output-non-utf8/Makefile diff --git a/src/test/run-make/linker-output-non-utf8/exec.rs b/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs similarity index 100% rename from src/test/run-make/linker-output-non-utf8/exec.rs rename to src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs diff --git a/src/test/run-make/linker-output-non-utf8/library.rs b/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs similarity index 100% rename from src/test/run-make/linker-output-non-utf8/library.rs rename to src/test/run-make-fulldeps/linker-output-non-utf8/library.rs diff --git a/src/test/run-make/llvm-pass/Makefile b/src/test/run-make-fulldeps/llvm-pass/Makefile similarity index 100% rename from src/test/run-make/llvm-pass/Makefile rename to src/test/run-make-fulldeps/llvm-pass/Makefile diff --git a/src/test/run-make/llvm-pass/llvm-function-pass.so.cc b/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc similarity index 100% rename from src/test/run-make/llvm-pass/llvm-function-pass.so.cc rename to src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc diff --git a/src/test/run-make/llvm-pass/llvm-module-pass.so.cc b/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc similarity index 100% rename from src/test/run-make/llvm-pass/llvm-module-pass.so.cc rename to src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc diff --git a/src/test/run-make/llvm-pass/main.rs b/src/test/run-make-fulldeps/llvm-pass/main.rs similarity index 100% rename from src/test/run-make/llvm-pass/main.rs rename to src/test/run-make-fulldeps/llvm-pass/main.rs diff --git a/src/test/run-make/llvm-pass/plugin.rs b/src/test/run-make-fulldeps/llvm-pass/plugin.rs similarity index 100% rename from src/test/run-make/llvm-pass/plugin.rs rename to src/test/run-make-fulldeps/llvm-pass/plugin.rs diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/Makefile b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/Makefile similarity index 100% rename from src/test/run-make/long-linker-command-lines-cmd-exe/Makefile rename to src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/Makefile diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.bat similarity index 100% rename from src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat rename to src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.bat diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs similarity index 100% rename from src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs rename to src/test/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs diff --git a/src/test/run-make/long-linker-command-lines/Makefile b/src/test/run-make-fulldeps/long-linker-command-lines/Makefile similarity index 75% rename from src/test/run-make/long-linker-command-lines/Makefile rename to src/test/run-make-fulldeps/long-linker-command-lines/Makefile index 309a27fe503a..5876fbc94bc9 100644 --- a/src/test/run-make/long-linker-command-lines/Makefile +++ b/src/test/run-make-fulldeps/long-linker-command-lines/Makefile @@ -1,5 +1,5 @@ -include ../tools.mk all: - $(RUSTC) foo.rs -g + $(RUSTC) foo.rs -g -O RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) diff --git a/src/test/run-make/long-linker-command-lines/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs similarity index 100% rename from src/test/run-make/long-linker-command-lines/foo.rs rename to src/test/run-make-fulldeps/long-linker-command-lines/foo.rs diff --git a/src/test/run-make/longjmp-across-rust/Makefile b/src/test/run-make-fulldeps/longjmp-across-rust/Makefile similarity index 100% rename from src/test/run-make/longjmp-across-rust/Makefile rename to src/test/run-make-fulldeps/longjmp-across-rust/Makefile diff --git a/src/test/run-make/longjmp-across-rust/foo.c b/src/test/run-make-fulldeps/longjmp-across-rust/foo.c similarity index 100% rename from src/test/run-make/longjmp-across-rust/foo.c rename to src/test/run-make-fulldeps/longjmp-across-rust/foo.c diff --git a/src/test/run-make/longjmp-across-rust/main.rs b/src/test/run-make-fulldeps/longjmp-across-rust/main.rs similarity index 100% rename from src/test/run-make/longjmp-across-rust/main.rs rename to src/test/run-make-fulldeps/longjmp-across-rust/main.rs diff --git a/src/test/run-make/ls-metadata/Makefile b/src/test/run-make-fulldeps/ls-metadata/Makefile similarity index 100% rename from src/test/run-make/ls-metadata/Makefile rename to src/test/run-make-fulldeps/ls-metadata/Makefile diff --git a/src/test/run-make/ls-metadata/foo.rs b/src/test/run-make-fulldeps/ls-metadata/foo.rs similarity index 100% rename from src/test/run-make/ls-metadata/foo.rs rename to src/test/run-make-fulldeps/ls-metadata/foo.rs diff --git a/src/test/run-make/lto-no-link-whole-rlib/Makefile b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/Makefile similarity index 100% rename from src/test/run-make/lto-no-link-whole-rlib/Makefile rename to src/test/run-make-fulldeps/lto-no-link-whole-rlib/Makefile diff --git a/src/test/run-make/lto-no-link-whole-rlib/bar.c b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/bar.c similarity index 100% rename from src/test/run-make/lto-no-link-whole-rlib/bar.c rename to src/test/run-make-fulldeps/lto-no-link-whole-rlib/bar.c diff --git a/src/test/run-make/lto-no-link-whole-rlib/foo.c b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/foo.c similarity index 100% rename from src/test/run-make/lto-no-link-whole-rlib/foo.c rename to src/test/run-make-fulldeps/lto-no-link-whole-rlib/foo.c diff --git a/src/test/run-make/lto-no-link-whole-rlib/lib1.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs similarity index 100% rename from src/test/run-make/lto-no-link-whole-rlib/lib1.rs rename to src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib1.rs diff --git a/src/test/run-make/lto-no-link-whole-rlib/lib2.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs similarity index 100% rename from src/test/run-make/lto-no-link-whole-rlib/lib2.rs rename to src/test/run-make-fulldeps/lto-no-link-whole-rlib/lib2.rs diff --git a/src/test/run-make/lto-no-link-whole-rlib/main.rs b/src/test/run-make-fulldeps/lto-no-link-whole-rlib/main.rs similarity index 100% rename from src/test/run-make/lto-no-link-whole-rlib/main.rs rename to src/test/run-make-fulldeps/lto-no-link-whole-rlib/main.rs diff --git a/src/test/run-make/lto-readonly-lib/Makefile b/src/test/run-make-fulldeps/lto-readonly-lib/Makefile similarity index 100% rename from src/test/run-make/lto-readonly-lib/Makefile rename to src/test/run-make-fulldeps/lto-readonly-lib/Makefile diff --git a/src/test/run-make/lto-readonly-lib/lib.rs b/src/test/run-make-fulldeps/lto-readonly-lib/lib.rs similarity index 100% rename from src/test/run-make/lto-readonly-lib/lib.rs rename to src/test/run-make-fulldeps/lto-readonly-lib/lib.rs diff --git a/src/test/run-make/lto-readonly-lib/main.rs b/src/test/run-make-fulldeps/lto-readonly-lib/main.rs similarity index 100% rename from src/test/run-make/lto-readonly-lib/main.rs rename to src/test/run-make-fulldeps/lto-readonly-lib/main.rs diff --git a/src/test/run-make/lto-smoke-c/Makefile b/src/test/run-make-fulldeps/lto-smoke-c/Makefile similarity index 100% rename from src/test/run-make/lto-smoke-c/Makefile rename to src/test/run-make-fulldeps/lto-smoke-c/Makefile diff --git a/src/test/run-make/lto-smoke-c/bar.c b/src/test/run-make-fulldeps/lto-smoke-c/bar.c similarity index 100% rename from src/test/run-make/lto-smoke-c/bar.c rename to src/test/run-make-fulldeps/lto-smoke-c/bar.c diff --git a/src/test/run-make/lto-smoke-c/foo.rs b/src/test/run-make-fulldeps/lto-smoke-c/foo.rs similarity index 100% rename from src/test/run-make/lto-smoke-c/foo.rs rename to src/test/run-make-fulldeps/lto-smoke-c/foo.rs diff --git a/src/test/run-make/lto-smoke/Makefile b/src/test/run-make-fulldeps/lto-smoke/Makefile similarity index 100% rename from src/test/run-make/lto-smoke/Makefile rename to src/test/run-make-fulldeps/lto-smoke/Makefile diff --git a/src/test/run-make/lto-smoke/lib.rs b/src/test/run-make-fulldeps/lto-smoke/lib.rs similarity index 100% rename from src/test/run-make/lto-smoke/lib.rs rename to src/test/run-make-fulldeps/lto-smoke/lib.rs diff --git a/src/test/run-make/lto-smoke/main.rs b/src/test/run-make-fulldeps/lto-smoke/main.rs similarity index 100% rename from src/test/run-make/lto-smoke/main.rs rename to src/test/run-make-fulldeps/lto-smoke/main.rs diff --git a/src/test/run-make/manual-crate-name/Makefile b/src/test/run-make-fulldeps/manual-crate-name/Makefile similarity index 100% rename from src/test/run-make/manual-crate-name/Makefile rename to src/test/run-make-fulldeps/manual-crate-name/Makefile diff --git a/src/test/run-make/manual-crate-name/bar.rs b/src/test/run-make-fulldeps/manual-crate-name/bar.rs similarity index 100% rename from src/test/run-make/manual-crate-name/bar.rs rename to src/test/run-make-fulldeps/manual-crate-name/bar.rs diff --git a/src/test/run-make/manual-link/Makefile b/src/test/run-make-fulldeps/manual-link/Makefile similarity index 100% rename from src/test/run-make/manual-link/Makefile rename to src/test/run-make-fulldeps/manual-link/Makefile diff --git a/src/test/run-make/manual-link/bar.c b/src/test/run-make-fulldeps/manual-link/bar.c similarity index 100% rename from src/test/run-make/manual-link/bar.c rename to src/test/run-make-fulldeps/manual-link/bar.c diff --git a/src/test/run-make/manual-link/foo.c b/src/test/run-make-fulldeps/manual-link/foo.c similarity index 100% rename from src/test/run-make/manual-link/foo.c rename to src/test/run-make-fulldeps/manual-link/foo.c diff --git a/src/test/run-make/manual-link/foo.rs b/src/test/run-make-fulldeps/manual-link/foo.rs similarity index 100% rename from src/test/run-make/manual-link/foo.rs rename to src/test/run-make-fulldeps/manual-link/foo.rs diff --git a/src/test/run-make/manual-link/main.rs b/src/test/run-make-fulldeps/manual-link/main.rs similarity index 100% rename from src/test/run-make/manual-link/main.rs rename to src/test/run-make-fulldeps/manual-link/main.rs diff --git a/src/test/run-make/many-crates-but-no-match/Makefile b/src/test/run-make-fulldeps/many-crates-but-no-match/Makefile similarity index 100% rename from src/test/run-make/many-crates-but-no-match/Makefile rename to src/test/run-make-fulldeps/many-crates-but-no-match/Makefile diff --git a/src/test/run-make/many-crates-but-no-match/crateA1.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA1.rs similarity index 100% rename from src/test/run-make/many-crates-but-no-match/crateA1.rs rename to src/test/run-make-fulldeps/many-crates-but-no-match/crateA1.rs diff --git a/src/test/run-make/many-crates-but-no-match/crateA2.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA2.rs similarity index 100% rename from src/test/run-make/many-crates-but-no-match/crateA2.rs rename to src/test/run-make-fulldeps/many-crates-but-no-match/crateA2.rs diff --git a/src/test/run-make/many-crates-but-no-match/crateA3.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateA3.rs similarity index 100% rename from src/test/run-make/many-crates-but-no-match/crateA3.rs rename to src/test/run-make-fulldeps/many-crates-but-no-match/crateA3.rs diff --git a/src/test/run-make/many-crates-but-no-match/crateB.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateB.rs similarity index 100% rename from src/test/run-make/many-crates-but-no-match/crateB.rs rename to src/test/run-make-fulldeps/many-crates-but-no-match/crateB.rs diff --git a/src/test/run-make/many-crates-but-no-match/crateC.rs b/src/test/run-make-fulldeps/many-crates-but-no-match/crateC.rs similarity index 100% rename from src/test/run-make/many-crates-but-no-match/crateC.rs rename to src/test/run-make-fulldeps/many-crates-but-no-match/crateC.rs diff --git a/src/test/run-make/metadata-flag-frobs-symbols/Makefile b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile similarity index 100% rename from src/test/run-make/metadata-flag-frobs-symbols/Makefile rename to src/test/run-make-fulldeps/metadata-flag-frobs-symbols/Makefile diff --git a/src/test/run-make/metadata-flag-frobs-symbols/bar.rs b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/bar.rs similarity index 100% rename from src/test/run-make/metadata-flag-frobs-symbols/bar.rs rename to src/test/run-make-fulldeps/metadata-flag-frobs-symbols/bar.rs diff --git a/src/test/run-make/metadata-flag-frobs-symbols/foo.rs b/src/test/run-make-fulldeps/metadata-flag-frobs-symbols/foo.rs similarity index 100% rename from src/test/run-make/metadata-flag-frobs-symbols/foo.rs rename to src/test/run-make-fulldeps/metadata-flag-frobs-symbols/foo.rs diff --git a/src/test/run-make/min-global-align/Makefile b/src/test/run-make-fulldeps/min-global-align/Makefile similarity index 100% rename from src/test/run-make/min-global-align/Makefile rename to src/test/run-make-fulldeps/min-global-align/Makefile diff --git a/src/test/run-make/min-global-align/min_global_align.rs b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs similarity index 100% rename from src/test/run-make/min-global-align/min_global_align.rs rename to src/test/run-make-fulldeps/min-global-align/min_global_align.rs diff --git a/src/test/run-make/mismatching-target-triples/Makefile b/src/test/run-make-fulldeps/mismatching-target-triples/Makefile similarity index 100% rename from src/test/run-make/mismatching-target-triples/Makefile rename to src/test/run-make-fulldeps/mismatching-target-triples/Makefile diff --git a/src/test/run-make/mismatching-target-triples/bar.rs b/src/test/run-make-fulldeps/mismatching-target-triples/bar.rs similarity index 100% rename from src/test/run-make/mismatching-target-triples/bar.rs rename to src/test/run-make-fulldeps/mismatching-target-triples/bar.rs diff --git a/src/test/run-make/mismatching-target-triples/foo.rs b/src/test/run-make-fulldeps/mismatching-target-triples/foo.rs similarity index 100% rename from src/test/run-make/mismatching-target-triples/foo.rs rename to src/test/run-make-fulldeps/mismatching-target-triples/foo.rs diff --git a/src/test/run-make/missing-crate-dependency/Makefile b/src/test/run-make-fulldeps/missing-crate-dependency/Makefile similarity index 100% rename from src/test/run-make/missing-crate-dependency/Makefile rename to src/test/run-make-fulldeps/missing-crate-dependency/Makefile diff --git a/src/test/run-make/missing-crate-dependency/crateA.rs b/src/test/run-make-fulldeps/missing-crate-dependency/crateA.rs similarity index 100% rename from src/test/run-make/missing-crate-dependency/crateA.rs rename to src/test/run-make-fulldeps/missing-crate-dependency/crateA.rs diff --git a/src/test/run-make/missing-crate-dependency/crateB.rs b/src/test/run-make-fulldeps/missing-crate-dependency/crateB.rs similarity index 100% rename from src/test/run-make/missing-crate-dependency/crateB.rs rename to src/test/run-make-fulldeps/missing-crate-dependency/crateB.rs diff --git a/src/test/run-make/missing-crate-dependency/crateC.rs b/src/test/run-make-fulldeps/missing-crate-dependency/crateC.rs similarity index 100% rename from src/test/run-make/missing-crate-dependency/crateC.rs rename to src/test/run-make-fulldeps/missing-crate-dependency/crateC.rs diff --git a/src/test/run-make/mixing-deps/Makefile b/src/test/run-make-fulldeps/mixing-deps/Makefile similarity index 100% rename from src/test/run-make/mixing-deps/Makefile rename to src/test/run-make-fulldeps/mixing-deps/Makefile diff --git a/src/test/run-make/mixing-deps/both.rs b/src/test/run-make-fulldeps/mixing-deps/both.rs similarity index 100% rename from src/test/run-make/mixing-deps/both.rs rename to src/test/run-make-fulldeps/mixing-deps/both.rs diff --git a/src/test/run-make/mixing-deps/dylib.rs b/src/test/run-make-fulldeps/mixing-deps/dylib.rs similarity index 100% rename from src/test/run-make/mixing-deps/dylib.rs rename to src/test/run-make-fulldeps/mixing-deps/dylib.rs diff --git a/src/test/run-make/mixing-deps/prog.rs b/src/test/run-make-fulldeps/mixing-deps/prog.rs similarity index 100% rename from src/test/run-make/mixing-deps/prog.rs rename to src/test/run-make-fulldeps/mixing-deps/prog.rs diff --git a/src/test/run-make/mixing-formats/Makefile b/src/test/run-make-fulldeps/mixing-formats/Makefile similarity index 100% rename from src/test/run-make/mixing-formats/Makefile rename to src/test/run-make-fulldeps/mixing-formats/Makefile diff --git a/src/test/run-make/mixing-formats/bar1.rs b/src/test/run-make-fulldeps/mixing-formats/bar1.rs similarity index 100% rename from src/test/run-make/mixing-formats/bar1.rs rename to src/test/run-make-fulldeps/mixing-formats/bar1.rs diff --git a/src/test/run-make/mixing-formats/bar2.rs b/src/test/run-make-fulldeps/mixing-formats/bar2.rs similarity index 100% rename from src/test/run-make/mixing-formats/bar2.rs rename to src/test/run-make-fulldeps/mixing-formats/bar2.rs diff --git a/src/test/run-make/mixing-formats/baz.rs b/src/test/run-make-fulldeps/mixing-formats/baz.rs similarity index 100% rename from src/test/run-make/mixing-formats/baz.rs rename to src/test/run-make-fulldeps/mixing-formats/baz.rs diff --git a/src/test/run-make/mixing-formats/baz2.rs b/src/test/run-make-fulldeps/mixing-formats/baz2.rs similarity index 100% rename from src/test/run-make/mixing-formats/baz2.rs rename to src/test/run-make-fulldeps/mixing-formats/baz2.rs diff --git a/src/test/run-make/mixing-formats/foo.rs b/src/test/run-make-fulldeps/mixing-formats/foo.rs similarity index 100% rename from src/test/run-make/mixing-formats/foo.rs rename to src/test/run-make-fulldeps/mixing-formats/foo.rs diff --git a/src/test/run-make/mixing-libs/Makefile b/src/test/run-make-fulldeps/mixing-libs/Makefile similarity index 100% rename from src/test/run-make/mixing-libs/Makefile rename to src/test/run-make-fulldeps/mixing-libs/Makefile diff --git a/src/test/run-make/mixing-libs/dylib.rs b/src/test/run-make-fulldeps/mixing-libs/dylib.rs similarity index 100% rename from src/test/run-make/mixing-libs/dylib.rs rename to src/test/run-make-fulldeps/mixing-libs/dylib.rs diff --git a/src/test/run-make/mixing-libs/prog.rs b/src/test/run-make-fulldeps/mixing-libs/prog.rs similarity index 100% rename from src/test/run-make/mixing-libs/prog.rs rename to src/test/run-make-fulldeps/mixing-libs/prog.rs diff --git a/src/test/run-make/mixing-libs/rlib.rs b/src/test/run-make-fulldeps/mixing-libs/rlib.rs similarity index 100% rename from src/test/run-make/mixing-libs/rlib.rs rename to src/test/run-make-fulldeps/mixing-libs/rlib.rs diff --git a/src/test/run-make/msvc-opt-minsize/Makefile b/src/test/run-make-fulldeps/msvc-opt-minsize/Makefile similarity index 100% rename from src/test/run-make/msvc-opt-minsize/Makefile rename to src/test/run-make-fulldeps/msvc-opt-minsize/Makefile diff --git a/src/test/run-make/msvc-opt-minsize/foo.rs b/src/test/run-make-fulldeps/msvc-opt-minsize/foo.rs similarity index 100% rename from src/test/run-make/msvc-opt-minsize/foo.rs rename to src/test/run-make-fulldeps/msvc-opt-minsize/foo.rs diff --git a/src/test/run-make/multiple-emits/Makefile b/src/test/run-make-fulldeps/multiple-emits/Makefile similarity index 100% rename from src/test/run-make/multiple-emits/Makefile rename to src/test/run-make-fulldeps/multiple-emits/Makefile diff --git a/src/test/run-make/multiple-emits/foo.rs b/src/test/run-make-fulldeps/multiple-emits/foo.rs similarity index 100% rename from src/test/run-make/multiple-emits/foo.rs rename to src/test/run-make-fulldeps/multiple-emits/foo.rs diff --git a/src/test/run-make/no-builtins-lto/Makefile b/src/test/run-make-fulldeps/no-builtins-lto/Makefile similarity index 100% rename from src/test/run-make/no-builtins-lto/Makefile rename to src/test/run-make-fulldeps/no-builtins-lto/Makefile diff --git a/src/test/run-make/no-builtins-lto/main.rs b/src/test/run-make-fulldeps/no-builtins-lto/main.rs similarity index 100% rename from src/test/run-make/no-builtins-lto/main.rs rename to src/test/run-make-fulldeps/no-builtins-lto/main.rs diff --git a/src/test/run-make/no-builtins-lto/no_builtins.rs b/src/test/run-make-fulldeps/no-builtins-lto/no_builtins.rs similarity index 100% rename from src/test/run-make/no-builtins-lto/no_builtins.rs rename to src/test/run-make-fulldeps/no-builtins-lto/no_builtins.rs diff --git a/src/test/run-make/no-duplicate-libs/Makefile b/src/test/run-make-fulldeps/no-duplicate-libs/Makefile similarity index 100% rename from src/test/run-make/no-duplicate-libs/Makefile rename to src/test/run-make-fulldeps/no-duplicate-libs/Makefile diff --git a/src/test/run-make/no-duplicate-libs/bar.c b/src/test/run-make-fulldeps/no-duplicate-libs/bar.c similarity index 100% rename from src/test/run-make/no-duplicate-libs/bar.c rename to src/test/run-make-fulldeps/no-duplicate-libs/bar.c diff --git a/src/test/run-make/no-duplicate-libs/foo.c b/src/test/run-make-fulldeps/no-duplicate-libs/foo.c similarity index 100% rename from src/test/run-make/no-duplicate-libs/foo.c rename to src/test/run-make-fulldeps/no-duplicate-libs/foo.c diff --git a/src/test/run-make/no-duplicate-libs/main.rs b/src/test/run-make-fulldeps/no-duplicate-libs/main.rs similarity index 100% rename from src/test/run-make/no-duplicate-libs/main.rs rename to src/test/run-make-fulldeps/no-duplicate-libs/main.rs diff --git a/src/test/run-make/no-integrated-as/Makefile b/src/test/run-make-fulldeps/no-integrated-as/Makefile similarity index 100% rename from src/test/run-make/no-integrated-as/Makefile rename to src/test/run-make-fulldeps/no-integrated-as/Makefile diff --git a/src/test/run-make/no-integrated-as/hello.rs b/src/test/run-make-fulldeps/no-integrated-as/hello.rs similarity index 100% rename from src/test/run-make/no-integrated-as/hello.rs rename to src/test/run-make-fulldeps/no-integrated-as/hello.rs diff --git a/src/test/run-make/no-intermediate-extras/Makefile b/src/test/run-make-fulldeps/no-intermediate-extras/Makefile similarity index 100% rename from src/test/run-make/no-intermediate-extras/Makefile rename to src/test/run-make-fulldeps/no-intermediate-extras/Makefile diff --git a/src/test/run-make/no-intermediate-extras/foo.rs b/src/test/run-make-fulldeps/no-intermediate-extras/foo.rs similarity index 100% rename from src/test/run-make/no-intermediate-extras/foo.rs rename to src/test/run-make-fulldeps/no-intermediate-extras/foo.rs diff --git a/src/test/run-make/obey-crate-type-flag/Makefile b/src/test/run-make-fulldeps/obey-crate-type-flag/Makefile similarity index 100% rename from src/test/run-make/obey-crate-type-flag/Makefile rename to src/test/run-make-fulldeps/obey-crate-type-flag/Makefile diff --git a/src/test/run-make/obey-crate-type-flag/test.rs b/src/test/run-make-fulldeps/obey-crate-type-flag/test.rs similarity index 100% rename from src/test/run-make/obey-crate-type-flag/test.rs rename to src/test/run-make-fulldeps/obey-crate-type-flag/test.rs diff --git a/src/test/run-make/output-filename-conflicts-with-directory/Makefile b/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/Makefile similarity index 100% rename from src/test/run-make/output-filename-conflicts-with-directory/Makefile rename to src/test/run-make-fulldeps/output-filename-conflicts-with-directory/Makefile diff --git a/src/test/run-make/output-filename-conflicts-with-directory/foo.rs b/src/test/run-make-fulldeps/output-filename-conflicts-with-directory/foo.rs similarity index 100% rename from src/test/run-make/output-filename-conflicts-with-directory/foo.rs rename to src/test/run-make-fulldeps/output-filename-conflicts-with-directory/foo.rs diff --git a/src/test/run-make/output-filename-overwrites-input/Makefile b/src/test/run-make-fulldeps/output-filename-overwrites-input/Makefile similarity index 100% rename from src/test/run-make/output-filename-overwrites-input/Makefile rename to src/test/run-make-fulldeps/output-filename-overwrites-input/Makefile diff --git a/src/test/run-make/output-filename-overwrites-input/bar.rs b/src/test/run-make-fulldeps/output-filename-overwrites-input/bar.rs similarity index 100% rename from src/test/run-make/output-filename-overwrites-input/bar.rs rename to src/test/run-make-fulldeps/output-filename-overwrites-input/bar.rs diff --git a/src/test/run-make/output-filename-overwrites-input/foo.rs b/src/test/run-make-fulldeps/output-filename-overwrites-input/foo.rs similarity index 100% rename from src/test/run-make/output-filename-overwrites-input/foo.rs rename to src/test/run-make-fulldeps/output-filename-overwrites-input/foo.rs diff --git a/src/test/run-make/output-type-permutations/Makefile b/src/test/run-make-fulldeps/output-type-permutations/Makefile similarity index 100% rename from src/test/run-make/output-type-permutations/Makefile rename to src/test/run-make-fulldeps/output-type-permutations/Makefile diff --git a/src/test/run-make/output-type-permutations/foo.rs b/src/test/run-make-fulldeps/output-type-permutations/foo.rs similarity index 100% rename from src/test/run-make/output-type-permutations/foo.rs rename to src/test/run-make-fulldeps/output-type-permutations/foo.rs diff --git a/src/test/run-make/output-with-hyphens/Makefile b/src/test/run-make-fulldeps/output-with-hyphens/Makefile similarity index 100% rename from src/test/run-make/output-with-hyphens/Makefile rename to src/test/run-make-fulldeps/output-with-hyphens/Makefile diff --git a/src/test/run-make/output-with-hyphens/foo-bar.rs b/src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs similarity index 100% rename from src/test/run-make/output-with-hyphens/foo-bar.rs rename to src/test/run-make-fulldeps/output-with-hyphens/foo-bar.rs diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile new file mode 100644 index 000000000000..e8c695f52bec --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: +ifeq ($(PROFILER_SUPPORT),1) + $(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1) +endif diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/test.rs b/src/test/run-make-fulldeps/pgo-gen-lto/test.rs new file mode 100644 index 000000000000..3f07b46791d2 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen-lto/test.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile new file mode 100644 index 000000000000..7dc227b5a145 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: +ifeq ($(PROFILER_SUPPORT),1) + $(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1) +endif diff --git a/src/test/run-make-fulldeps/pgo-gen/test.rs b/src/test/run-make-fulldeps/pgo-gen/test.rs new file mode 100644 index 000000000000..3f07b46791d2 --- /dev/null +++ b/src/test/run-make-fulldeps/pgo-gen/test.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/run-make/prefer-dylib/Makefile b/src/test/run-make-fulldeps/prefer-dylib/Makefile similarity index 100% rename from src/test/run-make/prefer-dylib/Makefile rename to src/test/run-make-fulldeps/prefer-dylib/Makefile diff --git a/src/test/run-make/prefer-dylib/bar.rs b/src/test/run-make-fulldeps/prefer-dylib/bar.rs similarity index 100% rename from src/test/run-make/prefer-dylib/bar.rs rename to src/test/run-make-fulldeps/prefer-dylib/bar.rs diff --git a/src/test/run-make/prefer-dylib/foo.rs b/src/test/run-make-fulldeps/prefer-dylib/foo.rs similarity index 100% rename from src/test/run-make/prefer-dylib/foo.rs rename to src/test/run-make-fulldeps/prefer-dylib/foo.rs diff --git a/src/test/run-make/prefer-rlib/Makefile b/src/test/run-make-fulldeps/prefer-rlib/Makefile similarity index 100% rename from src/test/run-make/prefer-rlib/Makefile rename to src/test/run-make-fulldeps/prefer-rlib/Makefile diff --git a/src/test/run-make/prefer-rlib/bar.rs b/src/test/run-make-fulldeps/prefer-rlib/bar.rs similarity index 100% rename from src/test/run-make/prefer-rlib/bar.rs rename to src/test/run-make-fulldeps/prefer-rlib/bar.rs diff --git a/src/test/run-make/prefer-rlib/foo.rs b/src/test/run-make-fulldeps/prefer-rlib/foo.rs similarity index 100% rename from src/test/run-make/prefer-rlib/foo.rs rename to src/test/run-make-fulldeps/prefer-rlib/foo.rs diff --git a/src/test/run-make/pretty-expanded-hygiene/Makefile b/src/test/run-make-fulldeps/pretty-expanded-hygiene/Makefile similarity index 100% rename from src/test/run-make/pretty-expanded-hygiene/Makefile rename to src/test/run-make-fulldeps/pretty-expanded-hygiene/Makefile diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make-fulldeps/pretty-expanded-hygiene/input.pp.rs similarity index 100% rename from src/test/run-make/pretty-expanded-hygiene/input.pp.rs rename to src/test/run-make-fulldeps/pretty-expanded-hygiene/input.pp.rs diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make-fulldeps/pretty-expanded-hygiene/input.rs similarity index 100% rename from src/test/run-make/pretty-expanded-hygiene/input.rs rename to src/test/run-make-fulldeps/pretty-expanded-hygiene/input.rs diff --git a/src/test/run-make/pretty-expanded/Makefile b/src/test/run-make-fulldeps/pretty-expanded/Makefile similarity index 100% rename from src/test/run-make/pretty-expanded/Makefile rename to src/test/run-make-fulldeps/pretty-expanded/Makefile diff --git a/src/test/run-make/pretty-expanded/input.rs b/src/test/run-make-fulldeps/pretty-expanded/input.rs similarity index 100% rename from src/test/run-make/pretty-expanded/input.rs rename to src/test/run-make-fulldeps/pretty-expanded/input.rs diff --git a/src/test/run-make/pretty-print-path-suffix/Makefile b/src/test/run-make-fulldeps/pretty-print-path-suffix/Makefile similarity index 100% rename from src/test/run-make/pretty-print-path-suffix/Makefile rename to src/test/run-make-fulldeps/pretty-print-path-suffix/Makefile diff --git a/src/test/run-make/pretty-print-path-suffix/foo.pp b/src/test/run-make-fulldeps/pretty-print-path-suffix/foo.pp similarity index 100% rename from src/test/run-make/pretty-print-path-suffix/foo.pp rename to src/test/run-make-fulldeps/pretty-print-path-suffix/foo.pp diff --git a/src/test/run-make/pretty-print-path-suffix/foo_method.pp b/src/test/run-make-fulldeps/pretty-print-path-suffix/foo_method.pp similarity index 100% rename from src/test/run-make/pretty-print-path-suffix/foo_method.pp rename to src/test/run-make-fulldeps/pretty-print-path-suffix/foo_method.pp diff --git a/src/test/run-make/pretty-print-path-suffix/input.rs b/src/test/run-make-fulldeps/pretty-print-path-suffix/input.rs similarity index 100% rename from src/test/run-make/pretty-print-path-suffix/input.rs rename to src/test/run-make-fulldeps/pretty-print-path-suffix/input.rs diff --git a/src/test/run-make/pretty-print-path-suffix/nest_foo.pp b/src/test/run-make-fulldeps/pretty-print-path-suffix/nest_foo.pp similarity index 100% rename from src/test/run-make/pretty-print-path-suffix/nest_foo.pp rename to src/test/run-make-fulldeps/pretty-print-path-suffix/nest_foo.pp diff --git a/src/test/run-make/pretty-print-to-file/Makefile b/src/test/run-make-fulldeps/pretty-print-to-file/Makefile similarity index 100% rename from src/test/run-make/pretty-print-to-file/Makefile rename to src/test/run-make-fulldeps/pretty-print-to-file/Makefile diff --git a/src/test/run-make/pretty-print-to-file/input.pp b/src/test/run-make-fulldeps/pretty-print-to-file/input.pp similarity index 100% rename from src/test/run-make/pretty-print-to-file/input.pp rename to src/test/run-make-fulldeps/pretty-print-to-file/input.pp diff --git a/src/test/run-make/pretty-print-to-file/input.rs b/src/test/run-make-fulldeps/pretty-print-to-file/input.rs similarity index 100% rename from src/test/run-make/pretty-print-to-file/input.rs rename to src/test/run-make-fulldeps/pretty-print-to-file/input.rs diff --git a/src/test/run-make/print-cfg/Makefile b/src/test/run-make-fulldeps/print-cfg/Makefile similarity index 100% rename from src/test/run-make/print-cfg/Makefile rename to src/test/run-make-fulldeps/print-cfg/Makefile diff --git a/src/test/run-make/print-target-list/Makefile b/src/test/run-make-fulldeps/print-target-list/Makefile similarity index 100% rename from src/test/run-make/print-target-list/Makefile rename to src/test/run-make-fulldeps/print-target-list/Makefile diff --git a/src/test/run-make/profile/Makefile b/src/test/run-make-fulldeps/profile/Makefile similarity index 100% rename from src/test/run-make/profile/Makefile rename to src/test/run-make-fulldeps/profile/Makefile diff --git a/src/test/run-make/profile/test.rs b/src/test/run-make-fulldeps/profile/test.rs similarity index 100% rename from src/test/run-make/profile/test.rs rename to src/test/run-make-fulldeps/profile/test.rs diff --git a/src/test/run-make/prune-link-args/Makefile b/src/test/run-make-fulldeps/prune-link-args/Makefile similarity index 100% rename from src/test/run-make/prune-link-args/Makefile rename to src/test/run-make-fulldeps/prune-link-args/Makefile diff --git a/src/test/run-make/prune-link-args/empty.rs b/src/test/run-make-fulldeps/prune-link-args/empty.rs similarity index 100% rename from src/test/run-make/prune-link-args/empty.rs rename to src/test/run-make-fulldeps/prune-link-args/empty.rs diff --git a/src/test/run-make/relocation-model/Makefile b/src/test/run-make-fulldeps/relocation-model/Makefile similarity index 100% rename from src/test/run-make/relocation-model/Makefile rename to src/test/run-make-fulldeps/relocation-model/Makefile diff --git a/src/test/run-make/relocation-model/foo.rs b/src/test/run-make-fulldeps/relocation-model/foo.rs similarity index 100% rename from src/test/run-make/relocation-model/foo.rs rename to src/test/run-make-fulldeps/relocation-model/foo.rs diff --git a/src/test/run-make-fulldeps/relro-levels/Makefile b/src/test/run-make-fulldeps/relro-levels/Makefile new file mode 100644 index 000000000000..673ba9a9a02c --- /dev/null +++ b/src/test/run-make-fulldeps/relro-levels/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +# This tests the different -Zrelro-level values, and makes sure that they they work properly. + +all: +ifeq ($(UNAME),Linux) + # Ensure that binaries built with the full relro level links them with both + # RELRO and BIND_NOW for doing eager symbol resolving. + $(RUSTC) -Zrelro-level=full hello.rs + readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO + readelf -d $(TMPDIR)/hello | grep -q BIND_NOW + + $(RUSTC) -Zrelro-level=partial hello.rs + readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO + + # Ensure that we're *not* built with RELRO when setting it to off. We do + # not want to check for BIND_NOW however, as the linker might have that + # enabled by default. + $(RUSTC) -Zrelro-level=off hello.rs + ! readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO +endif diff --git a/src/test/run-make/sanitizer-invalid-cratetype/hello.rs b/src/test/run-make-fulldeps/relro-levels/hello.rs similarity index 100% rename from src/test/run-make/sanitizer-invalid-cratetype/hello.rs rename to src/test/run-make-fulldeps/relro-levels/hello.rs diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make-fulldeps/reproducible-build/Makefile similarity index 64% rename from src/test/run-make/reproducible-build/Makefile rename to src/test/run-make-fulldeps/reproducible-build/Makefile index 629e61850512..ca76a5e5d77b 100644 --- a/src/test/run-make/reproducible-build/Makefile +++ b/src/test/run-make-fulldeps/reproducible-build/Makefile @@ -10,31 +10,27 @@ all: \ smoke: rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" - $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" - $(B2) - nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm" - nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm" - cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1 + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" debug: rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O $(RUSTC) reproducible-build-aux.rs -g - $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" -g - $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" -g - nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1-debug.nm" - nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2-debug.nm" - cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1 + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -g + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" opt: rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) linker.rs -O $(RUSTC) reproducible-build-aux.rs -O - $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" -O - $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" -O - nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1-opt.nm" - nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2-opt.nm" - cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1 + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O + $(RUSTC) reproducible-build.rs -C linker=$(call RUN_BINFILE,linker) -O + diff -u "$(TMPDIR)/linker-arguments1" "$(TMPDIR)/linker-arguments2" link_paths: rm -rf $(TMPDIR) && mkdir $(TMPDIR) diff --git a/src/test/run-make-fulldeps/reproducible-build/linker.rs b/src/test/run-make-fulldeps/reproducible-build/linker.rs new file mode 100644 index 000000000000..fd8946708bff --- /dev/null +++ b/src/test/run-make-fulldeps/reproducible-build/linker.rs @@ -0,0 +1,54 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::path::Path; +use std::fs::File; +use std::io::{Read, Write}; + +fn main() { + let mut dst = env::current_exe().unwrap(); + dst.pop(); + dst.push("linker-arguments1"); + if dst.exists() { + dst.pop(); + dst.push("linker-arguments2"); + assert!(!dst.exists()); + } + + let mut out = String::new(); + for arg in env::args().skip(1) { + let path = Path::new(&arg); + if !path.is_file() { + out.push_str(&arg); + out.push_str("\n"); + continue + } + + let mut contents = Vec::new(); + File::open(path).unwrap().read_to_end(&mut contents).unwrap(); + + out.push_str(&format!("{}: {}\n", arg, hash(&contents))); + } + + File::create(dst).unwrap().write_all(out.as_bytes()).unwrap(); +} + +// fnv hash for now +fn hash(contents: &[u8]) -> u64 { + let mut hash = 0xcbf29ce484222325; + + for byte in contents { + hash = hash ^ (*byte as u64); + hash = hash.wrapping_mul(0x100000001b3); + } + + hash +} diff --git a/src/test/run-make/reproducible-build/reproducible-build-aux.rs b/src/test/run-make-fulldeps/reproducible-build/reproducible-build-aux.rs similarity index 100% rename from src/test/run-make/reproducible-build/reproducible-build-aux.rs rename to src/test/run-make-fulldeps/reproducible-build/reproducible-build-aux.rs diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs similarity index 100% rename from src/test/run-make/reproducible-build/reproducible-build.rs rename to src/test/run-make-fulldeps/reproducible-build/reproducible-build.rs diff --git a/src/test/run-make-fulldeps/resolve-rename/Makefile b/src/test/run-make-fulldeps/resolve-rename/Makefile new file mode 100644 index 000000000000..4b0c36d01b7a --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) -C extra-filename=-hash foo.rs + $(RUSTC) bar.rs + mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib + $(RUSTC) baz.rs diff --git a/src/test/ui/feature-gate-dotdoteq_in_patterns.rs b/src/test/run-make-fulldeps/resolve-rename/bar.rs similarity index 78% rename from src/test/ui/feature-gate-dotdoteq_in_patterns.rs rename to src/test/run-make-fulldeps/resolve-rename/bar.rs index 1fb139bf07f4..1552b45f2fc1 100644 --- a/src/test/ui/feature-gate-dotdoteq_in_patterns.rs +++ b/src/test/run-make-fulldeps/resolve-rename/bar.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn main() { - match 22 { - 0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental - _ => {} - } -} +#![crate_type = "rlib"] + +extern crate foo; + +pub fn bar() { foo::foo() } diff --git a/src/test/run-make-fulldeps/resolve-rename/baz.rs b/src/test/run-make-fulldeps/resolve-rename/baz.rs new file mode 100644 index 000000000000..27d801490e42 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/baz.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate bar; + +pub fn baz() { bar::bar() } diff --git a/src/test/run-make-fulldeps/resolve-rename/foo.rs b/src/test/run-make-fulldeps/resolve-rename/foo.rs new file mode 100644 index 000000000000..830c289b65f1 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/foo.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/src/test/run-make/rlib-chain/Makefile b/src/test/run-make-fulldeps/rlib-chain/Makefile similarity index 100% rename from src/test/run-make/rlib-chain/Makefile rename to src/test/run-make-fulldeps/rlib-chain/Makefile diff --git a/src/test/run-make/rlib-chain/m1.rs b/src/test/run-make-fulldeps/rlib-chain/m1.rs similarity index 100% rename from src/test/run-make/rlib-chain/m1.rs rename to src/test/run-make-fulldeps/rlib-chain/m1.rs diff --git a/src/test/run-make/rlib-chain/m2.rs b/src/test/run-make-fulldeps/rlib-chain/m2.rs similarity index 100% rename from src/test/run-make/rlib-chain/m2.rs rename to src/test/run-make-fulldeps/rlib-chain/m2.rs diff --git a/src/test/run-make/rlib-chain/m3.rs b/src/test/run-make-fulldeps/rlib-chain/m3.rs similarity index 100% rename from src/test/run-make/rlib-chain/m3.rs rename to src/test/run-make-fulldeps/rlib-chain/m3.rs diff --git a/src/test/run-make/rlib-chain/m4.rs b/src/test/run-make-fulldeps/rlib-chain/m4.rs similarity index 100% rename from src/test/run-make/rlib-chain/m4.rs rename to src/test/run-make-fulldeps/rlib-chain/m4.rs diff --git a/src/test/run-make/rustc-macro-dep-files/Makefile b/src/test/run-make-fulldeps/rustc-macro-dep-files/Makefile similarity index 100% rename from src/test/run-make/rustc-macro-dep-files/Makefile rename to src/test/run-make-fulldeps/rustc-macro-dep-files/Makefile diff --git a/src/test/run-make/rustc-macro-dep-files/bar.rs b/src/test/run-make-fulldeps/rustc-macro-dep-files/bar.rs similarity index 100% rename from src/test/run-make/rustc-macro-dep-files/bar.rs rename to src/test/run-make-fulldeps/rustc-macro-dep-files/bar.rs diff --git a/src/test/run-make/rustc-macro-dep-files/foo.rs b/src/test/run-make-fulldeps/rustc-macro-dep-files/foo.rs similarity index 100% rename from src/test/run-make/rustc-macro-dep-files/foo.rs rename to src/test/run-make-fulldeps/rustc-macro-dep-files/foo.rs diff --git a/src/test/run-make/rustdoc-error-lines/Makefile b/src/test/run-make-fulldeps/rustdoc-error-lines/Makefile similarity index 100% rename from src/test/run-make/rustdoc-error-lines/Makefile rename to src/test/run-make-fulldeps/rustdoc-error-lines/Makefile diff --git a/src/test/run-make/rustdoc-error-lines/input.rs b/src/test/run-make-fulldeps/rustdoc-error-lines/input.rs similarity index 100% rename from src/test/run-make/rustdoc-error-lines/input.rs rename to src/test/run-make-fulldeps/rustdoc-error-lines/input.rs diff --git a/src/test/run-make/rustdoc-output-path/Makefile b/src/test/run-make-fulldeps/rustdoc-output-path/Makefile similarity index 100% rename from src/test/run-make/rustdoc-output-path/Makefile rename to src/test/run-make-fulldeps/rustdoc-output-path/Makefile diff --git a/src/test/run-make/rustdoc-output-path/foo.rs b/src/test/run-make-fulldeps/rustdoc-output-path/foo.rs similarity index 100% rename from src/test/run-make/rustdoc-output-path/foo.rs rename to src/test/run-make-fulldeps/rustdoc-output-path/foo.rs diff --git a/src/test/run-make/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile similarity index 100% rename from src/test/run-make/sanitizer-address/Makefile rename to src/test/run-make-fulldeps/sanitizer-address/Makefile diff --git a/src/test/run-make/sanitizer-address/overflow.rs b/src/test/run-make-fulldeps/sanitizer-address/overflow.rs similarity index 100% rename from src/test/run-make/sanitizer-address/overflow.rs rename to src/test/run-make-fulldeps/sanitizer-address/overflow.rs diff --git a/src/test/run-make/sanitizer-cdylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile similarity index 100% rename from src/test/run-make/sanitizer-cdylib-link/Makefile rename to src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile diff --git a/src/test/run-make/sanitizer-cdylib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs similarity index 100% rename from src/test/run-make/sanitizer-cdylib-link/library.rs rename to src/test/run-make-fulldeps/sanitizer-cdylib-link/library.rs diff --git a/src/test/run-make/sanitizer-cdylib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs similarity index 100% rename from src/test/run-make/sanitizer-cdylib-link/program.rs rename to src/test/run-make-fulldeps/sanitizer-cdylib-link/program.rs diff --git a/src/test/run-make/sanitizer-dylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile similarity index 100% rename from src/test/run-make/sanitizer-dylib-link/Makefile rename to src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile diff --git a/src/test/run-make/sanitizer-dylib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs similarity index 100% rename from src/test/run-make/sanitizer-dylib-link/library.rs rename to src/test/run-make-fulldeps/sanitizer-dylib-link/library.rs diff --git a/src/test/run-make/sanitizer-dylib-link/program.rs b/src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs similarity index 100% rename from src/test/run-make/sanitizer-dylib-link/program.rs rename to src/test/run-make-fulldeps/sanitizer-dylib-link/program.rs diff --git a/src/test/run-make/sanitizer-invalid-cratetype/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile similarity index 100% rename from src/test/run-make/sanitizer-invalid-cratetype/Makefile rename to src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile diff --git a/src/test/ui/did_you_mean/issue-41679.rs b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs similarity index 88% rename from src/test/ui/did_you_mean/issue-41679.rs rename to src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs index 98c909e212fd..41782851a1a6 100644 --- a/src/test/ui/did_you_mean/issue-41679.rs +++ b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/hello.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - let x = ~1; //~ ERROR can not be used as a unary operator + println!("Hello, world!"); } diff --git a/src/test/run-make/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile similarity index 100% rename from src/test/run-make/sanitizer-invalid-target/Makefile rename to src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile diff --git a/src/test/run-make/sanitizer-invalid-target/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs similarity index 100% rename from src/test/run-make/sanitizer-invalid-target/hello.rs rename to src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs diff --git a/src/test/run-make/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile similarity index 100% rename from src/test/run-make/sanitizer-leak/Makefile rename to src/test/run-make-fulldeps/sanitizer-leak/Makefile diff --git a/src/test/run-make/sanitizer-leak/leak.rs b/src/test/run-make-fulldeps/sanitizer-leak/leak.rs similarity index 100% rename from src/test/run-make/sanitizer-leak/leak.rs rename to src/test/run-make-fulldeps/sanitizer-leak/leak.rs diff --git a/src/test/run-make/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile similarity index 100% rename from src/test/run-make/sanitizer-memory/Makefile rename to src/test/run-make-fulldeps/sanitizer-memory/Makefile diff --git a/src/test/run-make/sanitizer-memory/uninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs similarity index 100% rename from src/test/run-make/sanitizer-memory/uninit.rs rename to src/test/run-make-fulldeps/sanitizer-memory/uninit.rs diff --git a/src/test/run-make/sanitizer-staticlib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile similarity index 100% rename from src/test/run-make/sanitizer-staticlib-link/Makefile rename to src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile diff --git a/src/test/run-make/sanitizer-staticlib-link/library.rs b/src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs similarity index 100% rename from src/test/run-make/sanitizer-staticlib-link/library.rs rename to src/test/run-make-fulldeps/sanitizer-staticlib-link/library.rs diff --git a/src/test/run-make/sanitizer-staticlib-link/program.c b/src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c similarity index 100% rename from src/test/run-make/sanitizer-staticlib-link/program.c rename to src/test/run-make-fulldeps/sanitizer-staticlib-link/program.c diff --git a/src/test/run-make/save-analysis-fail/Makefile b/src/test/run-make-fulldeps/save-analysis-fail/Makefile similarity index 100% rename from src/test/run-make/save-analysis-fail/Makefile rename to src/test/run-make-fulldeps/save-analysis-fail/Makefile diff --git a/src/test/run-make/save-analysis-fail/SameDir.rs b/src/test/run-make-fulldeps/save-analysis-fail/SameDir.rs similarity index 100% rename from src/test/run-make/save-analysis-fail/SameDir.rs rename to src/test/run-make-fulldeps/save-analysis-fail/SameDir.rs diff --git a/src/test/run-make/save-analysis-fail/SameDir3.rs b/src/test/run-make-fulldeps/save-analysis-fail/SameDir3.rs similarity index 100% rename from src/test/run-make/save-analysis-fail/SameDir3.rs rename to src/test/run-make-fulldeps/save-analysis-fail/SameDir3.rs diff --git a/src/test/run-make/save-analysis-fail/SubDir/mod.rs b/src/test/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs similarity index 100% rename from src/test/run-make/save-analysis-fail/SubDir/mod.rs rename to src/test/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs diff --git a/src/test/run-make/save-analysis-fail/foo.rs b/src/test/run-make-fulldeps/save-analysis-fail/foo.rs similarity index 100% rename from src/test/run-make/save-analysis-fail/foo.rs rename to src/test/run-make-fulldeps/save-analysis-fail/foo.rs diff --git a/src/test/run-make/save-analysis-fail/krate2.rs b/src/test/run-make-fulldeps/save-analysis-fail/krate2.rs similarity index 100% rename from src/test/run-make/save-analysis-fail/krate2.rs rename to src/test/run-make-fulldeps/save-analysis-fail/krate2.rs diff --git a/src/test/run-make/save-analysis/Makefile b/src/test/run-make-fulldeps/save-analysis/Makefile similarity index 100% rename from src/test/run-make/save-analysis/Makefile rename to src/test/run-make-fulldeps/save-analysis/Makefile diff --git a/src/test/run-make/save-analysis/SameDir.rs b/src/test/run-make-fulldeps/save-analysis/SameDir.rs similarity index 100% rename from src/test/run-make/save-analysis/SameDir.rs rename to src/test/run-make-fulldeps/save-analysis/SameDir.rs diff --git a/src/test/run-make/save-analysis/SameDir3.rs b/src/test/run-make-fulldeps/save-analysis/SameDir3.rs similarity index 100% rename from src/test/run-make/save-analysis/SameDir3.rs rename to src/test/run-make-fulldeps/save-analysis/SameDir3.rs diff --git a/src/test/run-make/save-analysis/SubDir/mod.rs b/src/test/run-make-fulldeps/save-analysis/SubDir/mod.rs similarity index 100% rename from src/test/run-make/save-analysis/SubDir/mod.rs rename to src/test/run-make-fulldeps/save-analysis/SubDir/mod.rs diff --git a/src/test/run-make/save-analysis/extra-docs.md b/src/test/run-make-fulldeps/save-analysis/extra-docs.md similarity index 100% rename from src/test/run-make/save-analysis/extra-docs.md rename to src/test/run-make-fulldeps/save-analysis/extra-docs.md diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make-fulldeps/save-analysis/foo.rs similarity index 100% rename from src/test/run-make/save-analysis/foo.rs rename to src/test/run-make-fulldeps/save-analysis/foo.rs diff --git a/src/test/run-make/save-analysis/krate2.rs b/src/test/run-make-fulldeps/save-analysis/krate2.rs similarity index 100% rename from src/test/run-make/save-analysis/krate2.rs rename to src/test/run-make-fulldeps/save-analysis/krate2.rs diff --git a/src/test/run-make/sepcomp-cci-copies/Makefile b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile similarity index 100% rename from src/test/run-make/sepcomp-cci-copies/Makefile rename to src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile diff --git a/src/test/run-make/sepcomp-cci-copies/cci_lib.rs b/src/test/run-make-fulldeps/sepcomp-cci-copies/cci_lib.rs similarity index 100% rename from src/test/run-make/sepcomp-cci-copies/cci_lib.rs rename to src/test/run-make-fulldeps/sepcomp-cci-copies/cci_lib.rs diff --git a/src/test/run-make/sepcomp-cci-copies/foo.rs b/src/test/run-make-fulldeps/sepcomp-cci-copies/foo.rs similarity index 100% rename from src/test/run-make/sepcomp-cci-copies/foo.rs rename to src/test/run-make-fulldeps/sepcomp-cci-copies/foo.rs diff --git a/src/test/run-make/sepcomp-inlining/Makefile b/src/test/run-make-fulldeps/sepcomp-inlining/Makefile similarity index 100% rename from src/test/run-make/sepcomp-inlining/Makefile rename to src/test/run-make-fulldeps/sepcomp-inlining/Makefile diff --git a/src/test/run-make/sepcomp-inlining/foo.rs b/src/test/run-make-fulldeps/sepcomp-inlining/foo.rs similarity index 100% rename from src/test/run-make/sepcomp-inlining/foo.rs rename to src/test/run-make-fulldeps/sepcomp-inlining/foo.rs diff --git a/src/test/run-make/sepcomp-separate/Makefile b/src/test/run-make-fulldeps/sepcomp-separate/Makefile similarity index 100% rename from src/test/run-make/sepcomp-separate/Makefile rename to src/test/run-make-fulldeps/sepcomp-separate/Makefile diff --git a/src/test/run-make/sepcomp-separate/foo.rs b/src/test/run-make-fulldeps/sepcomp-separate/foo.rs similarity index 100% rename from src/test/run-make/sepcomp-separate/foo.rs rename to src/test/run-make-fulldeps/sepcomp-separate/foo.rs diff --git a/src/test/run-make/simd-ffi/Makefile b/src/test/run-make-fulldeps/simd-ffi/Makefile similarity index 100% rename from src/test/run-make/simd-ffi/Makefile rename to src/test/run-make-fulldeps/simd-ffi/Makefile diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs similarity index 98% rename from src/test/run-make/simd-ffi/simd.rs rename to src/test/run-make-fulldeps/simd-ffi/simd.rs index 94b91c711cce..21411a35e3c3 100644 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs @@ -75,6 +75,9 @@ pub trait Sized { } #[lang = "copy"] pub trait Copy { } +impl Copy for f32 {} +impl Copy for i32 {} + pub mod marker { pub use Copy; } diff --git a/src/test/run-make/simple-dylib/Makefile b/src/test/run-make-fulldeps/simple-dylib/Makefile similarity index 100% rename from src/test/run-make/simple-dylib/Makefile rename to src/test/run-make-fulldeps/simple-dylib/Makefile diff --git a/src/test/run-make/simple-dylib/bar.rs b/src/test/run-make-fulldeps/simple-dylib/bar.rs similarity index 100% rename from src/test/run-make/simple-dylib/bar.rs rename to src/test/run-make-fulldeps/simple-dylib/bar.rs diff --git a/src/test/run-make/simple-dylib/foo.rs b/src/test/run-make-fulldeps/simple-dylib/foo.rs similarity index 100% rename from src/test/run-make/simple-dylib/foo.rs rename to src/test/run-make-fulldeps/simple-dylib/foo.rs diff --git a/src/test/run-make/simple-rlib/Makefile b/src/test/run-make-fulldeps/simple-rlib/Makefile similarity index 100% rename from src/test/run-make/simple-rlib/Makefile rename to src/test/run-make-fulldeps/simple-rlib/Makefile diff --git a/src/test/run-make/simple-rlib/bar.rs b/src/test/run-make-fulldeps/simple-rlib/bar.rs similarity index 100% rename from src/test/run-make/simple-rlib/bar.rs rename to src/test/run-make-fulldeps/simple-rlib/bar.rs diff --git a/src/test/run-make/simple-rlib/foo.rs b/src/test/run-make-fulldeps/simple-rlib/foo.rs similarity index 100% rename from src/test/run-make/simple-rlib/foo.rs rename to src/test/run-make-fulldeps/simple-rlib/foo.rs diff --git a/src/test/run-make/stable-symbol-names/Makefile b/src/test/run-make-fulldeps/stable-symbol-names/Makefile similarity index 100% rename from src/test/run-make/stable-symbol-names/Makefile rename to src/test/run-make-fulldeps/stable-symbol-names/Makefile diff --git a/src/test/run-make/stable-symbol-names/stable-symbol-names1.rs b/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names1.rs similarity index 100% rename from src/test/run-make/stable-symbol-names/stable-symbol-names1.rs rename to src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names1.rs diff --git a/src/test/run-make/stable-symbol-names/stable-symbol-names2.rs b/src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names2.rs similarity index 100% rename from src/test/run-make/stable-symbol-names/stable-symbol-names2.rs rename to src/test/run-make-fulldeps/stable-symbol-names/stable-symbol-names2.rs diff --git a/src/test/run-make/static-dylib-by-default/Makefile b/src/test/run-make-fulldeps/static-dylib-by-default/Makefile similarity index 100% rename from src/test/run-make/static-dylib-by-default/Makefile rename to src/test/run-make-fulldeps/static-dylib-by-default/Makefile diff --git a/src/test/run-make/static-dylib-by-default/bar.rs b/src/test/run-make-fulldeps/static-dylib-by-default/bar.rs similarity index 100% rename from src/test/run-make/static-dylib-by-default/bar.rs rename to src/test/run-make-fulldeps/static-dylib-by-default/bar.rs diff --git a/src/test/run-make/static-dylib-by-default/foo.rs b/src/test/run-make-fulldeps/static-dylib-by-default/foo.rs similarity index 100% rename from src/test/run-make/static-dylib-by-default/foo.rs rename to src/test/run-make-fulldeps/static-dylib-by-default/foo.rs diff --git a/src/test/run-make/static-dylib-by-default/main.c b/src/test/run-make-fulldeps/static-dylib-by-default/main.c similarity index 100% rename from src/test/run-make/static-dylib-by-default/main.c rename to src/test/run-make-fulldeps/static-dylib-by-default/main.c diff --git a/src/test/run-make/static-nobundle/Makefile b/src/test/run-make-fulldeps/static-nobundle/Makefile similarity index 100% rename from src/test/run-make/static-nobundle/Makefile rename to src/test/run-make-fulldeps/static-nobundle/Makefile diff --git a/src/test/run-make/static-nobundle/aaa.c b/src/test/run-make-fulldeps/static-nobundle/aaa.c similarity index 100% rename from src/test/run-make/static-nobundle/aaa.c rename to src/test/run-make-fulldeps/static-nobundle/aaa.c diff --git a/src/test/run-make/static-nobundle/bbb.rs b/src/test/run-make-fulldeps/static-nobundle/bbb.rs similarity index 100% rename from src/test/run-make/static-nobundle/bbb.rs rename to src/test/run-make-fulldeps/static-nobundle/bbb.rs diff --git a/src/test/run-make/static-nobundle/ccc.rs b/src/test/run-make-fulldeps/static-nobundle/ccc.rs similarity index 100% rename from src/test/run-make/static-nobundle/ccc.rs rename to src/test/run-make-fulldeps/static-nobundle/ccc.rs diff --git a/src/test/run-make/static-nobundle/ddd.rs b/src/test/run-make-fulldeps/static-nobundle/ddd.rs similarity index 100% rename from src/test/run-make/static-nobundle/ddd.rs rename to src/test/run-make-fulldeps/static-nobundle/ddd.rs diff --git a/src/test/run-make/static-unwinding/Makefile b/src/test/run-make-fulldeps/static-unwinding/Makefile similarity index 100% rename from src/test/run-make/static-unwinding/Makefile rename to src/test/run-make-fulldeps/static-unwinding/Makefile diff --git a/src/test/run-make/static-unwinding/lib.rs b/src/test/run-make-fulldeps/static-unwinding/lib.rs similarity index 100% rename from src/test/run-make/static-unwinding/lib.rs rename to src/test/run-make-fulldeps/static-unwinding/lib.rs diff --git a/src/test/run-make/static-unwinding/main.rs b/src/test/run-make-fulldeps/static-unwinding/main.rs similarity index 100% rename from src/test/run-make/static-unwinding/main.rs rename to src/test/run-make-fulldeps/static-unwinding/main.rs diff --git a/src/test/run-make/staticlib-blank-lib/Makefile b/src/test/run-make-fulldeps/staticlib-blank-lib/Makefile similarity index 100% rename from src/test/run-make/staticlib-blank-lib/Makefile rename to src/test/run-make-fulldeps/staticlib-blank-lib/Makefile diff --git a/src/test/run-make/staticlib-blank-lib/foo.rs b/src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs similarity index 100% rename from src/test/run-make/staticlib-blank-lib/foo.rs rename to src/test/run-make-fulldeps/staticlib-blank-lib/foo.rs diff --git a/src/test/run-make-fulldeps/std-core-cycle/Makefile b/src/test/run-make-fulldeps/std-core-cycle/Makefile new file mode 100644 index 000000000000..adc5be8016cf --- /dev/null +++ b/src/test/run-make-fulldeps/std-core-cycle/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +ifeq ($(UNAME),Darwin) +FLAGS := +else +ifdef IS_WINDOWS +FLAGS := +else +FLAGS := -C link-args=-Wl,--no-undefined +endif +endif + +all: + $(RUSTC) bar.rs + $(RUSTC) foo.rs $(FLAGS) diff --git a/src/test/run-make-fulldeps/std-core-cycle/bar.rs b/src/test/run-make-fulldeps/std-core-cycle/bar.rs new file mode 100644 index 000000000000..6def5b6f5e18 --- /dev/null +++ b/src/test/run-make-fulldeps/std-core-cycle/bar.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(allocator_api)] +#![crate_type = "rlib"] + +use std::heap::*; + +pub struct A; + +unsafe impl<'a> Alloc for &'a A { + unsafe fn alloc(&mut self, _: Layout) -> Result<*mut u8, AllocErr> { + loop {} + } + + unsafe fn dealloc(&mut self, _ptr: *mut u8, _: Layout) { + loop {} + } +} diff --git a/src/test/run-make-fulldeps/std-core-cycle/foo.rs b/src/test/run-make-fulldeps/std-core-cycle/foo.rs new file mode 100644 index 000000000000..04742bba3c87 --- /dev/null +++ b/src/test/run-make-fulldeps/std-core-cycle/foo.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(global_allocator)] +#![crate_type = "cdylib"] + +extern crate bar; + +#[global_allocator] +static A: bar::A = bar::A; + +#[no_mangle] +pub extern fn a(a: u32, b: u32) -> u32 { + a / b +} diff --git a/src/test/run-make/stdin-non-utf8/Makefile b/src/test/run-make-fulldeps/stdin-non-utf8/Makefile similarity index 100% rename from src/test/run-make/stdin-non-utf8/Makefile rename to src/test/run-make-fulldeps/stdin-non-utf8/Makefile diff --git a/src/test/run-make/stdin-non-utf8/non-utf8 b/src/test/run-make-fulldeps/stdin-non-utf8/non-utf8 similarity index 100% rename from src/test/run-make/stdin-non-utf8/non-utf8 rename to src/test/run-make-fulldeps/stdin-non-utf8/non-utf8 diff --git a/src/test/run-make/suspicious-library/Makefile b/src/test/run-make-fulldeps/suspicious-library/Makefile similarity index 100% rename from src/test/run-make/suspicious-library/Makefile rename to src/test/run-make-fulldeps/suspicious-library/Makefile diff --git a/src/test/run-make/suspicious-library/bar.rs b/src/test/run-make-fulldeps/suspicious-library/bar.rs similarity index 100% rename from src/test/run-make/suspicious-library/bar.rs rename to src/test/run-make-fulldeps/suspicious-library/bar.rs diff --git a/src/test/run-make/suspicious-library/foo.rs b/src/test/run-make-fulldeps/suspicious-library/foo.rs similarity index 100% rename from src/test/run-make/suspicious-library/foo.rs rename to src/test/run-make-fulldeps/suspicious-library/foo.rs diff --git a/src/test/run-make/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile similarity index 100% rename from src/test/run-make/symbol-visibility/Makefile rename to src/test/run-make-fulldeps/symbol-visibility/Makefile diff --git a/src/test/run-make/symbol-visibility/a_cdylib.rs b/src/test/run-make-fulldeps/symbol-visibility/a_cdylib.rs similarity index 100% rename from src/test/run-make/symbol-visibility/a_cdylib.rs rename to src/test/run-make-fulldeps/symbol-visibility/a_cdylib.rs diff --git a/src/test/run-make/symbol-visibility/a_rust_dylib.rs b/src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs similarity index 100% rename from src/test/run-make/symbol-visibility/a_rust_dylib.rs rename to src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs diff --git a/src/test/run-make/symbol-visibility/an_executable.rs b/src/test/run-make-fulldeps/symbol-visibility/an_executable.rs similarity index 100% rename from src/test/run-make/symbol-visibility/an_executable.rs rename to src/test/run-make-fulldeps/symbol-visibility/an_executable.rs diff --git a/src/test/run-make/symbol-visibility/an_rlib.rs b/src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs similarity index 100% rename from src/test/run-make/symbol-visibility/an_rlib.rs rename to src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs diff --git a/src/test/run-make/symbols-are-reasonable/Makefile b/src/test/run-make-fulldeps/symbols-are-reasonable/Makefile similarity index 100% rename from src/test/run-make/symbols-are-reasonable/Makefile rename to src/test/run-make-fulldeps/symbols-are-reasonable/Makefile diff --git a/src/test/run-make/symbols-are-reasonable/lib.rs b/src/test/run-make-fulldeps/symbols-are-reasonable/lib.rs similarity index 100% rename from src/test/run-make/symbols-are-reasonable/lib.rs rename to src/test/run-make-fulldeps/symbols-are-reasonable/lib.rs diff --git a/src/test/run-make/symbols-include-type-name/Makefile b/src/test/run-make-fulldeps/symbols-include-type-name/Makefile similarity index 100% rename from src/test/run-make/symbols-include-type-name/Makefile rename to src/test/run-make-fulldeps/symbols-include-type-name/Makefile diff --git a/src/test/run-make/symbols-include-type-name/lib.rs b/src/test/run-make-fulldeps/symbols-include-type-name/lib.rs similarity index 100% rename from src/test/run-make/symbols-include-type-name/lib.rs rename to src/test/run-make-fulldeps/symbols-include-type-name/lib.rs diff --git a/src/test/run-make/symlinked-extern/Makefile b/src/test/run-make-fulldeps/symlinked-extern/Makefile similarity index 100% rename from src/test/run-make/symlinked-extern/Makefile rename to src/test/run-make-fulldeps/symlinked-extern/Makefile diff --git a/src/test/run-make/symlinked-extern/bar.rs b/src/test/run-make-fulldeps/symlinked-extern/bar.rs similarity index 100% rename from src/test/run-make/symlinked-extern/bar.rs rename to src/test/run-make-fulldeps/symlinked-extern/bar.rs diff --git a/src/test/run-make/symlinked-extern/baz.rs b/src/test/run-make-fulldeps/symlinked-extern/baz.rs similarity index 100% rename from src/test/run-make/symlinked-extern/baz.rs rename to src/test/run-make-fulldeps/symlinked-extern/baz.rs diff --git a/src/test/run-make/symlinked-extern/foo.rs b/src/test/run-make-fulldeps/symlinked-extern/foo.rs similarity index 100% rename from src/test/run-make/symlinked-extern/foo.rs rename to src/test/run-make-fulldeps/symlinked-extern/foo.rs diff --git a/src/test/run-make/symlinked-libraries/Makefile b/src/test/run-make-fulldeps/symlinked-libraries/Makefile similarity index 100% rename from src/test/run-make/symlinked-libraries/Makefile rename to src/test/run-make-fulldeps/symlinked-libraries/Makefile diff --git a/src/test/run-make/symlinked-libraries/bar.rs b/src/test/run-make-fulldeps/symlinked-libraries/bar.rs similarity index 100% rename from src/test/run-make/symlinked-libraries/bar.rs rename to src/test/run-make-fulldeps/symlinked-libraries/bar.rs diff --git a/src/test/run-make/symlinked-libraries/foo.rs b/src/test/run-make-fulldeps/symlinked-libraries/foo.rs similarity index 100% rename from src/test/run-make/symlinked-libraries/foo.rs rename to src/test/run-make-fulldeps/symlinked-libraries/foo.rs diff --git a/src/test/run-make/symlinked-rlib/Makefile b/src/test/run-make-fulldeps/symlinked-rlib/Makefile similarity index 100% rename from src/test/run-make/symlinked-rlib/Makefile rename to src/test/run-make-fulldeps/symlinked-rlib/Makefile diff --git a/src/test/run-make/symlinked-rlib/bar.rs b/src/test/run-make-fulldeps/symlinked-rlib/bar.rs similarity index 100% rename from src/test/run-make/symlinked-rlib/bar.rs rename to src/test/run-make-fulldeps/symlinked-rlib/bar.rs diff --git a/src/test/run-make/symlinked-rlib/foo.rs b/src/test/run-make-fulldeps/symlinked-rlib/foo.rs similarity index 100% rename from src/test/run-make/symlinked-rlib/foo.rs rename to src/test/run-make-fulldeps/symlinked-rlib/foo.rs diff --git a/src/test/run-make/sysroot-crates-are-unstable/Makefile b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/Makefile similarity index 100% rename from src/test/run-make/sysroot-crates-are-unstable/Makefile rename to src/test/run-make-fulldeps/sysroot-crates-are-unstable/Makefile diff --git a/src/test/run-make/sysroot-crates-are-unstable/test.py b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py similarity index 100% rename from src/test/run-make/sysroot-crates-are-unstable/test.py rename to src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py diff --git a/src/test/run-make/target-cpu-native/Makefile b/src/test/run-make-fulldeps/target-cpu-native/Makefile similarity index 100% rename from src/test/run-make/target-cpu-native/Makefile rename to src/test/run-make-fulldeps/target-cpu-native/Makefile diff --git a/src/test/run-make/target-cpu-native/foo.rs b/src/test/run-make-fulldeps/target-cpu-native/foo.rs similarity index 100% rename from src/test/run-make/target-cpu-native/foo.rs rename to src/test/run-make-fulldeps/target-cpu-native/foo.rs diff --git a/src/test/run-make/target-specs/Makefile b/src/test/run-make-fulldeps/target-specs/Makefile similarity index 100% rename from src/test/run-make/target-specs/Makefile rename to src/test/run-make-fulldeps/target-specs/Makefile diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make-fulldeps/target-specs/foo.rs similarity index 100% rename from src/test/run-make/target-specs/foo.rs rename to src/test/run-make-fulldeps/target-specs/foo.rs diff --git a/src/test/run-make/target-specs/my-awesome-platform.json b/src/test/run-make-fulldeps/target-specs/my-awesome-platform.json similarity index 100% rename from src/test/run-make/target-specs/my-awesome-platform.json rename to src/test/run-make-fulldeps/target-specs/my-awesome-platform.json diff --git a/src/test/run-make/target-specs/my-incomplete-platform.json b/src/test/run-make-fulldeps/target-specs/my-incomplete-platform.json similarity index 100% rename from src/test/run-make/target-specs/my-incomplete-platform.json rename to src/test/run-make-fulldeps/target-specs/my-incomplete-platform.json diff --git a/src/test/run-make/target-specs/my-invalid-platform.json b/src/test/run-make-fulldeps/target-specs/my-invalid-platform.json similarity index 100% rename from src/test/run-make/target-specs/my-invalid-platform.json rename to src/test/run-make-fulldeps/target-specs/my-invalid-platform.json diff --git a/src/test/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json b/src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json similarity index 100% rename from src/test/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json rename to src/test/run-make-fulldeps/target-specs/my-x86_64-unknown-linux-gnu-platform.json diff --git a/src/test/run-make/target-without-atomics/Makefile b/src/test/run-make-fulldeps/target-without-atomics/Makefile similarity index 100% rename from src/test/run-make/target-without-atomics/Makefile rename to src/test/run-make-fulldeps/target-without-atomics/Makefile diff --git a/src/test/run-make/test-harness/Makefile b/src/test/run-make-fulldeps/test-harness/Makefile similarity index 100% rename from src/test/run-make/test-harness/Makefile rename to src/test/run-make-fulldeps/test-harness/Makefile diff --git a/src/test/run-make/test-harness/test-ignore-cfg.rs b/src/test/run-make-fulldeps/test-harness/test-ignore-cfg.rs similarity index 100% rename from src/test/run-make/test-harness/test-ignore-cfg.rs rename to src/test/run-make-fulldeps/test-harness/test-ignore-cfg.rs diff --git a/src/test/run-make/tools.mk b/src/test/run-make-fulldeps/tools.mk similarity index 98% rename from src/test/run-make/tools.mk rename to src/test/run-make-fulldeps/tools.mk index d9103e199273..af1707de6c02 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -9,7 +9,7 @@ RUSTC_ORIGINAL := $(RUSTC) BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)' BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)' RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) -RUSTDOC := $(BARE_RUSTDOC) +RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR) ifdef RUSTC_LINKER RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER) RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options diff --git a/src/test/run-make/treat-err-as-bug/Makefile b/src/test/run-make-fulldeps/treat-err-as-bug/Makefile similarity index 100% rename from src/test/run-make/treat-err-as-bug/Makefile rename to src/test/run-make-fulldeps/treat-err-as-bug/Makefile diff --git a/src/test/run-make/treat-err-as-bug/err.rs b/src/test/run-make-fulldeps/treat-err-as-bug/err.rs similarity index 100% rename from src/test/run-make/treat-err-as-bug/err.rs rename to src/test/run-make-fulldeps/treat-err-as-bug/err.rs diff --git a/src/test/run-make/type-mismatch-same-crate-name/Makefile b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/Makefile similarity index 100% rename from src/test/run-make/type-mismatch-same-crate-name/Makefile rename to src/test/run-make-fulldeps/type-mismatch-same-crate-name/Makefile diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateA.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateA.rs similarity index 100% rename from src/test/run-make/type-mismatch-same-crate-name/crateA.rs rename to src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateA.rs diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateB.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateB.rs similarity index 100% rename from src/test/run-make/type-mismatch-same-crate-name/crateB.rs rename to src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateB.rs diff --git a/src/test/run-make/type-mismatch-same-crate-name/crateC.rs b/src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs similarity index 100% rename from src/test/run-make/type-mismatch-same-crate-name/crateC.rs rename to src/test/run-make-fulldeps/type-mismatch-same-crate-name/crateC.rs diff --git a/src/test/run-make/use-extern-for-plugins/Makefile b/src/test/run-make-fulldeps/use-extern-for-plugins/Makefile similarity index 100% rename from src/test/run-make/use-extern-for-plugins/Makefile rename to src/test/run-make-fulldeps/use-extern-for-plugins/Makefile diff --git a/src/test/run-make/use-extern-for-plugins/bar.rs b/src/test/run-make-fulldeps/use-extern-for-plugins/bar.rs similarity index 100% rename from src/test/run-make/use-extern-for-plugins/bar.rs rename to src/test/run-make-fulldeps/use-extern-for-plugins/bar.rs diff --git a/src/test/run-make/use-extern-for-plugins/baz.rs b/src/test/run-make-fulldeps/use-extern-for-plugins/baz.rs similarity index 100% rename from src/test/run-make/use-extern-for-plugins/baz.rs rename to src/test/run-make-fulldeps/use-extern-for-plugins/baz.rs diff --git a/src/test/run-make/use-extern-for-plugins/foo.rs b/src/test/run-make-fulldeps/use-extern-for-plugins/foo.rs similarity index 100% rename from src/test/run-make/use-extern-for-plugins/foo.rs rename to src/test/run-make-fulldeps/use-extern-for-plugins/foo.rs diff --git a/src/test/run-make/used/Makefile b/src/test/run-make-fulldeps/used/Makefile similarity index 100% rename from src/test/run-make/used/Makefile rename to src/test/run-make-fulldeps/used/Makefile diff --git a/src/test/run-make/used/used.rs b/src/test/run-make-fulldeps/used/used.rs similarity index 100% rename from src/test/run-make/used/used.rs rename to src/test/run-make-fulldeps/used/used.rs diff --git a/src/test/run-make/version/Makefile b/src/test/run-make-fulldeps/version/Makefile similarity index 100% rename from src/test/run-make/version/Makefile rename to src/test/run-make-fulldeps/version/Makefile diff --git a/src/test/run-make/volatile-intrinsics/Makefile b/src/test/run-make-fulldeps/volatile-intrinsics/Makefile similarity index 100% rename from src/test/run-make/volatile-intrinsics/Makefile rename to src/test/run-make-fulldeps/volatile-intrinsics/Makefile diff --git a/src/test/run-make/volatile-intrinsics/main.rs b/src/test/run-make-fulldeps/volatile-intrinsics/main.rs similarity index 100% rename from src/test/run-make/volatile-intrinsics/main.rs rename to src/test/run-make-fulldeps/volatile-intrinsics/main.rs diff --git a/src/test/run-make/weird-output-filenames/Makefile b/src/test/run-make-fulldeps/weird-output-filenames/Makefile similarity index 100% rename from src/test/run-make/weird-output-filenames/Makefile rename to src/test/run-make-fulldeps/weird-output-filenames/Makefile diff --git a/src/test/run-make/weird-output-filenames/foo.rs b/src/test/run-make-fulldeps/weird-output-filenames/foo.rs similarity index 100% rename from src/test/run-make/weird-output-filenames/foo.rs rename to src/test/run-make-fulldeps/weird-output-filenames/foo.rs diff --git a/src/test/run-make/windows-spawn/Makefile b/src/test/run-make-fulldeps/windows-spawn/Makefile similarity index 100% rename from src/test/run-make/windows-spawn/Makefile rename to src/test/run-make-fulldeps/windows-spawn/Makefile diff --git a/src/test/run-make/windows-spawn/hello.rs b/src/test/run-make-fulldeps/windows-spawn/hello.rs similarity index 100% rename from src/test/run-make/windows-spawn/hello.rs rename to src/test/run-make-fulldeps/windows-spawn/hello.rs diff --git a/src/test/run-make/windows-spawn/spawn.rs b/src/test/run-make-fulldeps/windows-spawn/spawn.rs similarity index 100% rename from src/test/run-make/windows-spawn/spawn.rs rename to src/test/run-make-fulldeps/windows-spawn/spawn.rs diff --git a/src/test/run-make/windows-subsystem/Makefile b/src/test/run-make-fulldeps/windows-subsystem/Makefile similarity index 100% rename from src/test/run-make/windows-subsystem/Makefile rename to src/test/run-make-fulldeps/windows-subsystem/Makefile diff --git a/src/test/run-make/windows-subsystem/console.rs b/src/test/run-make-fulldeps/windows-subsystem/console.rs similarity index 100% rename from src/test/run-make/windows-subsystem/console.rs rename to src/test/run-make-fulldeps/windows-subsystem/console.rs diff --git a/src/test/run-make/windows-subsystem/windows.rs b/src/test/run-make-fulldeps/windows-subsystem/windows.rs similarity index 100% rename from src/test/run-make/windows-subsystem/windows.rs rename to src/test/run-make-fulldeps/windows-subsystem/windows.rs diff --git a/src/test/run-make/wasm-custom-section/Makefile b/src/test/run-make/wasm-custom-section/Makefile new file mode 100644 index 000000000000..399951e51631 --- /dev/null +++ b/src/test/run-make/wasm-custom-section/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +ifeq ($(TARGET),wasm32-unknown-unknown) +all: + $(RUSTC) foo.rs --target wasm32-unknown-unknown + $(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown + $(NODE) foo.js $(TMPDIR)/bar.wasm +else +all: +endif diff --git a/src/test/run-make/wasm-custom-section/bar.rs b/src/test/run-make/wasm-custom-section/bar.rs new file mode 100644 index 000000000000..e3db36d6dbd4 --- /dev/null +++ b/src/test/run-make/wasm-custom-section/bar.rs @@ -0,0 +1,24 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] +#![feature(wasm_custom_section)] +#![deny(warnings)] + +extern crate foo; + +#[wasm_custom_section = "foo"] +const A: [u8; 2] = [5, 6]; + +#[wasm_custom_section = "baz"] +const B: [u8; 2] = [7, 8]; + +#[no_mangle] +pub extern fn foo() {} diff --git a/src/test/run-make/wasm-custom-section/foo.js b/src/test/run-make/wasm-custom-section/foo.js new file mode 100644 index 000000000000..e7a4cfc344ef --- /dev/null +++ b/src/test/run-make/wasm-custom-section/foo.js @@ -0,0 +1,46 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const fs = require('fs'); +const process = require('process'); +const assert = require('assert'); +const buffer = fs.readFileSync(process.argv[2]); + +let m = new WebAssembly.Module(buffer); +let sections = WebAssembly.Module.customSections(m, "baz"); +console.log('section baz', sections); +assert.strictEqual(sections.length, 1); +let section = new Uint8Array(sections[0]); +console.log('contents', section); +assert.strictEqual(section.length, 2); +assert.strictEqual(section[0], 7); +assert.strictEqual(section[1], 8); + +sections = WebAssembly.Module.customSections(m, "bar"); +console.log('section bar', sections); +assert.strictEqual(sections.length, 1, "didn't pick up `bar` section from dependency"); +section = new Uint8Array(sections[0]); +console.log('contents', section); +assert.strictEqual(section.length, 2); +assert.strictEqual(section[0], 3); +assert.strictEqual(section[1], 4); + +sections = WebAssembly.Module.customSections(m, "foo"); +console.log('section foo', sections); +assert.strictEqual(sections.length, 1, "didn't create `foo` section"); +section = new Uint8Array(sections[0]); +console.log('contents', section); +assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections"); +assert.strictEqual(section[0], 5); +assert.strictEqual(section[1], 6); +assert.strictEqual(section[2], 1); +assert.strictEqual(section[3], 2); + +process.exit(0); diff --git a/src/test/run-make/wasm-custom-section/foo.rs b/src/test/run-make/wasm-custom-section/foo.rs new file mode 100644 index 000000000000..44d1efd7c2d6 --- /dev/null +++ b/src/test/run-make/wasm-custom-section/foo.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +#![feature(wasm_custom_section)] +#![deny(warnings)] + +#[wasm_custom_section = "foo"] +const A: [u8; 2] = [1, 2]; + +#[wasm_custom_section = "bar"] +const B: [u8; 2] = [3, 4]; diff --git a/src/test/run-make/wasm-import-module/Makefile b/src/test/run-make/wasm-import-module/Makefile new file mode 100644 index 000000000000..399951e51631 --- /dev/null +++ b/src/test/run-make/wasm-import-module/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +ifeq ($(TARGET),wasm32-unknown-unknown) +all: + $(RUSTC) foo.rs --target wasm32-unknown-unknown + $(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown + $(NODE) foo.js $(TMPDIR)/bar.wasm +else +all: +endif diff --git a/src/test/run-make/wasm-import-module/bar.rs b/src/test/run-make/wasm-import-module/bar.rs new file mode 100644 index 000000000000..9e659223c651 --- /dev/null +++ b/src/test/run-make/wasm-import-module/bar.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] +#![feature(wasm_import_module)] +#![deny(warnings)] + +extern crate foo; + +#[wasm_import_module = "./me"] +extern { + #[link_name = "me_in_dep"] + fn dep(); +} + +#[no_mangle] +pub extern fn foo() { + unsafe { + foo::dep(); + dep(); + } +} diff --git a/src/test/run-make/wasm-import-module/foo.js b/src/test/run-make/wasm-import-module/foo.js new file mode 100644 index 000000000000..369962e55b1e --- /dev/null +++ b/src/test/run-make/wasm-import-module/foo.js @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const fs = require('fs'); +const process = require('process'); +const assert = require('assert'); +const buffer = fs.readFileSync(process.argv[2]); + +let m = new WebAssembly.Module(buffer); +let imports = WebAssembly.Module.imports(m); +console.log('imports', imports); +assert.strictEqual(imports.length, 2); + +assert.strictEqual(imports[0].kind, 'function'); +assert.strictEqual(imports[1].kind, 'function'); + +let modules = [imports[0].module, imports[1].module]; +modules.sort(); + +assert.strictEqual(modules[0], './dep'); +assert.strictEqual(modules[1], './me'); diff --git a/src/test/run-make/wasm-import-module/foo.rs b/src/test/run-make/wasm-import-module/foo.rs new file mode 100644 index 000000000000..bcd2ca70befa --- /dev/null +++ b/src/test/run-make/wasm-import-module/foo.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +#![feature(wasm_import_module)] +#![deny(warnings)] + +#[wasm_import_module = "./dep"] +extern { + pub fn dep(); +} diff --git a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs index 9f9ef4772242..62cb870c7bb4 100644 --- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs @@ -115,6 +115,10 @@ fn reject_stmt_parse(es: &str) { } fn main() { + syntax::with_globals(|| run()); +} + +fn run() { let both = &["#[attr]", "#![attr]"]; let outer = &["#[attr]"]; let none = &[]; @@ -122,16 +126,6 @@ fn main() { check_expr_attrs("#[attr] box 0", outer); reject_expr_parse("box #![attr] 0"); - check_expr_attrs("#[attr] 0 <- #[attr] 0", none); - check_expr_attrs("#[attr] (0 <- 0)", outer); - reject_expr_parse("0 #[attr] <- 0"); - reject_expr_parse("0 <- #![attr] 0"); - - check_expr_attrs("in #[attr] 0 {#[attr] 0}", none); - check_expr_attrs("#[attr] (in 0 {0})", outer); - reject_expr_parse("in 0 #[attr] {0}"); - reject_expr_parse("in 0 {#![attr] 0}"); - check_expr_attrs("#[attr] [#![attr]]", both); check_expr_attrs("#[attr] [#![attr] 0]", both); check_expr_attrs("#[attr] [#![attr] 0; 0]", both); diff --git a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs index aa2f1626a6a8..5ebd32921329 100644 --- a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs @@ -96,6 +96,8 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt, } }) ], + // these are covered in proc_macro/attr-stmt-expr.rs + Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item"), } } @@ -140,6 +142,8 @@ fn expand_duplicate(cx: &mut ExtCtxt, new_it.ident = copy_name; push(Annotatable::TraitItem(P(new_it))); } + // these are covered in proc_macro/attr-stmt-expr.rs + Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item") } } diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs index 8da2ae8b29ab..231ed2898f1d 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs @@ -53,5 +53,6 @@ pub fn plugin_registrar(reg: &mut Registry) { def_info: None, allow_internal_unstable: false, allow_internal_unsafe: false, + unstable_feature: None, }); } diff --git a/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs b/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs index 26419a51513f..dc6f33bad997 100644 --- a/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs +++ b/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs @@ -12,7 +12,6 @@ #![crate_type="dylib"] #![feature(plugin_registrar, rustc_private)] -#![feature(slice_patterns)] extern crate syntax; extern crate syntax_pos; @@ -49,7 +48,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } let text = match args[0] { - TokenTree::Token(_, token::Ident(s)) => s.to_string(), + TokenTree::Token(_, token::Ident(s, _)) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); return DummyResult::any(sp); diff --git a/src/test/run-pass-fulldeps/binary-heap-panic-safe.rs b/src/test/run-pass-fulldeps/binary-heap-panic-safe.rs deleted file mode 100644 index 6139a7d3201c..000000000000 --- a/src/test/run-pass-fulldeps/binary-heap-panic-safe.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(rustc_private, std_panic)] - -extern crate rand; - -use rand::{thread_rng, Rng}; -use std::panic::{self, AssertUnwindSafe}; - -use std::collections::BinaryHeap; -use std::cmp; -use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - -static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; - -// old binaryheap failed this test -// -// Integrity means that all elements are present after a comparison panics, -// even if the order may not be correct. -// -// Destructors must be called exactly once per element. -fn test_integrity() { - #[derive(Eq, PartialEq, Ord, Clone, Debug)] - struct PanicOrd(T, bool); - - impl Drop for PanicOrd { - fn drop(&mut self) { - // update global drop count - DROP_COUNTER.fetch_add(1, Ordering::SeqCst); - } - } - - impl PartialOrd for PanicOrd { - fn partial_cmp(&self, other: &Self) -> Option { - if self.1 || other.1 { - panic!("Panicking comparison"); - } - self.0.partial_cmp(&other.0) - } - } - let mut rng = thread_rng(); - const DATASZ: usize = 32; - const NTEST: usize = 10; - - // don't use 0 in the data -- we want to catch the zeroed-out case. - let data = (1..DATASZ + 1).collect::>(); - - // since it's a fuzzy test, run several tries. - for _ in 0..NTEST { - for i in 1..DATASZ + 1 { - DROP_COUNTER.store(0, Ordering::SeqCst); - - let mut panic_ords: Vec<_> = data.iter() - .filter(|&&x| x != i) - .map(|&x| PanicOrd(x, false)) - .collect(); - let panic_item = PanicOrd(i, true); - - // heapify the sane items - rng.shuffle(&mut panic_ords); - let mut heap = BinaryHeap::from(panic_ords); - let inner_data; - - { - // push the panicking item to the heap and catch the panic - let thread_result = { - let mut heap_ref = AssertUnwindSafe(&mut heap); - panic::catch_unwind(move || { - heap_ref.push(panic_item); - }) - }; - assert!(thread_result.is_err()); - - // Assert no elements were dropped - let drops = DROP_COUNTER.load(Ordering::SeqCst); - assert!(drops == 0, "Must not drop items. drops={}", drops); - inner_data = heap.clone().into_vec(); - drop(heap); - } - let drops = DROP_COUNTER.load(Ordering::SeqCst); - assert_eq!(drops, DATASZ); - - let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::>(); - data_sorted.sort(); - assert_eq!(data_sorted, data); - } - } -} - -fn main() { - test_integrity(); -} - diff --git a/src/test/run-pass-fulldeps/issue-35829.rs b/src/test/run-pass-fulldeps/issue-35829.rs index 07d4bd2fe151..798c214bc471 100644 --- a/src/test/run-pass-fulldeps/issue-35829.rs +++ b/src/test/run-pass-fulldeps/issue-35829.rs @@ -20,13 +20,16 @@ use syntax::ext::expand::ExpansionConfig; use syntax::parse::ParseSess; use syntax::codemap::{FilePathMapping, dummy_spanned}; use syntax::print::pprust::expr_to_string; -use syntax::ast::{Expr, ExprKind, LitKind, StrStyle, RangeLimits}; -use syntax::symbol::Symbol; +use syntax::ast::{ExprKind, LitKind, RangeLimits}; use syntax::ptr::P; use rustc_data_structures::sync::Lrc; fn main() { + syntax::with_globals(|| run()); +} + +fn run() { let parse_sess = ParseSess::new(FilePathMapping::empty()); let exp_cfg = ExpansionConfig::default("issue_35829".to_owned()); let mut resolver = DummyResolver; diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs index 10c44c8044b4..920760cd34ac 100644 --- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs @@ -84,18 +84,11 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { let mut g = |e| f(expr(e)); - for kind in 0 .. 17 { + for kind in 0 .. 16 { match kind { 0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))), - 1 => { - // Note that for binary expressions, we explore each side separately. The - // parenthesization decisions for the LHS and RHS should be independent, and this - // way produces `O(n)` results instead of `O(n^2)`. - iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(e, make_x()))); - iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(make_x(), e))); - }, - 2 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))), - 3 => { + 1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))), + 2 => { let seg = PathSegment { identifier: Ident::from_str("x"), span: DUMMY_SP, @@ -107,25 +100,25 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall( seg.clone(), vec![make_x(), e]))); }, - 4 => { + 3 => { let op = Spanned { span: DUMMY_SP, node: BinOpKind::Add }; iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x()))); iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e))); }, - 5 => { + 4 => { let op = Spanned { span: DUMMY_SP, node: BinOpKind::Mul }; iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x()))); iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e))); }, - 6 => { + 5 => { let op = Spanned { span: DUMMY_SP, node: BinOpKind::Shl }; iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x()))); iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e))); }, - 7 => { + 6 => { iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e))); }, - 8 => { + 7 => { let block = P(Block { stmts: Vec::new(), id: DUMMY_NODE_ID, @@ -135,7 +128,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { }); iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None))); }, - 9 => { + 8 => { let decl = P(FnDecl { inputs: vec![], output: FunctionRetTy::Default(DUMMY_SP), @@ -148,28 +141,28 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { e, DUMMY_SP))); }, - 10 => { + 9 => { iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x()))); iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e))); }, - 11 => { + 10 => { let ident = Spanned { span: DUMMY_SP, node: Ident::from_str("f") }; iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, ident))); }, - 12 => { + 11 => { iter_exprs(depth - 1, &mut |e| g(ExprKind::Range( Some(e), Some(make_x()), RangeLimits::HalfOpen))); iter_exprs(depth - 1, &mut |e| g(ExprKind::Range( Some(make_x()), Some(e), RangeLimits::HalfOpen))); }, - 13 => { + 12 => { iter_exprs(depth - 1, &mut |e| g(ExprKind::AddrOf(Mutability::Immutable, e))); }, - 14 => { + 13 => { g(ExprKind::Ret(None)); iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e)))); }, - 15 => { + 14 => { let seg = PathSegment { identifier: Ident::from_str("S"), span: DUMMY_SP, @@ -181,7 +174,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { }; g(ExprKind::Struct(path, vec![], Some(make_x()))); }, - 16 => { + 15 => { iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e))); }, _ => panic!("bad counter value in iter_exprs"), @@ -221,8 +214,11 @@ impl Folder for AddParens { } } - fn main() { + syntax::with_globals(|| run()); +} + +fn run() { let ps = ParseSess::new(FilePathMapping::empty()); iter_exprs(2, &mut |e| { diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs b/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs new file mode 100644 index 000000000000..98316c62ef13 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs @@ -0,0 +1,46 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:attr-stmt-expr.rs +// ignore-stage1 + +#![feature(proc_macro, stmt_expr_attributes)] + +extern crate attr_stmt_expr; +use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr, + no_output, noop}; + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_print_expr] + println!("{}", string) +} + +fn main() { + #[expect_let] + let string = "Hello, world!"; + + #[expect_print_stmt] + println!("{}", string); + + let _: () = { + #[no_output] + "Hello, world!" + }; + + let _: &'static str = #[noop] "Hello, world!"; + + let _: &'static str = { + #[noop] "Hello, world!" + }; + + #[expect_expr] + print_str("string") +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs new file mode 100644 index 000000000000..972368b7b532 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs @@ -0,0 +1,61 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "let string = \"Hello, world!\";"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println!(\"{}\" , string);"); + item +} + +#[proc_macro_attribute] +pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "print_str(\"string\")"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println!(\"{}\" , string)"); + item +} + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() + +} + +#[proc_macro_attribute] +pub fn noop(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + item +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/negative-token.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/negative-token.rs new file mode 100644 index 000000000000..e5ebb7c2e41b --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/negative-token.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn neg_one(_input: TokenStream) -> TokenStream { + TokenTree { + span: Span::call_site(), + kind: TokenNode::Literal(Literal::i32(-1)), + }.into() +} + +#[proc_macro] +pub fn neg_one_float(_input: TokenStream) -> TokenStream { + TokenTree { + span: Span::call_site(), + kind: TokenNode::Literal(Literal::f32(-1.0)), + }.into() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/negative-token.rs b/src/test/run-pass-fulldeps/proc-macro/negative-token.rs new file mode 100644 index 000000000000..418e692fa24a --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/negative-token.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:negative-token.rs +// ignore-stage1 + +#![feature(proc_macro)] + +extern crate negative_token; + +use negative_token::*; + +fn main() { + assert_eq!(-1, neg_one!()); + assert_eq!(-1.0, neg_one_float!()); +} diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 949aa8a9518c..c597360c0426 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -21,6 +21,10 @@ use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; fn main() { + syntax::with_globals(|| run()); +} + +fn run() { let ps = syntax::parse::ParseSess::new(FilePathMapping::empty()); let mut resolver = syntax::ext::base::DummyResolver; let mut cx = syntax::ext::base::ExtCtxt::new( diff --git a/src/test/run-pass-fulldeps/sort-unstable.rs b/src/test/run-pass-fulldeps/sort-unstable.rs deleted file mode 100644 index af8a691aa3ec..000000000000 --- a/src/test/run-pass-fulldeps/sort-unstable.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(rustc_private, sort_internals)] - -extern crate core; -extern crate rand; - -use std::cmp::Ordering::{Equal, Greater, Less}; -use core::slice::heapsort; - -use rand::{Rng, XorShiftRng}; - -fn main() { - let mut v = [0; 600]; - let mut tmp = [0; 600]; - let mut rng = XorShiftRng::new_unseeded(); - - for len in (2..25).chain(500..510) { - let v = &mut v[0..len]; - let tmp = &mut tmp[0..len]; - - for &modulus in &[5, 10, 100, 1000] { - for _ in 0..100 { - for i in 0..len { - v[i] = rng.gen::() % modulus; - } - - // Sort in default order. - tmp.copy_from_slice(v); - tmp.sort_unstable(); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in ascending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| a.cmp(b)); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Sort in descending order. - tmp.copy_from_slice(v); - tmp.sort_unstable_by(|a, b| b.cmp(a)); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - - // Test heapsort using `<` operator. - tmp.copy_from_slice(v); - heapsort(tmp, |a, b| a < b); - assert!(tmp.windows(2).all(|w| w[0] <= w[1])); - - // Test heapsort using `>` operator. - tmp.copy_from_slice(v); - heapsort(tmp, |a, b| a > b); - assert!(tmp.windows(2).all(|w| w[0] >= w[1])); - } - } - } - - // Sort using a completely random comparison function. - // This will reorder the elements *somehow*, but won't panic. - for i in 0..v.len() { - v[i] = i as i32; - } - v.sort_unstable_by(|_, _| *rng.choose(&[Less, Equal, Greater]).unwrap()); - v.sort_unstable(); - for i in 0..v.len() { - assert_eq!(v[i], i as i32); - } - - // Should not panic. - [0i32; 0].sort_unstable(); - [(); 10].sort_unstable(); - [(); 100].sort_unstable(); - - let mut v = [0xDEADBEEFu64]; - v.sort_unstable(); - assert!(v == [0xDEADBEEF]); -} diff --git a/src/test/run-pass-fulldeps/vector-sort-panic-safe.rs b/src/test/run-pass-fulldeps/vector-sort-panic-safe.rs deleted file mode 100644 index adc72aa0ea23..000000000000 --- a/src/test/run-pass-fulldeps/vector-sort-panic-safe.rs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-emscripten no threads support - -#![feature(rustc_private)] -#![feature(sort_unstable)] - -extern crate rand; - -use rand::{thread_rng, Rng}; -use std::cell::Cell; -use std::cmp::Ordering; -use std::panic; -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize}; -use std::sync::atomic::Ordering::Relaxed; -use std::thread; - -const MAX_LEN: usize = 80; - -static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ - // FIXME #5244: AtomicUsize is not Copy. - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), -]; - -static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT; - -#[derive(Clone, Eq)] -struct DropCounter { - x: u32, - id: usize, - version: Cell, -} - -impl PartialEq for DropCounter { - fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other) == Some(Ordering::Equal) - } -} - -impl PartialOrd for DropCounter { - fn partial_cmp(&self, other: &Self) -> Option { - self.version.set(self.version.get() + 1); - other.version.set(other.version.get() + 1); - VERSIONS.fetch_add(2, Relaxed); - self.x.partial_cmp(&other.x) - } -} - -impl Ord for DropCounter { - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).unwrap() - } -} - -impl Drop for DropCounter { - fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Relaxed); - VERSIONS.fetch_sub(self.version.get(), Relaxed); - } -} - -macro_rules! test { - ($input:ident, $func:ident) => { - let len = $input.len(); - - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) }); - - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - VERSIONS.store(0, Relaxed); - for i in 0..len { - DROP_COUNTS[i].store(0, Relaxed); - } - - let v = $input.to_owned(); - let _ = thread::spawn(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.$func(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }).join(); - - // Check that the number of things dropped is exactly - // what we expect (i.e. the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Relaxed); - assert!(count == 1, - "found drop count == {} for i == {}, len == {}", - count, i, len); - } - - // Check that the most recent versions of values were dropped. - assert_eq!(VERSIONS.load(Relaxed), 0); - } - } -} - -thread_local!(static SILENCE_PANIC: Cell = Cell::new(false)); - -fn main() { - let prev = panic::take_hook(); - panic::set_hook(Box::new(move |info| { - if !SILENCE_PANIC.with(|s| s.get()) { - prev(info); - } - })); - - let mut rng = thread_rng(); - - for len in (1..20).chain(70..MAX_LEN) { - for &modulus in &[5, 20, 50] { - for &has_runs in &[false, true] { - let mut input = (0..len) - .map(|id| { - DropCounter { - x: rng.next_u32() % modulus, - id: id, - version: Cell::new(0), - } - }) - .collect::>(); - - if has_runs { - for c in &mut input { - c.x = c.id as u32; - } - - for _ in 0..5 { - let a = rng.gen::() % len; - let b = rng.gen::() % len; - if a < b { - input[a..b].reverse(); - } else { - input.swap(a, b); - } - } - } - - test!(input, sort_by); - test!(input, sort_unstable_by); - } - } - } -} diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs b/src/test/run-pass/assert-escape.rs similarity index 72% rename from src/test/ui/rfc-2005-default-binding-mode/suggestion.rs rename to src/test/run-pass/assert-escape.rs index b9b974ff3c52..d340806c3577 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs +++ b/src/test/run-pass/assert-escape.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,7 +9,5 @@ // except according to those terms. fn main() { - if let Some(y) = &Some(22) { //~ ERROR non-reference pattern - println!("{}", y); - } + assert!(r#"☃\backslash"#.contains("\\")); } diff --git a/src/test/run-pass/attr-on-generic-formals.rs b/src/test/run-pass/attr-on-generic-formals.rs index 5985284d8496..e87b9e3d82a2 100644 --- a/src/test/run-pass/attr-on-generic-formals.rs +++ b/src/test/run-pass/attr-on-generic-formals.rs @@ -17,7 +17,7 @@ // using `rustc_attrs` feature. There is a separate compile-fail/ test // ensuring that the attribute feature-gating works in this context.) -#![feature(generic_param_attrs, rustc_attrs)] +#![feature(rustc_attrs)] #![allow(dead_code)] struct StLt<#[rustc_lt_struct] 'a>(&'a u32); diff --git a/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs b/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs index 1266e589b127..d89129434411 100644 --- a/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs +++ b/src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // The point of this test is to illustrate that the `#[may_dangle]` diff --git a/src/test/run-pass/auxiliary/unstable-macros.rs b/src/test/run-pass/auxiliary/unstable-macros.rs new file mode 100644 index 000000000000..6462c11af481 --- /dev/null +++ b/src/test/run-pass/auxiliary/unstable-macros.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(staged_api)] +#![stable(feature = "unit_test", since = "0.0.0")] + +#[unstable(feature = "unstable_macros", issue = "0")] +#[macro_export] +macro_rules! unstable_macro{ () => () } diff --git a/src/test/run-pass/clone-closure.rs b/src/test/run-pass/clone-closure.rs index 7f554c77fc4f..0fe3711d8d32 100644 --- a/src/test/run-pass/clone-closure.rs +++ b/src/test/run-pass/clone-closure.rs @@ -10,8 +10,6 @@ // Check that closures implement `Clone`. -#![feature(clone_closures)] - #[derive(Clone)] struct S(i32); diff --git a/src/test/run-pass/conservative_impl_trait.rs b/src/test/run-pass/conservative_impl_trait.rs index 30090018e294..14e1ca612c08 100644 --- a/src/test/run-pass/conservative_impl_trait.rs +++ b/src/test/run-pass/conservative_impl_trait.rs @@ -10,8 +10,6 @@ // #39665 -#![feature(conservative_impl_trait)] - fn batches(n: &u32) -> impl Iterator { std::iter::once(n) } diff --git a/src/test/run-pass/copy-closure.rs b/src/test/run-pass/copy-closure.rs index 309c83ebd99a..a211d6fc3a38 100644 --- a/src/test/run-pass/copy-closure.rs +++ b/src/test/run-pass/copy-closure.rs @@ -10,9 +10,6 @@ // Check that closures implement `Copy`. -#![feature(copy_closures)] -#![feature(clone_closures)] - fn call T>(f: F) -> T { f() } fn main() { diff --git a/src/test/run-pass/ctfe/signed_enum_discr.rs b/src/test/run-pass/ctfe/signed_enum_discr.rs new file mode 100644 index 000000000000..7049d28a8708 --- /dev/null +++ b/src/test/run-pass/ctfe/signed_enum_discr.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// https://github.com/rust-lang/rust/issues/49181 + +#[derive(Eq, PartialEq)] +#[repr(i8)] +pub enum A { + B = -1, + C = 1, +} + +pub const D: A = A::B; + +fn main() { + match A::C { + D => {}, + _ => {} + } +} diff --git a/src/test/run-pass/deep.rs b/src/test/run-pass/deep.rs index 9ae4f2c1e708..d59fe8d813d2 100644 --- a/src/test/run-pass/deep.rs +++ b/src/test/run-pass/deep.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - +// ignore-emscripten apparently blows the stack fn f(x: isize) -> isize { if x == 1 { return 1; } else { let y: isize = 1 + f(x - 1); return y; } diff --git a/src/test/run-pass/destructure-array-1.rs b/src/test/run-pass/destructure-array-1.rs index 0d24f0bd0d7b..43271162c181 100644 --- a/src/test/run-pass/destructure-array-1.rs +++ b/src/test/run-pass/destructure-array-1.rs @@ -11,9 +11,6 @@ // Ensure that we can do a destructuring bind of a fixed-size array, // even when the element type has a destructor. - -#![feature(slice_patterns)] - struct D { x: u8 } impl Drop for D { fn drop(&mut self) { } } diff --git a/src/test/run-pass/diverging-fallback-control-flow.rs b/src/test/run-pass/diverging-fallback-control-flow.rs index 723a98bcdfa0..a96f98b9efda 100644 --- a/src/test/run-pass/diverging-fallback-control-flow.rs +++ b/src/test/run-pass/diverging-fallback-control-flow.rs @@ -14,8 +14,6 @@ // These represent current behavior, but are pretty dubious. I would // like to revisit these and potentially change them. --nmatsakis -#![feature(never_type)] - trait BadDefault { fn default() -> Self; } diff --git a/src/test/run-pass/dropck-eyepatch-reorder.rs b/src/test/run-pass/dropck-eyepatch-reorder.rs index bbf8bb8c3523..a99a7232e9eb 100644 --- a/src/test/run-pass/dropck-eyepatch-reorder.rs +++ b/src/test/run-pass/dropck-eyepatch-reorder.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // The point of this test is to test uses of `#[may_dangle]` attribute diff --git a/src/test/run-pass/dropck-eyepatch.rs b/src/test/run-pass/dropck-eyepatch.rs index 4a09ba05dff5..c0c091d78eb1 100644 --- a/src/test/run-pass/dropck-eyepatch.rs +++ b/src/test/run-pass/dropck-eyepatch.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // The point of this test is to illustrate that the `#[may_dangle]` diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs index fdec6a26ac94..399823ec92d0 100644 --- a/src/test/run-pass/dyn-trait.rs +++ b/src/test/run-pass/dyn-trait.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-pretty `dyn ::foo` parses differently in the current epoch +// ignore-pretty `dyn ::foo` parses differently in the current edition #![feature(dyn_trait)] diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 4d0bd3f3412f..765fb06e5f3a 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -13,7 +13,8 @@ // ignore-wasm32-bare compiled with panic=abort by default -#![feature(generators, generator_trait, untagged_unions, slice_patterns, advanced_slice_patterns)] +#![feature(generators, generator_trait, untagged_unions)] +#![feature(slice_patterns)] use std::cell::{Cell, RefCell}; use std::ops::Generator; @@ -178,7 +179,7 @@ fn generator(a: &Allocator, run_count: usize) { ); }; for _ in 0..run_count { - gen.resume(); + unsafe { gen.resume(); } } } diff --git a/src/test/run-pass/empty-types-in-patterns.rs b/src/test/run-pass/empty-types-in-patterns.rs index 033b185a0ef0..87db44019298 100644 --- a/src/test/run-pass/empty-types-in-patterns.rs +++ b/src/test/run-pass/empty-types-in-patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] +#![feature(exhaustive_patterns)] #![feature(slice_patterns)] #![allow(unreachable_patterns)] #![allow(unreachable_code)] diff --git a/src/test/run-pass/enum-null-pointer-opt.rs b/src/test/run-pass/enum-null-pointer-opt.rs index e296aff2782c..12f17a1575e8 100644 --- a/src/test/run-pass/enum-null-pointer-opt.rs +++ b/src/test/run-pass/enum-null-pointer-opt.rs @@ -10,10 +10,9 @@ #![feature(nonzero, core)] -extern crate core; - -use core::nonzero::NonZero; use std::mem::size_of; +use std::num::NonZeroUsize; +use std::ptr::NonNull; use std::rc::Rc; use std::sync::Arc; @@ -59,8 +58,8 @@ fn main() { assert_eq!(size_of::<[Box; 1]>(), size_of::; 1]>>()); // Should apply to NonZero - assert_eq!(size_of::>(), size_of::>>()); - assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::>(), size_of::>>()); // Should apply to types that use NonZero internally assert_eq!(size_of::>(), size_of::>>()); diff --git a/src/test/run-pass/epoch-gate-feature.rs b/src/test/run-pass/epoch-gate-feature.rs index 37d092c06e02..e3cd1edd2098 100644 --- a/src/test/run-pass/epoch-gate-feature.rs +++ b/src/test/run-pass/epoch-gate-feature.rs @@ -11,7 +11,7 @@ // Checks if the correct registers are being used to pass arguments // when the sysv64 ABI is specified. -// compile-flags: -Zepoch=2018 +#![feature(rust_2018_preview)] pub trait Foo {} diff --git a/src/test/run-pass/float-int-invalid-const-cast.rs b/src/test/run-pass/float-int-invalid-const-cast.rs index 80ab12482cbb..f84432abbfa0 100644 --- a/src/test/run-pass/float-int-invalid-const-cast.rs +++ b/src/test/run-pass/float-int-invalid-const-cast.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(i128_type)] +// ignore-emscripten no i128 support + #![deny(const_err)] use std::{f32, f64}; diff --git a/src/test/run-pass/generator/auxiliary/xcrate-reachable.rs b/src/test/run-pass/generator/auxiliary/xcrate-reachable.rs index a6a2a2d081e1..91e43537cc21 100644 --- a/src/test/run-pass/generator/auxiliary/xcrate-reachable.rs +++ b/src/test/run-pass/generator/auxiliary/xcrate-reachable.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, generators, generator_trait)] +#![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/src/test/run-pass/generator/auxiliary/xcrate.rs b/src/test/run-pass/generator/auxiliary/xcrate.rs index f6878e64fbf9..fcfe0b754b68 100644 --- a/src/test/run-pass/generator/auxiliary/xcrate.rs +++ b/src/test/run-pass/generator/auxiliary/xcrate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generators, generator_trait, conservative_impl_trait)] +#![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/src/test/run-pass/generator/conditional-drop.rs b/src/test/run-pass/generator/conditional-drop.rs index 8329684e1a39..3d39c46186be 100644 --- a/src/test/run-pass/generator/conditional-drop.rs +++ b/src/test/run-pass/generator/conditional-drop.rs @@ -42,9 +42,9 @@ fn t1() { }; let n = A.load(Ordering::SeqCst); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n + 1); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n + 1); } @@ -58,8 +58,8 @@ fn t2() { }; let n = A.load(Ordering::SeqCst); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n); - a.resume(); + unsafe { a.resume() }; assert_eq!(A.load(Ordering::SeqCst), n + 1); } diff --git a/src/test/run-pass/generator/control-flow.rs b/src/test/run-pass/generator/control-flow.rs index 60a00b4e4675..09971410e556 100644 --- a/src/test/run-pass/generator/control-flow.rs +++ b/src/test/run-pass/generator/control-flow.rs @@ -16,7 +16,7 @@ fn finish(mut amt: usize, mut t: T) -> T::Return where T: Generator { loop { - match t.resume() { + match unsafe { t.resume() } { GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(), GeneratorState::Complete(ret) => { assert_eq!(amt, 0); diff --git a/src/test/run-pass/generator/drop-env.rs b/src/test/run-pass/generator/drop-env.rs index ac42a25899db..ef4dc24472e6 100644 --- a/src/test/run-pass/generator/drop-env.rs +++ b/src/test/run-pass/generator/drop-env.rs @@ -37,7 +37,7 @@ fn t1() { }; let n = A.load(Ordering::SeqCst); - drop(foo.resume()); + drop(unsafe { foo.resume() }); assert_eq!(A.load(Ordering::SeqCst), n); drop(foo); assert_eq!(A.load(Ordering::SeqCst), n + 1); @@ -50,7 +50,7 @@ fn t2() { }; let n = A.load(Ordering::SeqCst); - drop(foo.resume()); + drop(unsafe { foo.resume() }); assert_eq!(A.load(Ordering::SeqCst), n + 1); drop(foo); assert_eq!(A.load(Ordering::SeqCst), n + 1); diff --git a/src/test/run-pass/generator/issue-44197.rs b/src/test/run-pass/generator/issue-44197.rs index 7cb80ea8b21b..272b7eb7bfdd 100644 --- a/src/test/run-pass/generator/issue-44197.rs +++ b/src/test/run-pass/generator/issue-44197.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, generators, generator_trait)] +#![feature(generators, generator_trait)] use std::ops::{ Generator, GeneratorState }; @@ -35,6 +35,8 @@ fn bar2(baz: String) -> impl Generator { } fn main() { - assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new())); - assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(())); + unsafe { + assert_eq!(bar(String::new()).resume(), GeneratorState::Yielded(String::new())); + assert_eq!(bar2(String::new()).resume(), GeneratorState::Complete(())); + } } diff --git a/src/test/run-pass/generator/iterator-count.rs b/src/test/run-pass/generator/iterator-count.rs index 9afe95f9e865..3564ddaa8068 100644 --- a/src/test/run-pass/generator/iterator-count.rs +++ b/src/test/run-pass/generator/iterator-count.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generators, generator_trait, conservative_impl_trait)] +#![feature(generators, generator_trait)] use std::ops::{GeneratorState, Generator}; struct W(T); +// This impl isn't safe in general, but the generator used in this test is movable +// so it won't cause problems. impl> Iterator for W { type Item = T::Yield; fn next(&mut self) -> Option { - match self.0.resume() { + match unsafe { self.0.resume() } { GeneratorState::Complete(..) => None, GeneratorState::Yielded(v) => Some(v), } diff --git a/src/test/run-pass/generator/live-upvar-across-yield.rs b/src/test/run-pass/generator/live-upvar-across-yield.rs index e34b0b3100c3..28e7da232ce0 100644 --- a/src/test/run-pass/generator/live-upvar-across-yield.rs +++ b/src/test/run-pass/generator/live-upvar-across-yield.rs @@ -17,5 +17,5 @@ fn main() { let mut a = || { b(yield); }; - a.resume(); + unsafe { a.resume() }; } diff --git a/src/test/run-pass/generator/nested_generators.rs b/src/test/run-pass/generator/nested_generators.rs index f70d4144a3c9..29808da85a7a 100644 --- a/src/test/run-pass/generator/nested_generators.rs +++ b/src/test/run-pass/generator/nested_generators.rs @@ -20,7 +20,7 @@ fn main() { yield 2; }; - match sub_generator.resume() { + match unsafe { sub_generator.resume() } { GeneratorState::Yielded(x) => { yield x; } diff --git a/src/test/run-pass/generator/panic-drops.rs b/src/test/run-pass/generator/panic-drops.rs index 36e401a54bcd..3d7b60ab6b90 100644 --- a/src/test/run-pass/generator/panic-drops.rs +++ b/src/test/run-pass/generator/panic-drops.rs @@ -42,7 +42,7 @@ fn main() { assert_eq!(A.load(Ordering::SeqCst), 0); let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); @@ -57,7 +57,7 @@ fn main() { assert_eq!(A.load(Ordering::SeqCst), 1); let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); diff --git a/src/test/run-pass/generator/panic-safe.rs b/src/test/run-pass/generator/panic-safe.rs index 0d5bae7876bd..ace5cdde51d8 100644 --- a/src/test/run-pass/generator/panic-safe.rs +++ b/src/test/run-pass/generator/panic-safe.rs @@ -24,13 +24,13 @@ fn main() { }; let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); for _ in 0..10 { let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - foo.resume() + unsafe { foo.resume() } })); assert!(res.is_err()); } diff --git a/src/test/run-pass/generator/resume-after-return.rs b/src/test/run-pass/generator/resume-after-return.rs index 56511dcd53a6..06e7615d2619 100644 --- a/src/test/run-pass/generator/resume-after-return.rs +++ b/src/test/run-pass/generator/resume-after-return.rs @@ -23,12 +23,12 @@ fn main() { yield; }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } - match panic::catch_unwind(move || foo.resume()) { + match panic::catch_unwind(move || unsafe { foo.resume() }) { Ok(_) => panic!("generator successfully resumed"), Err(_) => {} } diff --git a/src/test/run-pass/generator/smoke.rs b/src/test/run-pass/generator/smoke.rs index 8693964665d3..7395c8484c16 100644 --- a/src/test/run-pass/generator/smoke.rs +++ b/src/test/run-pass/generator/smoke.rs @@ -24,7 +24,7 @@ fn simple() { } }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -40,7 +40,7 @@ fn return_capture() { a }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -52,11 +52,11 @@ fn simple_yield() { yield; }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -69,11 +69,11 @@ fn yield_capture() { yield b; }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -86,11 +86,11 @@ fn simple_yield_value() { return String::from("foo") }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(ref s) if *s == "bar" => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -104,11 +104,11 @@ fn return_after_yield() { return a }; - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } @@ -156,11 +156,11 @@ fn send_and_sync() { fn send_over_threads() { let mut foo = || { yield }; thread::spawn(move || { - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } @@ -169,11 +169,11 @@ fn send_over_threads() { let a = String::from("a"); let mut foo = || { yield a }; thread::spawn(move || { - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(ref s) if *s == "a" => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } diff --git a/src/test/run-pass/generator/static-generators.rs b/src/test/run-pass/generator/static-generators.rs index 9504414d8b6f..ebc070eee09c 100644 --- a/src/test/run-pass/generator/static-generators.rs +++ b/src/test/run-pass/generator/static-generators.rs @@ -13,14 +13,14 @@ use std::ops::{Generator, GeneratorState}; fn main() { - let mut generator = unsafe { - static || { - let a = true; - let b = &a; - yield; - assert_eq!(b as *const _, &a as *const _); - } + let mut generator = static || { + let a = true; + let b = &a; + yield; + assert_eq!(b as *const _, &a as *const _); }; - assert_eq!(generator.resume(), GeneratorState::Yielded(())); - assert_eq!(generator.resume(), GeneratorState::Complete(())); + unsafe { + assert_eq!(generator.resume(), GeneratorState::Yielded(())); + assert_eq!(generator.resume(), GeneratorState::Complete(())); + } } diff --git a/src/test/run-pass/generator/xcrate-reachable.rs b/src/test/run-pass/generator/xcrate-reachable.rs index dff5e08b9c20..2fc39ba18691 100644 --- a/src/test/run-pass/generator/xcrate-reachable.rs +++ b/src/test/run-pass/generator/xcrate-reachable.rs @@ -10,12 +10,12 @@ // aux-build:xcrate-reachable.rs -#![feature(conservative_impl_trait, generator_trait)] +#![feature(generator_trait)] extern crate xcrate_reachable as foo; use std::ops::Generator; fn main() { - foo::foo().resume(); + unsafe { foo::foo().resume(); } } diff --git a/src/test/run-pass/generator/xcrate.rs b/src/test/run-pass/generator/xcrate.rs index dc7a6fdef9c7..04791d513567 100644 --- a/src/test/run-pass/generator/xcrate.rs +++ b/src/test/run-pass/generator/xcrate.rs @@ -19,18 +19,18 @@ use std::ops::{GeneratorState, Generator}; fn main() { let mut foo = xcrate::foo(); - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } let mut foo = xcrate::bar(3); - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Yielded(3) => {} s => panic!("bad state: {:?}", s), } - match foo.resume() { + match unsafe { foo.resume() } { GeneratorState::Complete(()) => {} s => panic!("bad state: {:?}", s), } diff --git a/src/test/run-pass/generator/yield-subtype.rs b/src/test/run-pass/generator/yield-subtype.rs index 7e8a0d1e2b92..c41341690441 100644 --- a/src/test/run-pass/generator/yield-subtype.rs +++ b/src/test/run-pass/generator/yield-subtype.rs @@ -9,6 +9,7 @@ // except according to those terms. // revisions:lexical nll +//[nll]compile-flags: -Z disable-nll-user-type-assert #![cfg_attr(nll, feature(nll))] #![feature(generators)] diff --git a/src/test/run-pass/i128-ffi.rs b/src/test/run-pass/i128-ffi.rs index d989210dd71f..edf278cbf64a 100644 --- a/src/test/run-pass/i128-ffi.rs +++ b/src/test/run-pass/i128-ffi.rs @@ -15,8 +15,6 @@ // ignore-windows // ignore-32bit -#![feature(i128_type)] - #[link(name = "rust_test_helpers", kind = "static")] extern "C" { fn identity(f: u128) -> u128; diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs index c3e43c92590e..baf3b3399849 100644 --- a/src/test/run-pass/i128.rs +++ b/src/test/run-pass/i128.rs @@ -12,7 +12,7 @@ // compile-flags: -Z borrowck=compare -#![feature(i128_type, test)] +#![feature(test)] extern crate test; use test::black_box as b; diff --git a/src/test/run-pass/ignore-all-the-things.rs b/src/test/run-pass/ignore-all-the-things.rs index 711f2dd6c667..c14f3dc72916 100644 --- a/src/test/run-pass/ignore-all-the-things.rs +++ b/src/test/run-pass/ignore-all-the-things.rs @@ -10,7 +10,6 @@ // pretty-expanded FIXME #23616 -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] struct Foo(isize, isize, isize, isize); @@ -20,11 +19,11 @@ pub fn main() { let Foo(..) = Foo(5, 5, 5, 5); let Foo(..) = Foo(5, 5, 5, 5); let Bar{..} = Bar{a: 5, b: 5, c: 5, d: 5}; - //let (..) = (5, 5, 5, 5); - //let Foo(a, b, ..) = Foo(5, 5, 5, 5); - //let Foo(.., d) = Foo(5, 5, 5, 5); - //let (a, b, ..) = (5, 5, 5, 5); - //let (.., c, d) = (5, 5, 5, 5); + let (..) = (5, 5, 5, 5); + let Foo(a, b, ..) = Foo(5, 5, 5, 5); + let Foo(.., d) = Foo(5, 5, 5, 5); + let (a, b, ..) = (5, 5, 5, 5); + let (.., c, d) = (5, 5, 5, 5); let Bar{b: b, ..} = Bar{a: 5, b: 5, c: 5, d: 5}; match [5, 5, 5, 5] { [..] => { } diff --git a/src/test/run-pass/impl-for-never.rs b/src/test/run-pass/impl-for-never.rs index 794f5969bff5..cf54e1c3bd59 100644 --- a/src/test/run-pass/impl-for-never.rs +++ b/src/test/run-pass/impl-for-never.rs @@ -10,8 +10,6 @@ // Test that we can call static methods on ! both directly and when it appears in a generic -#![feature(never_type)] - trait StringifyType { fn stringify_type() -> &'static str; } diff --git a/src/test/run-pass/impl-trait/auto-trait-leak.rs b/src/test/run-pass/impl-trait/auto-trait-leak.rs index 011d910c5a50..62fbae7b40c0 100644 --- a/src/test/run-pass/impl-trait/auto-trait-leak.rs +++ b/src/test/run-pass/impl-trait/auto-trait-leak.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - // Fast path, main can see the concrete type returned. fn before() -> impl FnMut(i32) { let mut p = Box::new(0); diff --git a/src/test/run-pass/impl-trait/auxiliary/xcrate.rs b/src/test/run-pass/impl-trait/auxiliary/xcrate.rs index e4f525a98261..c27a2dd89d52 100644 --- a/src/test/run-pass/impl-trait/auxiliary/xcrate.rs +++ b/src/test/run-pass/impl-trait/auxiliary/xcrate.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - // NOTE commented out due to issue #45994 //pub fn fourway_add(a: i32) -> impl Fn(i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 { // move |b| move |c| move |d| a + b + c + d diff --git a/src/test/run-pass/impl-trait/equality.rs b/src/test/run-pass/impl-trait/equality.rs index ceed454e5ad7..034d3d7c80f3 100644 --- a/src/test/run-pass/impl-trait/equality.rs +++ b/src/test/run-pass/impl-trait/equality.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, specialization)] +#![feature(specialization)] trait Foo: std::fmt::Debug + Eq {} diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index aca100591dde..b1db20307178 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -11,9 +11,7 @@ // revisions: normal nll //[nll] compile-flags: -Znll -Zborrowck=mir -#![feature(conservative_impl_trait, - universal_impl_trait, - fn_traits, +#![feature(fn_traits, step_trait, unboxed_closures, copy_closures, diff --git a/src/test/run-pass/impl-trait/example-st.rs b/src/test/run-pass/impl-trait/example-st.rs index e9326ed286af..a06bde7f532d 100644 --- a/src/test/run-pass/impl-trait/example-st.rs +++ b/src/test/run-pass/impl-trait/example-st.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - struct State; type Error = (); diff --git a/src/test/run-pass/impl-trait/issue-42479.rs b/src/test/run-pass/impl-trait/issue-42479.rs index 629948a5dc4a..df7a6c130922 100644 --- a/src/test/run-pass/impl-trait/issue-42479.rs +++ b/src/test/run-pass/impl-trait/issue-42479.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - use std::iter::once; struct Foo { diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index fcad23926fc0..d126d795d909 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, underscore_lifetimes, universal_impl_trait)] #![allow(warnings)] use std::fmt::Debug; diff --git a/src/test/run-pass/impl-trait/universal_hrtb_anon.rs b/src/test/run-pass/impl-trait/universal_hrtb_anon.rs index 48874ef41de5..9fc74757da0b 100644 --- a/src/test/run-pass/impl-trait/universal_hrtb_anon.rs +++ b/src/test/run-pass/impl-trait/universal_hrtb_anon.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - fn hrtb(f: impl Fn(&u32) -> u32) -> u32 { f(&22) + f(&44) } diff --git a/src/test/run-pass/impl-trait/universal_hrtb_named.rs b/src/test/run-pass/impl-trait/universal_hrtb_named.rs index 95147a542005..3aefc79ebf78 100644 --- a/src/test/run-pass/impl-trait/universal_hrtb_named.rs +++ b/src/test/run-pass/impl-trait/universal_hrtb_named.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - fn hrtb(f: impl for<'a> Fn(&'a u32) -> &'a u32) -> u32 { f(&22) + f(&44) } diff --git a/src/test/run-pass/impl-trait/universal_in_adt_in_parameters.rs b/src/test/run-pass/impl-trait/universal_in_adt_in_parameters.rs index d0f18575297b..57452a2e475c 100644 --- a/src/test/run-pass/impl-trait/universal_in_adt_in_parameters.rs +++ b/src/test/run-pass/impl-trait/universal_in_adt_in_parameters.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] use std::fmt::Display; fn check_display_eq(iter: &Vec) { diff --git a/src/test/run-pass/impl-trait/universal_in_impl_trait_in_parameters.rs b/src/test/run-pass/impl-trait/universal_in_impl_trait_in_parameters.rs index ccf24b77a6b7..fea946f12584 100644 --- a/src/test/run-pass/impl-trait/universal_in_impl_trait_in_parameters.rs +++ b/src/test/run-pass/impl-trait/universal_in_impl_trait_in_parameters.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] use std::fmt::Display; fn check_display_eq(iter: impl IntoIterator) { diff --git a/src/test/run-pass/impl-trait/universal_in_trait_defn_parameters.rs b/src/test/run-pass/impl-trait/universal_in_trait_defn_parameters.rs index af0201b5f871..d3611e02e025 100644 --- a/src/test/run-pass/impl-trait/universal_in_trait_defn_parameters.rs +++ b/src/test/run-pass/impl-trait/universal_in_trait_defn_parameters.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - use std::fmt::Debug; trait InTraitDefnParameters { diff --git a/src/test/run-pass/impl-trait/universal_multiple_bounds.rs b/src/test/run-pass/impl-trait/universal_multiple_bounds.rs index bb332c0c96cb..594207feb09a 100644 --- a/src/test/run-pass/impl-trait/universal_multiple_bounds.rs +++ b/src/test/run-pass/impl-trait/universal_multiple_bounds.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - use std::fmt::Display; fn foo(f: impl Display + Clone) -> String { diff --git a/src/test/run-pass/in-band-lifetimes.rs b/src/test/run-pass/in-band-lifetimes.rs index 95cc3c3759e6..6edd0d686eff 100644 --- a/src/test/run-pass/in-band-lifetimes.rs +++ b/src/test/run-pass/in-band-lifetimes.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(warnings)] -#![feature(in_band_lifetimes, universal_impl_trait, conservative_impl_trait)] +#![feature(in_band_lifetimes)] fn foo(x: &'x u8) -> &'x u8 { x } fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x } diff --git a/src/test/run-pass/inc-range-pat.rs b/src/test/run-pass/inc-range-pat.rs index 5faf36eddaf0..237b41b6128c 100644 --- a/src/test/run-pass/inc-range-pat.rs +++ b/src/test/run-pass/inc-range-pat.rs @@ -9,8 +9,6 @@ // except according to those terms. // Test old and new syntax for inclusive range patterns. -#![feature(dotdoteq_in_patterns)] - fn main() { assert!(match 42 { 0 ... 100 => true, _ => false }); diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index bfa3a1e128a9..7a8ff1befc7f 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(intrinsics, i128_type)] +// ignore-emscripten no i128 support + +#![feature(intrinsics)] mod rusti { extern "rust-intrinsic" { diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index a2c55634749c..5132405a9d58 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten fma not implemented in emscripten + macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ let (a, b) = (&$a, &$b); diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index eb2177202a22..d3ba477fa573 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -10,8 +10,6 @@ // pretty-expanded FIXME #23616 -use std::ascii::AsciiExt; - static NAME: &'static str = "hello world"; fn main() { diff --git a/src/test/run-pass/issue-13027.rs b/src/test/run-pass/issue-13027.rs index 149874847117..d28ea94ec1a0 100644 --- a/src/test/run-pass/issue-13027.rs +++ b/src/test/run-pass/issue-13027.rs @@ -12,8 +12,6 @@ // Tests that match expression handles overlapped literal and range // properly in the presence of guard function. -#![feature(slice_patterns)] - fn val() -> usize { 1 } static CONST: usize = 1; diff --git a/src/test/run-pass/issue-15080.rs b/src/test/run-pass/issue-15080.rs index 14e003788469..59267f79e264 100644 --- a/src/test/run-pass/issue-15080.rs +++ b/src/test/run-pass/issue-15080.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(slice_patterns)] fn main() { diff --git a/src/test/run-pass/issue-15104.rs b/src/test/run-pass/issue-15104.rs index 508360cb7011..2878f2795c59 100644 --- a/src/test/run-pass/issue-15104.rs +++ b/src/test/run-pass/issue-15104.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(slice_patterns)] fn main() { diff --git a/src/test/run-pass/issue-16648.rs b/src/test/run-pass/issue-16648.rs index e1b94179764b..bf272308fa9d 100644 --- a/src/test/run-pass/issue-16648.rs +++ b/src/test/run-pass/issue-16648.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(slice_patterns)] - fn main() { let x: (isize, &[isize]) = (2, &[1, 2]); assert_eq!(match x { diff --git a/src/test/run-pass/issue-17877.rs b/src/test/run-pass/issue-17877.rs index 6c87e8d35fbf..d3fe0903a1d6 100644 --- a/src/test/run-pass/issue-17877.rs +++ b/src/test/run-pass/issue-17877.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(slice_patterns)] fn main() { diff --git a/src/test/run-pass/issue-23433.rs b/src/test/run-pass/issue-23433.rs index 7af732f561de..9547b2f08a6b 100644 --- a/src/test/run-pass/issue-23433.rs +++ b/src/test/run-pass/issue-23433.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Don't fail if we encounter a NonZero<*T> where T is an unsized type +// Don't fail if we encounter a NonNull where T is an unsized type use std::ptr::NonNull; diff --git a/src/test/run-pass/issue-27889.rs b/src/test/run-pass/issue-27889.rs index 3f7d0400c884..29a5f6dd24bd 100644 --- a/src/test/run-pass/issue-27889.rs +++ b/src/test/run-pass/issue-27889.rs @@ -10,7 +10,6 @@ // Test that a field can have the same name in different variants // of an enum -// FIXME #27889 pub enum Foo { X { foo: u32 }, diff --git a/src/test/run-pass/issue-28561.rs b/src/test/run-pass/issue-28561.rs index 8c73830f4d77..e21e487fedd1 100644 --- a/src/test/run-pass/issue-28561.rs +++ b/src/test/run-pass/issue-28561.rs @@ -45,7 +45,7 @@ struct Array { f32: [T; 32], } -// FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone` +// FIXME(#44580): merge with `Array` once `[T; N]: Clone` where `T: Clone` #[derive(Clone, Copy)] struct CopyArray { f00: [T; 00], diff --git a/src/test/run-pass/issue-32947.rs b/src/test/run-pass/issue-32947.rs index d0fef36efb9c..d059a46b4df1 100644 --- a/src/test/run-pass/issue-32947.rs +++ b/src/test/run-pass/issue-32947.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten FIXME(#45351) + #![feature(repr_simd, test)] extern crate test; diff --git a/src/test/run-pass/issue-36792.rs b/src/test/run-pass/issue-36792.rs index faf983f6ecb1..f2755ec3f846 100644 --- a/src/test/run-pass/issue-36792.rs +++ b/src/test/run-pass/issue-36792.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] fn foo() -> impl Copy { foo } diff --git a/src/test/run-pass/issue-37598.rs b/src/test/run-pass/issue-37598.rs index d32d2fc29544..e97c8d9f4176 100644 --- a/src/test/run-pass/issue-37598.rs +++ b/src/test/run-pass/issue-37598.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns, slice_patterns)] +#![feature(slice_patterns)] fn check(list: &[u8]) { match list { diff --git a/src/test/run-pass/issue-38002.rs b/src/test/run-pass/issue-38002.rs index 489d35e9147a..dd6ccec973fc 100644 --- a/src/test/run-pass/issue-38002.rs +++ b/src/test/run-pass/issue-38002.rs @@ -10,8 +10,6 @@ // Check that constant ADTs are translated OK, part k of N. -#![feature(slice_patterns)] - enum Bar { C } diff --git a/src/test/run-pass/issue-38074.rs b/src/test/run-pass/issue-38074.rs index 5c9a63b86166..2368ba8a110b 100644 --- a/src/test/run-pass/issue-38074.rs +++ b/src/test/run-pass/issue-38074.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten FIXME(#45351) + #![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { diff --git a/src/test/run-pass/issue-38763.rs b/src/test/run-pass/issue-38763.rs index 01cc8265a399..e038062ff9ae 100644 --- a/src/test/run-pass/issue-38763.rs +++ b/src/test/run-pass/issue-38763.rs @@ -10,8 +10,6 @@ // ignore-emscripten -#![feature(i128_type)] - #[repr(C)] pub struct Foo(i128); diff --git a/src/test/run-pass/issue-38987.rs b/src/test/run-pass/issue-38987.rs index a513476d4a33..31a3b7233d8c 100644 --- a/src/test/run-pass/issue-38987.rs +++ b/src/test/run-pass/issue-38987.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(i128_type)] fn main() { let _ = -0x8000_0000_0000_0000_0000_0000_0000_0000i128; diff --git a/src/test/run-pass/issue-39720.rs b/src/test/run-pass/issue-39720.rs index f90696e3cdf1..9873a8c2bf44 100644 --- a/src/test/run-pass/issue-39720.rs +++ b/src/test/run-pass/issue-39720.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten FIXME(#45351) + #![feature(repr_simd, platform_intrinsics)] #[repr(C)] diff --git a/src/test/compile-fail/issue-14084.rs b/src/test/run-pass/issue-42453.rs similarity index 78% rename from src/test/compile-fail/issue-14084.rs rename to src/test/run-pass/issue-42453.rs index 446514c8dd45..dfe3a21961e3 100644 --- a/src/test/compile-fail/issue-14084.rs +++ b/src/test/run-pass/issue-42453.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] -#![feature(placement_in_syntax)] +#[derive(Debug)] +struct builder; fn main() { - () <- 0; - //~^ ERROR: `(): std::ops::Placer<_>` is not satisfied + } + diff --git a/src/test/run-pass/issue-44402.rs b/src/test/run-pass/issue-44402.rs index 244aa65a3d56..a5a0a5a57944 100644 --- a/src/test/run-pass/issue-44402.rs +++ b/src/test/run-pass/issue-44402.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] +#![feature(exhaustive_patterns)] // Regression test for inhabitedness check. The old // cache used to cause us to incorrectly decide diff --git a/src/test/run-pass/issue-46855.rs b/src/test/run-pass/issue-46855.rs index d864d55c9397..28aa6c731ec8 100644 --- a/src/test/run-pass/issue-46855.rs +++ b/src/test/run-pass/issue-46855.rs @@ -10,8 +10,6 @@ // compile-flags: -Zmir-opt-level=1 -#![feature(slice_patterns)] - use std::mem; #[derive(Copy, Clone)] diff --git a/src/test/run-pass/issue-46959.rs b/src/test/run-pass/issue-46959.rs index 0826f5e49238..7f050c055b0c 100644 --- a/src/test/run-pass/issue-46959.rs +++ b/src/test/run-pass/issue-46959.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] -#![feature(conservative_impl_trait)] #![deny(non_camel_case_types)] #[allow(dead_code)] diff --git a/src/test/run-pass/issue-7784.rs b/src/test/run-pass/issue-7784.rs index badc013cd621..8d21594aa12c 100644 --- a/src/test/run-pass/issue-7784.rs +++ b/src/test/run-pass/issue-7784.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] use std::ops::Add; diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs index 39053769b24b..ffdd99ebf6e5 100644 --- a/src/test/run-pass/loop-break-value.rs +++ b/src/test/run-pass/loop-break-value.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] - #[allow(unused)] fn never_returns() { loop { diff --git a/src/test/run-pass/macro-stability.rs b/src/test/run-pass/macro-stability.rs new file mode 100644 index 000000000000..9afcd51aa85a --- /dev/null +++ b/src/test/run-pass/macro-stability.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:unstable-macros.rs + +#![feature(unstable_macros)] + +#[macro_use] extern crate unstable_macros; + +#[unstable(feature = "local_unstable", issue = "0")] +macro_rules! local_unstable { () => () } + +fn main() { + unstable_macro!(); + local_unstable!(); +} diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs index 78a37f518378..ca6ef2e42777 100644 --- a/src/test/run-pass/match-arm-statics.rs +++ b/src/test/run-pass/match-arm-statics.rs @@ -94,6 +94,13 @@ fn issue_14576() { const F : C = C::D; assert_eq!(match C::D { F => 1, _ => 2, }, 1); + + // test gaps + #[derive(PartialEq, Eq)] + enum G { H = 3, I = 5 } + const K : G = G::I; + + assert_eq!(match G::I { K => 1, _ => 2, }, 1); } fn issue_13731() { diff --git a/src/test/run-pass/match-vec-alternatives.rs b/src/test/run-pass/match-vec-alternatives.rs index fa609593c24b..7d03d9c2abe2 100644 --- a/src/test/run-pass/match-vec-alternatives.rs +++ b/src/test/run-pass/match-vec-alternatives.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { diff --git a/src/test/run-pass/mir_calls_to_shims.rs b/src/test/run-pass/mir_calls_to_shims.rs index 9641ed282936..dda7a46f3258 100644 --- a/src/test/run-pass/mir_calls_to_shims.rs +++ b/src/test/run-pass/mir_calls_to_shims.rs @@ -11,7 +11,6 @@ // ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] -#![feature(never_type)] use std::panic; diff --git a/src/test/run-pass/mir_heavy_promoted.rs b/src/test/run-pass/mir_heavy_promoted.rs index 9e033421574b..b50852175776 100644 --- a/src/test/run-pass/mir_heavy_promoted.rs +++ b/src/test/run-pass/mir_heavy_promoted.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten apparently only works in optimized mode + const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024]; // Check that the promoted copy of TEST_DATA doesn't diff --git a/src/test/run-pass/never-result.rs b/src/test/run-pass/never-result.rs index 5c0af392f44d..8aa2a13ed8c8 100644 --- a/src/test/run-pass/never-result.rs +++ b/src/test/run-pass/never-result.rs @@ -10,8 +10,6 @@ // Test that we can extract a ! through pattern matching then use it as several different types. -#![feature(never_type)] - fn main() { let x: Result = Ok(123); match x { diff --git a/src/test/run-pass/new-box-syntax.rs b/src/test/run-pass/new-box-syntax.rs index 34687c6ca1de..6598b70b3d5c 100644 --- a/src/test/run-pass/new-box-syntax.rs +++ b/src/test/run-pass/new-box-syntax.rs @@ -14,16 +14,11 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ #![allow(dead_code, unused_variables)] -#![feature(box_syntax, box_heap)] -#![feature(placement_in_syntax)] - -// during check-pretty, the expanded code needs to opt into these -// features -#![feature(placement_new_protocol, core_intrinsics)] +#![feature(box_syntax)] // Tests that the new `box` syntax works with unique pointers. -use std::boxed::{Box, HEAP}; +use std::boxed::Box; struct Structure { x: isize, @@ -31,7 +26,6 @@ struct Structure { } pub fn main() { - let x: Box = in HEAP { 2 }; let y: Box = box 2; let b: Box = box (1 + 2); let c = box (3 + 4); diff --git a/src/test/run-pass/next-power-of-two-overflow-debug.rs b/src/test/run-pass/next-power-of-two-overflow-debug.rs index 2782f8c2a598..2135b3f8764c 100644 --- a/src/test/run-pass/next-power-of-two-overflow-debug.rs +++ b/src/test/run-pass/next-power-of-two-overflow-debug.rs @@ -10,8 +10,7 @@ // compile-flags: -C debug_assertions=yes // ignore-wasm32-bare compiled with panic=abort by default - -#![feature(i128_type)] +// ignore-emscripten dies with an LLVM error use std::panic; diff --git a/src/test/run-pass/next-power-of-two-overflow-ndebug.rs b/src/test/run-pass/next-power-of-two-overflow-ndebug.rs index f8bcb961c683..b05c1863d902 100644 --- a/src/test/run-pass/next-power-of-two-overflow-ndebug.rs +++ b/src/test/run-pass/next-power-of-two-overflow-ndebug.rs @@ -9,8 +9,7 @@ // except according to those terms. // compile-flags: -C debug_assertions=no - -#![feature(i128_type)] +// ignore-emscripten dies with an LLVM error fn main() { for i in 129..256 { diff --git a/src/test/run-pass/nll/rc-loop.rs b/src/test/run-pass/nll/rc-loop.rs index 2b746fac4d42..2114dbebe93f 100644 --- a/src/test/run-pass/nll/rc-loop.rs +++ b/src/test/run-pass/nll/rc-loop.rs @@ -14,7 +14,6 @@ // `x`. The lexical checker makes this very painful. The NLL checker // does not. -#![feature(match_default_bindings)] #![feature(nll)] use std::rc::Rc; diff --git a/src/test/run-pass/packed-struct-borrow-element.rs b/src/test/run-pass/packed-struct-borrow-element.rs index 3041c73afba8..e725b25efee5 100644 --- a/src/test/run-pass/packed-struct-borrow-element.rs +++ b/src/test/run-pass/packed-struct-borrow-element.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten weird assertion? #[repr(packed)] struct Foo { diff --git a/src/test/run-pass/placement-in-syntax.rs b/src/test/run-pass/placement-in-syntax.rs deleted file mode 100644 index 7bda9ae25243..000000000000 --- a/src/test/run-pass/placement-in-syntax.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(dead_code, unused_variables)] -#![feature(box_heap)] -#![feature(placement_in_syntax)] - -// Tests that the new `in` syntax works with unique pointers. -// -// Compare with new-box-syntax.rs - -use std::boxed::{Box, HEAP}; - -struct Structure { - x: isize, - y: isize, -} - -pub fn main() { - let x: Box = in HEAP { 2 }; - let b: Box = in HEAP { 1 + 2 }; - let c = in HEAP { 3 + 4 }; - - let s: Box = in HEAP { - Structure { - x: 3, - y: 4, - } - }; -} diff --git a/src/test/run-pass/process-spawn-nonexistent.rs b/src/test/run-pass/process-spawn-nonexistent.rs new file mode 100644 index 000000000000..9219cd625f30 --- /dev/null +++ b/src/test/run-pass/process-spawn-nonexistent.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-cloudabi no processes +// ignore-emscripten no processes + +use std::io::ErrorKind; +use std::process::Command; + +fn main() { + assert_eq!(Command::new("nonexistent") + .spawn() + .unwrap_err() + .kind(), + ErrorKind::NotFound); +} diff --git a/src/test/run-pass/range-inclusive-pattern-precedence.rs b/src/test/run-pass/range-inclusive-pattern-precedence.rs new file mode 100644 index 000000000000..5e491d48bcf4 --- /dev/null +++ b/src/test/run-pass/range-inclusive-pattern-precedence.rs @@ -0,0 +1,32 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_patterns, pattern_parentheses)] + +const VALUE: usize = 21; + +pub fn main() { + match &18 { + &(18..=18) => {} + _ => { unreachable!(); } + } + match &21 { + &(VALUE..=VALUE) => {} + _ => { unreachable!(); } + } + match Box::new(18) { + box (18..=18) => {} + _ => { unreachable!(); } + } + match Box::new(21) { + box (VALUE..=VALUE) => {} + _ => { unreachable!(); } + } +} diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs index 71e11804052d..5d46bfab8878 100644 --- a/src/test/run-pass/range_inclusive.rs +++ b/src/test/run-pass/range_inclusive.rs @@ -10,7 +10,7 @@ // Test inclusive range syntax. -#![feature(inclusive_range_syntax, inclusive_range, iterator_step_by)] +#![feature(iterator_step_by)] use std::ops::{RangeInclusive, RangeToInclusive}; diff --git a/src/test/run-pass/range_inclusive_gate.rs b/src/test/run-pass/range_inclusive_gate.rs index 570087aedbba..6c2731fa5a9b 100644 --- a/src/test/run-pass/range_inclusive_gate.rs +++ b/src/test/run-pass/range_inclusive_gate.rs @@ -9,8 +9,7 @@ // except according to those terms. // Test that you only need the syntax gate if you don't mention the structs. - -#![feature(inclusive_range_syntax)] +// (Obsoleted since both features are stabilized) fn main() { let mut count = 0; diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs index 5e534da01287..046d27a9f0fe 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs @@ -8,6 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - fn main() {} diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs index 80fa4d17b611..4aa7d8c3a77d 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] #![feature(process_exitcode_placeholder)] use std::process::ExitCode; diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs index 269ac451cf4d..33686ed0b8fa 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - use std::io::Error; fn main() -> Result<(), Box> { diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs index 751db0fb5008..1c87e31e763e 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] - use std::io::Error; fn main() -> Result<(), Error> { diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs index 494500d522ab..11997eb69172 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -10,7 +10,7 @@ // compile-flags: --test -#![feature(termination_trait)] +#![feature(termination_trait_test)] #![feature(test)] extern crate test; diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/box.rs b/src/test/run-pass/rfc-2005-default-binding-mode/box.rs index 85453f32208c..95bce1935e52 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/box.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/box.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(box_syntax, box_patterns)] -#![feature(match_default_bindings)] struct Foo{} diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/constref.rs b/src/test/run-pass/rfc-2005-default-binding-mode/constref.rs index 1b8fdbaa4d75..af40ef2b1c5d 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/constref.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/constref.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - const CONST_REF: &[u8; 3] = b"foo"; trait Foo { diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/enum.rs b/src/test/run-pass/rfc-2005-default-binding-mode/enum.rs index a7b3db021b02..4755fc37ef34 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/enum.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/enum.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - enum Wrapper { Wrap(i32), } diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/for.rs b/src/test/run-pass/rfc-2005-default-binding-mode/for.rs index 4feab94a7edf..c2467d3f0091 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/for.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/for.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - pub fn main() { let mut tups = vec![(0u8, 1u8)]; diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/general.rs b/src/test/run-pass/rfc-2005-default-binding-mode/general.rs index 779a38bdb167..df28046d7d70 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/general.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/general.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - fn some_or_wildcard(r: &Option, b: &i32) { let _: &i32 = match r { Some(a) => a, diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/lit.rs b/src/test/run-pass/rfc-2005-default-binding-mode/lit.rs index 0b2a8e52fbf7..004ea42b65b8 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/lit.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/lit.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - fn with_u8() { let s = 5u8; let r = match &s { diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/range.rs b/src/test/run-pass/rfc-2005-default-binding-mode/range.rs index aafaa4cca82c..2292d97eaf4e 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/range.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/range.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - pub fn main() { let i = 5; match &&&&i { diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/ref-region.rs b/src/test/run-pass/rfc-2005-default-binding-mode/ref-region.rs index de7df011b56f..bc96853fd948 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/ref-region.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/ref-region.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - fn foo<'a, 'b>(x: &'a &'b Option) -> &'a u32 { let x: &'a &'a Option = x; match x { diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs b/src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs index f980ef0ccddd..1d86a2ecf869 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/reset-mode.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - // Test that we "reset" the mode as we pass through a `&` pattern. // // cc #46688 diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/slice.rs b/src/test/run-pass/rfc-2005-default-binding-mode/slice.rs index 1717d0d54c02..0d1d0893c593 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/slice.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(slice_patterns)] -#![feature(match_default_bindings)] fn slice_pat() { let sl: &[u8] = b"foo"; diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/struct.rs b/src/test/run-pass/rfc-2005-default-binding-mode/struct.rs index 11a675c0c72a..017439b3b140 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/struct.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/struct.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - #[derive(Debug, PartialEq)] struct Foo { x: u8, diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/tuple-struct.rs b/src/test/run-pass/rfc-2005-default-binding-mode/tuple-struct.rs index 7867d6529050..3b55405abdd7 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/tuple-struct.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/tuple-struct.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - enum Foo { Bar(Option, (), (), Vec), Baz, diff --git a/src/test/run-pass/rfc-2005-default-binding-mode/tuple.rs b/src/test/run-pass/rfc-2005-default-binding-mode/tuple.rs index cf27265b2ed5..966b8e1a8127 100644 --- a/src/test/run-pass/rfc-2005-default-binding-mode/tuple.rs +++ b/src/test/run-pass/rfc-2005-default-binding-mode/tuple.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - pub fn main() { let foo = (Some(1), (), (), vec![2, 3]); diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs b/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs new file mode 100644 index 000000000000..6cea75cf1d11 --- /dev/null +++ b/src/test/run-pass/rfc-2151-raw-identifiers/attr.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(raw_identifiers)] + +use std::mem; + +#[r#repr(r#C, r#packed)] +struct Test { + a: bool, b: u64 +} + +#[r#derive(r#Debug)] +struct Test2(u32); + +pub fn main() { + assert_eq!(mem::size_of::(), 9); + assert_eq!("Test2(123)", format!("{:?}", Test2(123))); +} diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs b/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs new file mode 100644 index 000000000000..5d495c4e9e55 --- /dev/null +++ b/src/test/run-pass/rfc-2151-raw-identifiers/basic.rs @@ -0,0 +1,31 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(raw_identifiers)] + +fn r#fn(r#match: u32) -> u32 { + r#match +} + +pub fn main() { + let r#struct = 1; + assert_eq!(1, r#struct); + + let foo = 2; + assert_eq!(2, r#foo); + + let r#bar = 3; + assert_eq!(3, bar); + + assert_eq!(4, r#fn(4)); + + let r#true = false; + assert_eq!(r#true, false); +} diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/items.rs b/src/test/run-pass/rfc-2151-raw-identifiers/items.rs new file mode 100644 index 000000000000..256bd263d38d --- /dev/null +++ b/src/test/run-pass/rfc-2151-raw-identifiers/items.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(raw_identifiers)] + +#[derive(Debug, PartialEq, Eq)] +struct IntWrapper(u32); + +#[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Hash, Copy, Clone, Default)] +struct HasKeywordField { + r#struct: u32, +} + +struct Generic(T); + +trait Trait { + fn r#trait(&self) -> u32; +} +impl Trait for Generic { + fn r#trait(&self) -> u32 { + self.0 + } +} + +pub fn main() { + assert_eq!(IntWrapper(1), r#IntWrapper(1)); + + match IntWrapper(2) { + r#IntWrapper(r#struct) => assert_eq!(2, r#struct), + } + + assert_eq!("HasKeywordField { struct: 3 }", format!("{:?}", HasKeywordField { r#struct: 3 })); + + assert_eq!(4, Generic(4).0); + assert_eq!(5, Generic(5).r#trait()); +} diff --git a/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs b/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs new file mode 100644 index 000000000000..4bd16ded52fb --- /dev/null +++ b/src/test/run-pass/rfc-2151-raw-identifiers/macros.rs @@ -0,0 +1,48 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(decl_macro)] +#![feature(raw_identifiers)] + +r#macro_rules! r#struct { + ($r#struct:expr) => { $r#struct } +} + +macro_rules! old_macro { + ($a:expr) => {$a} +} + +macro r#decl_macro($r#fn:expr) { + $r#fn +} + +macro passthrough($id:ident) { + $id +} + +macro_rules! test_pat_match { + (a) => { 6 }; + (r#a) => { 7 }; +} + +pub fn main() { + r#println!("{struct}", r#struct = 1); + assert_eq!(2, r#struct!(2)); + assert_eq!(3, r#old_macro!(3)); + assert_eq!(4, decl_macro!(4)); + + let r#match = 5; + assert_eq!(5, passthrough!(r#match)); + + assert_eq!("r#struct", stringify!(r#struct)); + + assert_eq!(6, test_pat_match!(a)); + assert_eq!(7, test_pat_match!(r#a)); +} diff --git a/src/test/run-pass/saturating-float-casts.rs b/src/test/run-pass/saturating-float-casts.rs index c8fa49c62a0b..ad3b4b172594 100644 --- a/src/test/run-pass/saturating-float-casts.rs +++ b/src/test/run-pass/saturating-float-casts.rs @@ -11,7 +11,7 @@ // Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction. // compile-flags: -Z saturating-float-casts -#![feature(test, i128, i128_type, stmt_expr_attributes)] +#![feature(test, stmt_expr_attributes)] #![deny(overflowing_literals)] extern crate test; diff --git a/src/test/run-pass/simd-intrinsic-generic-arithmetic.rs b/src/test/run-pass/simd-intrinsic-generic-arithmetic.rs index 1894cd0084bc..ac6d0c697ecc 100644 --- a/src/test/run-pass/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/run-pass/simd-intrinsic-generic-arithmetic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten FIXME(#45351) hits an LLVM assert + #![feature(repr_simd, platform_intrinsics)] #[repr(simd)] diff --git a/src/test/run-pass/simd-intrinsic-generic-comparison.rs b/src/test/run-pass/simd-intrinsic-generic-comparison.rs index 5802fb30bd68..d27378ba8930 100644 --- a/src/test/run-pass/simd-intrinsic-generic-comparison.rs +++ b/src/test/run-pass/simd-intrinsic-generic-comparison.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten FIXME(#45351) hits an LLVM assert + #![feature(repr_simd, platform_intrinsics, concat_idents)] #![allow(non_camel_case_types)] diff --git a/src/test/run-pass/simd-intrinsic-generic-elements.rs b/src/test/run-pass/simd-intrinsic-generic-elements.rs index f0444c271705..72fcef27a665 100644 --- a/src/test/run-pass/simd-intrinsic-generic-elements.rs +++ b/src/test/run-pass/simd-intrinsic-generic-elements.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-emscripten FIXME(#45351) hits an LLVM assert + #![feature(repr_simd, platform_intrinsics)] #[repr(simd)] diff --git a/src/test/run-pass/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd-intrinsic-generic-reduction.rs new file mode 100644 index 000000000000..9a1214d3b35e --- /dev/null +++ b/src/test/run-pass/simd-intrinsic-generic-reduction.rs @@ -0,0 +1,172 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// min-llvm-version 5.0 +// ignore-emscripten + +// Test that the simd_reduce_{op} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct b8x16( + pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8 +); + +extern "platform-intrinsic" { + fn simd_reduce_add_unordered(x: T) -> U; + fn simd_reduce_mul_unordered(x: T) -> U; + fn simd_reduce_add_ordered(x: T, acc: U) -> U; + fn simd_reduce_mul_ordered(x: T, acc: U) -> U; + fn simd_reduce_min(x: T) -> U; + fn simd_reduce_max(x: T) -> U; + fn simd_reduce_min_nanless(x: T) -> U; + fn simd_reduce_max_nanless(x: T) -> U; + fn simd_reduce_and(x: T) -> U; + fn simd_reduce_or(x: T) -> U; + fn simd_reduce_xor(x: T) -> U; + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +fn main() { + unsafe { + let x = i32x4(1, -2, 3, 4); + let r: i32 = simd_reduce_add_unordered(x); + assert_eq!(r, 6_i32); + let r: i32 = simd_reduce_mul_unordered(x); + assert_eq!(r, -24_i32); + let r: i32 = simd_reduce_add_ordered(x, -1); + assert_eq!(r, 5_i32); + let r: i32 = simd_reduce_mul_ordered(x, -1); + assert_eq!(r, 24_i32); + + let r: i32 = simd_reduce_min(x); + assert_eq!(r, -2_i32); + let r: i32 = simd_reduce_max(x); + assert_eq!(r, 4_i32); + + let x = i32x4(-1, -1, -1, -1); + let r: i32 = simd_reduce_and(x); + assert_eq!(r, -1_i32); + let r: i32 = simd_reduce_or(x); + assert_eq!(r, -1_i32); + let r: i32 = simd_reduce_xor(x); + assert_eq!(r, 0_i32); + + let x = i32x4(-1, -1, 0, -1); + let r: i32 = simd_reduce_and(x); + assert_eq!(r, 0_i32); + let r: i32 = simd_reduce_or(x); + assert_eq!(r, -1_i32); + let r: i32 = simd_reduce_xor(x); + assert_eq!(r, -1_i32); + } + + unsafe { + let x = u32x4(1, 2, 3, 4); + let r: u32 = simd_reduce_add_unordered(x); + assert_eq!(r, 10_u32); + let r: u32 = simd_reduce_mul_unordered(x); + assert_eq!(r, 24_u32); + let r: u32 = simd_reduce_add_ordered(x, 1); + assert_eq!(r, 11_u32); + let r: u32 = simd_reduce_mul_ordered(x, 2); + assert_eq!(r, 48_u32); + + let r: u32 = simd_reduce_min(x); + assert_eq!(r, 1_u32); + let r: u32 = simd_reduce_max(x); + assert_eq!(r, 4_u32); + + let t = u32::max_value(); + let x = u32x4(t, t, t, t); + let r: u32 = simd_reduce_and(x); + assert_eq!(r, t); + let r: u32 = simd_reduce_or(x); + assert_eq!(r, t); + let r: u32 = simd_reduce_xor(x); + assert_eq!(r, 0_u32); + + let x = u32x4(t, t, 0, t); + let r: u32 = simd_reduce_and(x); + assert_eq!(r, 0_u32); + let r: u32 = simd_reduce_or(x); + assert_eq!(r, t); + let r: u32 = simd_reduce_xor(x); + assert_eq!(r, t); + } + + unsafe { + let x = f32x4(1., -2., 3., 4.); + let r: f32 = simd_reduce_add_unordered(x); + assert_eq!(r, 6_f32); + let r: f32 = simd_reduce_mul_unordered(x); + assert_eq!(r, -24_f32); + // FIXME: only works correctly for accumulator, 0: + // https://bugs.llvm.org/show_bug.cgi?id=36734 + let r: f32 = simd_reduce_add_ordered(x, 0.); + assert_eq!(r, 6_f32); + // FIXME: only works correctly for accumulator, 1: + // https://bugs.llvm.org/show_bug.cgi?id=36734 + let r: f32 = simd_reduce_mul_ordered(x, 1.); + assert_eq!(r, -24_f32); + + let r: f32 = simd_reduce_min(x); + assert_eq!(r, -2_f32); + let r: f32 = simd_reduce_max(x); + assert_eq!(r, 4_f32); + let r: f32 = simd_reduce_min_nanless(x); + assert_eq!(r, -2_f32); + let r: f32 = simd_reduce_max_nanless(x); + assert_eq!(r, 4_f32); + } + + unsafe { + let x = b8x4(!0, !0, !0, !0); + let r: bool = simd_reduce_all(x); + assert_eq!(r, true); + let r: bool = simd_reduce_any(x); + assert_eq!(r, true); + + let x = b8x4(!0, !0, 0, !0); + let r: bool = simd_reduce_all(x); + assert_eq!(r, false); + let r: bool = simd_reduce_any(x); + assert_eq!(r, true); + + let x = b8x4(0, 0, 0, 0); + let r: bool = simd_reduce_all(x); + assert_eq!(r, false); + let r: bool = simd_reduce_any(x); + assert_eq!(r, false); + } +} diff --git a/src/test/run-pass/simd-intrinsic-generic-select.rs b/src/test/run-pass/simd-intrinsic-generic-select.rs new file mode 100644 index 000000000000..8e94d797e894 --- /dev/null +++ b/src/test/run-pass/simd-intrinsic-generic-select.rs @@ -0,0 +1,146 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-emscripten + +// Test that the simd_select intrinsics produces correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +extern "platform-intrinsic" { + fn simd_select(x: T, a: U, b: U) -> U; +} + +fn main() { + let m0 = b8x4(!0, !0, !0, !0); + let m1 = b8x4(0, 0, 0, 0); + let m2 = b8x4(!0, !0, 0, 0); + let m3 = b8x4(0, 0, !0, !0); + let m4 = b8x4(!0, 0, !0, 0); + + unsafe { + let a = i32x4(1, -2, 3, 4); + let b = i32x4(5, 6, -7, 8); + + let r: i32x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: i32x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: i32x4 = simd_select(m2, a, b); + let e = i32x4(1, -2, -7, 8); + assert_eq!(r, e); + + let r: i32x4 = simd_select(m3, a, b); + let e = i32x4(5, 6, 3, 4); + assert_eq!(r, e); + + let r: i32x4 = simd_select(m4, a, b); + let e = i32x4(1, 6, 3, 8); + assert_eq!(r, e); + } + + unsafe { + let a = u32x4(1, 2, 3, 4); + let b = u32x4(5, 6, 7, 8); + + let r: u32x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: u32x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: u32x4 = simd_select(m2, a, b); + let e = u32x4(1, 2, 7, 8); + assert_eq!(r, e); + + let r: u32x4 = simd_select(m3, a, b); + let e = u32x4(5, 6, 3, 4); + assert_eq!(r, e); + + let r: u32x4 = simd_select(m4, a, b); + let e = u32x4(1, 6, 3, 8); + assert_eq!(r, e); + } + + unsafe { + let a = f32x4(1., 2., 3., 4.); + let b = f32x4(5., 6., 7., 8.); + + let r: f32x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: f32x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: f32x4 = simd_select(m2, a, b); + let e = f32x4(1., 2., 7., 8.); + assert_eq!(r, e); + + let r: f32x4 = simd_select(m3, a, b); + let e = f32x4(5., 6., 3., 4.); + assert_eq!(r, e); + + let r: f32x4 = simd_select(m4, a, b); + let e = f32x4(1., 6., 3., 8.); + assert_eq!(r, e); + } + + unsafe { + let t = !0 as i8; + let f = 0 as i8; + let a = b8x4(t, f, t, f); + let b = b8x4(f, f, f, t); + + let r: b8x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: b8x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: b8x4 = simd_select(m2, a, b); + let e = b8x4(t, f, f, t); + assert_eq!(r, e); + + let r: b8x4 = simd_select(m3, a, b); + let e = b8x4(f, f, t, f); + assert_eq!(r, e); + + let r: b8x4 = simd_select(m4, a, b); + let e = b8x4(t, f, t, t); + assert_eq!(r, e); + } +} diff --git a/src/test/run-pass/sse2.rs b/src/test/run-pass/sse2.rs index 22469b2fde05..b1d7e5435c4c 100644 --- a/src/test/run-pass/sse2.rs +++ b/src/test/run-pass/sse2.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-system-llvm -- needs MCSubtargetInfo::getFeatureTable() +// min-llvm-version 6.0 +// ^ needs MCSubtargetInfo::checkFeatures() // ignore-cloudabi no std::env #![feature(cfg_target_feature)] @@ -29,4 +30,7 @@ fn main() { assert!(cfg!(target_feature = "sse2"), "SSE2 was not detected as available on an x86 platform"); } + // check a negative case too -- whitelisted on x86, but not enabled by default + assert!(cfg!(not(target_feature = "avx2")), + "AVX2 shouldn't be detected as available by default on any platform"); } diff --git a/src/test/run-pass/stack-probes-lto.rs b/src/test/run-pass/stack-probes-lto.rs index 4deced1297bd..d1cb75909c15 100644 --- a/src/test/run-pass/stack-probes-lto.rs +++ b/src/test/run-pass/stack-probes-lto.rs @@ -10,6 +10,10 @@ // ignore-arm // ignore-aarch64 +// ignore-mips +// ignore-mips64 +// ignore-powerpc +// ignore-s390x // ignore-wasm // ignore-cloudabi no processes // ignore-emscripten no processes diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs index 4224a65ffd7c..78c5782be383 100644 --- a/src/test/run-pass/stack-probes.rs +++ b/src/test/run-pass/stack-probes.rs @@ -10,6 +10,10 @@ // ignore-arm // ignore-aarch64 +// ignore-mips +// ignore-mips64 +// ignore-powerpc +// ignore-s390x // ignore-wasm // ignore-cloudabi no processes // ignore-emscripten no processes diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs index 903532e9bc80..e096fb3bbaef 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -18,8 +18,8 @@ use std::collections::VecDeque; use std::collections::HashMap; use std::collections::HashSet; -use std::collections::Bound::Included; use std::mem; +use std::ops::Bound::Included; fn is_sync(_: T) where T: Sync {} fn is_send(_: T) where T: Send {} diff --git a/src/test/run-pass/trailing-comma.rs b/src/test/run-pass/trailing-comma.rs index b9eda0846537..02bae5aa4551 100644 --- a/src/test/run-pass/trailing-comma.rs +++ b/src/test/run-pass/trailing-comma.rs @@ -10,7 +10,6 @@ // pretty-expanded FIXME #23616 -#![feature(advanced_slice_patterns,)] #![feature(slice_patterns)] fn f(_: T,) {} diff --git a/src/test/run-pass/u128-as-f32.rs b/src/test/run-pass/u128-as-f32.rs index 117e520155fd..2848fb2d51a6 100644 --- a/src/test/run-pass/u128-as-f32.rs +++ b/src/test/run-pass/u128-as-f32.rs @@ -10,7 +10,7 @@ // ignore-emscripten u128 not supported -#![feature(test, i128, i128_type)] +#![feature(test)] #![deny(overflowing_literals)] extern crate test; diff --git a/src/test/run-pass/u128.rs b/src/test/run-pass/u128.rs index ebd43a860338..d649b3b74d39 100644 --- a/src/test/run-pass/u128.rs +++ b/src/test/run-pass/u128.rs @@ -12,7 +12,7 @@ // compile-flags: -Z borrowck=compare -#![feature(i128_type, test)] +#![feature(test)] extern crate test; use test::black_box as b; diff --git a/src/test/run-pass/underscore-lifetimes.rs b/src/test/run-pass/underscore-lifetimes.rs index ed0369353bcd..4dd1a565c9f1 100644 --- a/src/test/run-pass/underscore-lifetimes.rs +++ b/src/test/run-pass/underscore-lifetimes.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(underscore_lifetimes)] - struct Foo<'a>(&'a u8); fn foo(x: &u8) -> Foo<'_> { diff --git a/src/test/run-pass/vec-matching-autoslice.rs b/src/test/run-pass/vec-matching-autoslice.rs index 9df777e7af0d..7268536a51fa 100644 --- a/src/test/run-pass/vec-matching-autoslice.rs +++ b/src/test/run-pass/vec-matching-autoslice.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(slice_patterns)] - pub fn main() { let x = [1, 2, 3]; match x { diff --git a/src/test/run-pass/vec-matching-fixed.rs b/src/test/run-pass/vec-matching-fixed.rs index 1ed6ddc41107..060d152488a9 100644 --- a/src/test/run-pass/vec-matching-fixed.rs +++ b/src/test/run-pass/vec-matching-fixed.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] fn a() { diff --git a/src/test/run-pass/vec-matching-fold.rs b/src/test/run-pass/vec-matching-fold.rs index ac80a4211ada..1a30f875580c 100644 --- a/src/test/run-pass/vec-matching-fold.rs +++ b/src/test/run-pass/vec-matching-fold.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] use std::fmt::Debug; diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index bd0731a555cb..ace418f21606 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] fn a() { diff --git a/src/test/run-pass/vec-tail-matching.rs b/src/test/run-pass/vec-tail-matching.rs index d123eb36a7d4..4f31405ead50 100644 --- a/src/test/run-pass/vec-tail-matching.rs +++ b/src/test/run-pass/vec-tail-matching.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - #![feature(slice_patterns)] struct Foo { diff --git a/src/test/rustdoc/auxiliary/extern-impl-trait.rs b/src/test/rustdoc/auxiliary/extern-impl-trait.rs new file mode 100644 index 000000000000..ba6c3e956953 --- /dev/null +++ b/src/test/rustdoc/auxiliary/extern-impl-trait.rs @@ -0,0 +1,37 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Foo { + type Associated; +} + +pub struct X; +pub struct Y; + + +impl Foo for X { + type Associated = (); +} + +impl Foo for Y { + type Associated = (); +} + +impl X { + pub fn returns_sized<'a>(&'a self) -> impl Foo + 'a { + X + } +} + +impl Y { + pub fn returns_unsized<'a>(&'a self) -> Box + 'a> { + Box::new(X) + } +} diff --git a/src/test/rustdoc/check-styled-link.rs b/src/test/rustdoc/check-styled-link.rs new file mode 100644 index 000000000000..1633711e83d9 --- /dev/null +++ b/src/test/rustdoc/check-styled-link.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +pub struct Foo; + +// @has foo/struct.Bar.html '//a[@href="../foo/struct.Foo.html"]' 'Foo' + +/// Code-styled reference to [`Foo`]. +pub struct Bar; diff --git a/src/test/rustdoc/default-trait-method-link.rs b/src/test/rustdoc/default-trait-method-link.rs new file mode 100644 index 000000000000..9cde446eb941 --- /dev/null +++ b/src/test/rustdoc/default-trait-method-link.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/trait.Foo.html '//a[@href="../foo/trait.Foo.html#tymethod.req"]' 'req' +// @has foo/trait.Foo.html '//a[@href="../foo/trait.Foo.html#method.prov"]' 'prov' + +/// Always make sure to implement [`req`], but you don't have to implement [`prov`]. +/// +/// [`req`]: Foo::req +/// [`prov`]: Foo::prov +pub trait Foo { + /// Required + fn req(); + /// Provided + fn prov() {} +} diff --git a/src/test/rustdoc/deprecated-future.rs b/src/test/rustdoc/deprecated-future.rs new file mode 100644 index 000000000000..6feb98dad09c --- /dev/null +++ b/src/test/rustdoc/deprecated-future.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(deprecated)] + +// @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \ +// 'Deprecating in 99.99.99: effectively never' +#[deprecated(since = "99.99.99", note = "effectively never")] +pub struct S; diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs index 8499e5c741ee..ea8a13b034be 100644 --- a/src/test/rustdoc/doc-cfg.rs +++ b/src/test/rustdoc/doc-cfg.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(doc_cfg)] +#![feature(target_feature, cfg_target_feature)] // @has doc_cfg/struct.Portable.html // @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' '' @@ -45,3 +46,26 @@ pub mod unix_only { fn unix_and_arm_only_function() {} } } + +// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that +// item as well + +// the portability header is different on the module view versus the full view +// @has doc_cfg/index.html +// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z' + +// @has doc_cfg/fn.uses_target_feature.html +// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \ +// 'This is supported with target feature avx only.' +#[target_feature(enable = "avx")] +pub unsafe fn uses_target_feature() { + content::should::be::irrelevant(); +} + +// @has doc_cfg/fn.uses_cfg_target_feature.html +// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \ +// 'This is supported with target feature avx only.' +#[doc(cfg(target_feature = "avx"))] +pub fn uses_cfg_target_feature() { + uses_target_feature(); +} diff --git a/src/test/ui/feature-gate-clone-closures.rs b/src/test/rustdoc/empty-section.rs similarity index 67% rename from src/test/ui/feature-gate-clone-closures.rs rename to src/test/rustdoc/empty-section.rs index a15153ea7bf0..3748313593fc 100644 --- a/src/test/ui/feature-gate-clone-closures.rs +++ b/src/test/rustdoc/empty-section.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Clone)] -struct S(i32); +#![crate_name = "foo"] -fn main() { - let a = S(5); - let hello = move || { - println!("Hello {}", a.0); - }; +#![feature(optin_builtin_traits)] - let hello = hello.clone(); //~ ERROR no method named `clone` found for type -} +pub struct Foo; + +// @has foo/struct.Foo.html +// @!has - '//*[@class="synthetic-implementations"]' 'Auto Trait Implementations' +impl !Send for Foo {} +impl !Sync for Foo {} diff --git a/src/test/rustdoc/extern-impl-trait.rs b/src/test/rustdoc/extern-impl-trait.rs new file mode 100644 index 000000000000..02a8e962fe17 --- /dev/null +++ b/src/test/rustdoc/extern-impl-trait.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:extern-impl-trait.rs + +#![crate_name = "foo"] + +extern crate extern_impl_trait; + +// @has 'foo/struct.X.html' '//code' "impl Foo + 'a" +pub use extern_impl_trait::X; + +// @has 'foo/struct.Y.html' '//code' "impl ?Sized + Foo + 'a" +pub use extern_impl_trait::Y; diff --git a/src/test/rustdoc/issue-32556.rs b/src/test/rustdoc/issue-32556.rs new file mode 100644 index 000000000000..3ab138079a1f --- /dev/null +++ b/src/test/rustdoc/issue-32556.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// Blah blah blah +/// ```ignore (testing rustdoc's handling of ignore) +/// bad_assert!(); +/// ``` +pub fn foo() {} diff --git a/src/test/rustdoc/issue-43869.rs b/src/test/rustdoc/issue-43869.rs index 554c71500cc8..a5ed3d892ce9 100644 --- a/src/test/rustdoc/issue-43869.rs +++ b/src/test/rustdoc/issue-43869.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - pub fn g() -> impl Iterator { Some(1u8).into_iter() } diff --git a/src/test/rustdoc/issue-46976.rs b/src/test/rustdoc/issue-46976.rs index 0df80fe3bd77..ce09f62a552d 100644 --- a/src/test/rustdoc/issue-46976.rs +++ b/src/test/rustdoc/issue-46976.rs @@ -8,5 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] pub fn ice(f: impl Fn()) {} diff --git a/src/test/rustdoc/link-assoc-const.rs b/src/test/rustdoc/link-assoc-const.rs new file mode 100644 index 000000000000..aa7ef07d5c0c --- /dev/null +++ b/src/test/rustdoc/link-assoc-const.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/index.html '//a[@href="../foo/foo/constant.FIRSTCONST.html"]' 'foo::FIRSTCONST' +// @has foo/index.html '//a[@href="../foo/struct.Bar.html#associatedconstant.CONST"]' 'Bar::CONST' + +//! We have here [`foo::FIRSTCONST`] and [`Bar::CONST`]. + +pub mod foo { + pub const FIRSTCONST: u32 = 42; +} + +pub struct Bar; + +impl Bar { + pub const CONST: u32 = 42; +} diff --git a/src/test/rustdoc/primitive-link.rs b/src/test/rustdoc/primitive-link.rs new file mode 100644 index 000000000000..b0cf8acc7c02 --- /dev/null +++ b/src/test/rustdoc/primitive-link.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// ignore-tidy-linelength + +// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32' +// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64' + +/// It contains [`u32`] and [i64]. +pub struct Foo; diff --git a/src/test/rustdoc/struct-field.rs b/src/test/rustdoc/struct-field.rs new file mode 100644 index 000000000000..c5016bac7d39 --- /dev/null +++ b/src/test/rustdoc/struct-field.rs @@ -0,0 +1,33 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// ignore-tidy-linelength + +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/struct.Foo.html#structfield.bar"]' 'Foo::bar' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/union.Bar.html#structfield.foo"]' 'Bar::foo' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/enum.Uniooon.html#X.v"]' 'Uniooon::X' + +//! Test with [Foo::bar], [Bar::foo], [Uniooon::X] + +pub struct Foo { + pub bar: usize, +} + +pub union Bar { + pub foo: u32, +} + +pub enum Uniooon { + F, + X, + Y, +} diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index 531798c30c65..a4ebf6d3a7e8 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -30,7 +30,7 @@ mod foo { } // @has complex/struct.NotOuter.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'a, T, K: \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'a, T, K: \ // ?Sized> Send for NotOuter<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index 272925e5db54..1c1e7bc25052 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -18,10 +18,10 @@ where {} // @has lifetimes/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Send \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \ // for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Sync \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \ // for Foo<'c, K> where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index d81e6309dff6..ef6797ecf3c5 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -9,10 +9,10 @@ // except according to those terms. // @has manual/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' 'impl Sync for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl Sync for \ // Foo where T: Sync' // -// @has - '//*[@id="implementations-list"]/*[@class="impl"]/*/code' \ +// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' \ // 'impl Send for Foo' // // @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1 diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs index ec9cb710f1f8..64480d28240b 100644 --- a/src/test/rustdoc/synthetic_auto/negative.rs +++ b/src/test/rustdoc/synthetic_auto/negative.rs @@ -13,10 +13,10 @@ pub struct Inner { } // @has negative/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl !Send for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl !Send for \ // Outer" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl \ // !Sync for Outer" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index 1f33a8b13cbf..ccdbe159b6c5 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -18,10 +18,10 @@ where } // @has nested/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' 'impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl Send for \ // Foo where T: Copy' // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' \ // 'impl Sync for Foo where T: Sync' pub struct Foo { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 0b37f2ed3179..24fba221b993 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -19,7 +19,7 @@ where } // @has no_redundancy/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl Send for \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl Send for \ // Outer where T: Copy + Send" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index 977607fb1482..d588190c4f9d 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -33,10 +33,10 @@ where } // @has project/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Send \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \ // for Foo<'c, K> where K: MyTrait, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Sync \ +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \ // for Foo<'c, K> where K: MyTrait, ::MyItem: OtherTrait, 'c: 'static," pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/universal-impl-trait.rs b/src/test/rustdoc/universal-impl-trait.rs new file mode 100644 index 000000000000..4cf99562c529 --- /dev/null +++ b/src/test/rustdoc/universal-impl-trait.rs @@ -0,0 +1,46 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(universal_impl_trait)] +#![crate_name = "foo"] + +// @has foo/fn.foo.html +// @has - //pre 'foo(' +// @matches - '_x: impl (' + // @matches - '_x: impl (T); + +impl S { + // @has foo/struct.S.html + // @has - 'bar(' + // @matches - '_bar: impl (' + // @matches - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html' + pub fn baz(_baz: S) { + } +} + +// @has - 'method(' +// @matches - '_x: impl Trait for S {} diff --git a/src/test/ui-fulldeps/custom-derive/issue-36935.stderr b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr index b082999a8978..027825699412 100644 --- a/src/test/ui-fulldeps/custom-derive/issue-36935.stderr +++ b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr @@ -6,3 +6,5 @@ LL | #[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked | = help: message: lolnope +error: aborting due to previous error + diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr index ac26b5212ecb..c03ee7f983f5 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr +++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr @@ -21,4 +21,4 @@ LL | #[allow(test_lint)] error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0453" +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui-fulldeps/proc-macro/load-panic.stderr b/src/test/ui-fulldeps/proc-macro/load-panic.stderr index edfd134469cd..30ad53f9041f 100644 --- a/src/test/ui-fulldeps/proc-macro/load-panic.stderr +++ b/src/test/ui-fulldeps/proc-macro/load-panic.stderr @@ -6,3 +6,5 @@ LL | #[derive(A)] | = help: message: nope! +error: aborting due to previous error + diff --git a/src/test/ui-fulldeps/proc-macro/signature.stderr b/src/test/ui-fulldeps/proc-macro/signature.stderr index dad403ccf3a6..fdd10c3c5b90 100644 --- a/src/test/ui-fulldeps/proc-macro/signature.stderr +++ b/src/test/ui-fulldeps/proc-macro/signature.stderr @@ -12,4 +12,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index ff31595ee9ba..82f527f8cca8 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -154,4 +154,4 @@ LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &() error: aborting due to 11 previous errors -If you want more information on this error, try using "rustc --explain E0631" +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/arbitrary-self-types-not-object-safe.stderr index ba240c8d5115..b3f9cbc587ba 100644 --- a/src/test/ui/arbitrary-self-types-not-object-safe.stderr +++ b/src/test/ui/arbitrary-self-types-not-object-safe.stderr @@ -17,4 +17,4 @@ LL | let x = Box::new(5usize) as Box; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/asm-out-assign-imm.stderr b/src/test/ui/asm-out-assign-imm.stderr index 16df627578e9..4ec758b97f2d 100644 --- a/src/test/ui/asm-out-assign-imm.stderr +++ b/src/test/ui/asm-out-assign-imm.stderr @@ -9,4 +9,4 @@ LL | asm!("mov $1, $0" : "=r"(x) : "r"(5)); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0384" +For more information about this error, try `rustc --explain E0384`. diff --git a/src/test/ui/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-const-impl-wrong-lifetime.stderr index e0a9653423fb..d800f4c727d7 100644 --- a/src/test/ui/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-const-impl-wrong-lifetime.stderr @@ -15,4 +15,4 @@ LL | impl<'a> Foo for &'a () { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-const-impl-wrong-type.stderr b/src/test/ui/associated-const-impl-wrong-type.stderr index 6c2f2600acc3..cfccacaee282 100644 --- a/src/test/ui/associated-const-impl-wrong-type.stderr +++ b/src/test/ui/associated-const-impl-wrong-type.stderr @@ -9,4 +9,4 @@ LL | const BAR: i32 = -1; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0326" +For more information about this error, try `rustc --explain E0326`. diff --git a/src/test/ui/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-type-projection-from-multiple-supertraits.stderr index 3b732ed39331..7a10b6d021f5 100644 --- a/src/test/ui/associated-type-projection-from-multiple-supertraits.stderr +++ b/src/test/ui/associated-type-projection-from-multiple-supertraits.stderr @@ -42,5 +42,5 @@ LL | fn paint(c: C, d: C::Color) { error: aborting due to 4 previous errors -You've got a few errors: E0191, E0221 -If you want more information on an error, try using "rustc --explain E0191" +Some errors occurred: E0191, E0221. +For more information about an error, try `rustc --explain E0191`. diff --git a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs index 75b60aa8d10b..052575de4c26 100644 --- a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs @@ -31,5 +31,5 @@ trait Add { fn ice(a: A) { let r = loop {}; r = r + a; - //~^ ERROR the trait bound `(): Add` is not satisfied + //~^ ERROR the trait bound `!: Add` is not satisfied } diff --git a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr index f69b0af71f62..c22a645385ad 100644 --- a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr +++ b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr @@ -1,9 +1,9 @@ -error[E0277]: the trait bound `(): Add` is not satisfied +error[E0277]: the trait bound `!: Add` is not satisfied --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:33:11 | LL | r = r + a; - | ^ the trait `Add` is not implemented for `()` + | ^ the trait `Add` is not implemented for `!` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types-in-ambiguous-context.stderr b/src/test/ui/associated-types-in-ambiguous-context.stderr index ff5c45e797e5..c45873ffd530 100644 --- a/src/test/ui/associated-types-in-ambiguous-context.stderr +++ b/src/test/ui/associated-types-in-ambiguous-context.stderr @@ -24,4 +24,4 @@ LL | fn grab(&self) -> Grab::Value; error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0223" +For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/attr-usage-repr.stderr b/src/test/ui/attr-usage-repr.stderr index 03c6f599b6c7..1f3b358545bd 100644 --- a/src/test/ui/attr-usage-repr.stderr +++ b/src/test/ui/attr-usage-repr.stderr @@ -40,4 +40,4 @@ LL | enum ESimd { A, B } error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0517" +For more information about this error, try `rustc --explain E0517`. diff --git a/src/test/ui/augmented-assignments.stderr b/src/test/ui/augmented-assignments.stderr index e04dc2f72a30..953af813c382 100644 --- a/src/test/ui/augmented-assignments.stderr +++ b/src/test/ui/augmented-assignments.stderr @@ -20,5 +20,5 @@ LL | x; //~ value moved here error: aborting due to 2 previous errors -You've got a few errors: E0382, E0596 -If you want more information on an error, try using "rustc --explain E0382" +Some errors occurred: E0382, E0596. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/feature-gate-advanced-slice-features.rs b/src/test/ui/auxiliary/inference_unstable_iterator.rs similarity index 50% rename from src/test/ui/feature-gate-advanced-slice-features.rs rename to src/test/ui/auxiliary/inference_unstable_iterator.rs index dc9b4e634ab7..b73346e6332c 100644 --- a/src/test/ui/feature-gate-advanced-slice-features.rs +++ b/src/test/ui/auxiliary/inference_unstable_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-advanced_slice_patterns +#![feature(staged_api)] -#![feature(slice_patterns)] +#![stable(feature = "ipu_iterator", since = "1.0.0")] -fn main() { - let x = [ 1, 2, 3, 4, 5 ]; - match x { - [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches - [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches - [ 1, 2, xs.. ] => {} // OK without feature gate +#[stable(feature = "ipu_iterator", since = "1.0.0")] +pub trait IpuIterator { + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_flatten(&self) -> u32 { + 0 } } + +#[stable(feature = "ipu_iterator", since = "1.0.0")] +impl IpuIterator for char {} diff --git a/src/test/ui/auxiliary/inference_unstable_itertools.rs b/src/test/ui/auxiliary/inference_unstable_itertools.rs new file mode 100644 index 000000000000..2ad264ee3d82 --- /dev/null +++ b/src/test/ui/auxiliary/inference_unstable_itertools.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait IpuItertools { + fn ipu_flatten(&self) -> u32 { + 1 + } +} + +impl IpuItertools for char {} diff --git a/src/test/ui/binary-op-on-double-ref.stderr b/src/test/ui/binary-op-on-double-ref.stderr index b6c502b90b58..07aa3bfe40de 100644 --- a/src/test/ui/binary-op-on-double-ref.stderr +++ b/src/test/ui/binary-op-on-double-ref.stderr @@ -9,4 +9,4 @@ LL | x % 2 == 0 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/blind-item-item-shadow.stderr b/src/test/ui/blind-item-item-shadow.stderr index f02dd6b3e98f..240ea6061b97 100644 --- a/src/test/ui/blind-item-item-shadow.stderr +++ b/src/test/ui/blind-item-item-shadow.stderr @@ -15,4 +15,4 @@ LL | use foo::foo as other_foo; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0255" +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr index 242906ca5cb4..d864d767957d 100644 --- a/src/test/ui/block-result/block-must-not-have-result-do.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr @@ -9,4 +9,4 @@ LL | true //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr index ca730927c880..005a3ab9b5df 100644 --- a/src/test/ui/block-result/block-must-not-have-result-res.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -11,4 +11,4 @@ LL | true //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr index 1a4852a4541a..a003ae871cad 100644 --- a/src/test/ui/block-result/block-must-not-have-result-while.stderr +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -9,4 +9,4 @@ LL | true //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 6fa892e10e75..a0855c317379 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -28,4 +28,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index 8fad1c4de4a1..e9cd72812347 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -15,4 +15,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 7f39f53d6f99..888ee5a2d19a 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -31,4 +31,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 0df7cf43c351..e54e22522f25 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -20,4 +20,4 @@ LL | a::Enum::EnumStructVariant { x, y, z } => { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 238edb765ac1..990fb404c946 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -17,5 +17,5 @@ LL | let x = foo(5)(2); error: aborting due to 2 previous errors -You've got a few errors: E0308, E0618 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0618. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 03d9d03371ee..c94dd7086266 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -22,5 +22,5 @@ LL | b + 3 //~ ERROR E0277 error: aborting due to 2 previous errors -You've got a few errors: E0277, E0308 -If you want more information on an error, try using "rustc --explain E0277" +Some errors occurred: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index af0e25ab18a9..c4dee857574b 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -8,4 +8,4 @@ LL | || self.b() error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index 74379809de0d..27018b5da7bd 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -11,4 +11,4 @@ LL | &panic!() error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr index 10a8814a7e54..585cfb3d0d35 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.stderr +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -17,4 +17,4 @@ LL | fn bar() -> usize { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr index 76284f3b71b6..f9917b07f070 100644 --- a/src/test/ui/bogus-tag.stderr +++ b/src/test/ui/bogus-tag.stderr @@ -9,4 +9,4 @@ LL | color::hsl(h, s, l) => { println!("hsl"); } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.stderr index 7bea41b2209e..5bf1fc081786 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.stderr +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.stderr @@ -161,5 +161,5 @@ LL | } error: aborting due to 16 previous errors -You've got a few errors: E0382, E0502, E0503, E0505 -If you want more information on an error, try using "rustc --explain E0382" +Some errors occurred: E0382, E0502, E0503, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr index 7205b48399a2..c739165ddbd3 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr @@ -150,4 +150,4 @@ LL | } error: aborting due to 10 previous errors -If you want more information on this error, try using "rustc --explain E0499" +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr index 98176cce508a..eb1fa53d7558 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.stderr @@ -12,4 +12,4 @@ LL | spawn(move || books.push(4)); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0373" +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr index 5de31c3ac357..1343c0a1f5b7 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.stderr @@ -12,4 +12,4 @@ LL | Box::new(move || books.push(4)) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0373" +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index 989322662e86..356fad07666e 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -8,4 +8,4 @@ LL | Box::new(|| x) //~ ERROR cannot move out of captured outer variable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0507" +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr index acc78f4ab329..81ed058e47f4 100644 --- a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr @@ -34,5 +34,5 @@ LL | n => { error: aborting due to 3 previous errors -You've got a few errors: E0507, E0509 -If you want more information on an error, try using "rustc --explain E0507" +Some errors occurred: E0507, E0509. +For more information about an error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr index 49d5daa543bb..c4051e5a2556 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr @@ -15,4 +15,4 @@ LL | | Foo { string: b }] => { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0508" +For more information about this error, try `rustc --explain E0508`. diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr index a2fbe5ab9cd5..654afa421868 100644 --- a/src/test/ui/borrowck/borrowck-reinit.stderr +++ b/src/test/ui/borrowck/borrowck-reinit.stderr @@ -20,4 +20,4 @@ LL | let _ = (1,x); //~ ERROR use of moved value: `x` (Ast) error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr index 01899446f48f..648ee1dff785 100644 --- a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr +++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr @@ -36,5 +36,5 @@ LL | }; error: aborting due to 3 previous errors -You've got a few errors: E0499, E0502 -If you want more information on an error, try using "rustc --explain E0499" +Some errors occurred: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs index 07b268f1a4b0..111968e9c931 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(slice_patterns)] diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr index 3d9fbc800385..6673549e2390 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `vec[..]` because it is borrowed - --> $DIR/borrowck-vec-pattern-nesting.rs:21:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:20:13 | LL | [box ref _a, _, _] => { | ------ borrow of `vec[..]` occurs here @@ -8,7 +8,7 @@ LL | vec[0] = box 4; //~ ERROR cannot assign | ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here error[E0506]: cannot assign to `vec[..]` because it is borrowed - --> $DIR/borrowck-vec-pattern-nesting.rs:33:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:32:13 | LL | &mut [ref _b..] => { | ------ borrow of `vec[..]` occurs here @@ -17,7 +17,7 @@ LL | vec[0] = box 4; //~ ERROR cannot assign | ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:43:14 + --> $DIR/borrowck-vec-pattern-nesting.rs:42:14 | LL | &mut [_a, //~ ERROR cannot move out | ^-- hint: to prevent move, use `ref _a` or `ref mut _a` @@ -30,7 +30,7 @@ LL | | ] => { | |_________^ cannot move out of here error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:56:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:55:13 | LL | let a = vec[0]; //~ ERROR cannot move out | ^^^^^^ @@ -39,7 +39,7 @@ LL | let a = vec[0]; //~ ERROR cannot move out | help: consider using a reference instead: `&vec[0]` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:64:14 + --> $DIR/borrowck-vec-pattern-nesting.rs:63:14 | LL | &mut [ //~ ERROR cannot move out | ______________^ @@ -50,7 +50,7 @@ LL | | _b] => {} | hint: to prevent move, use `ref _b` or `ref mut _b` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:69:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:68:13 | LL | let a = vec[0]; //~ ERROR cannot move out | ^^^^^^ @@ -59,7 +59,7 @@ LL | let a = vec[0]; //~ ERROR cannot move out | help: consider using a reference instead: `&vec[0]` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:77:14 + --> $DIR/borrowck-vec-pattern-nesting.rs:76:14 | LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out | ^--^^--^^--^ @@ -70,7 +70,7 @@ LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out | cannot move out of here error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:81:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:80:13 | LL | let a = vec[0]; //~ ERROR cannot move out | ^^^^^^ @@ -80,5 +80,5 @@ LL | let a = vec[0]; //~ ERROR cannot move out error: aborting due to 8 previous errors -You've got a few errors: E0506, E0508 -If you want more information on an error, try using "rustc --explain E0506" +Some errors occurred: E0506, E0508. +For more information about an error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/immutable-arg.stderr b/src/test/ui/borrowck/immutable-arg.stderr index 34de3ca19a3c..b7506849b817 100644 --- a/src/test/ui/borrowck/immutable-arg.stderr +++ b/src/test/ui/borrowck/immutable-arg.stderr @@ -16,4 +16,4 @@ LL | _x = 4; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0384" +For more information about this error, try `rustc --explain E0384`. diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index f0ee6b31f736..39525d787b1f 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -54,4 +54,4 @@ LL | if let Some(thing) = maybe { error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.stderr index 9b777246861f..cda59d3bc68b 100644 --- a/src/test/ui/borrowck/mut-borrow-in-loop.stderr +++ b/src/test/ui/borrowck/mut-borrow-in-loop.stderr @@ -27,4 +27,4 @@ LL | } error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0499" +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr index 583f97b6cdfd..80a3ba4493c5 100644 --- a/src/test/ui/borrowck/mut-borrow-outside-loop.stderr +++ b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr @@ -21,4 +21,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0499" +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 2fe3a45b76d4..b58dbd1e4d1c 100644 --- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -46,5 +46,5 @@ LL | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { error: aborting due to 4 previous errors -You've got a few errors: E0195, E0276, E0308 -If you want more information on an error, try using "rustc --explain E0195" +Some errors occurred: E0195, E0276, E0308. +For more information about an error, try `rustc --explain E0195`. diff --git a/src/test/run-pass/issue-38972.rs b/src/test/ui/borrowck/two-phase-method-receivers.rs similarity index 61% rename from src/test/run-pass/issue-38972.rs rename to src/test/ui/borrowck/two-phase-method-receivers.rs index d5df84e0fb08..e690263a916f 100644 --- a/src/test/run-pass/issue-38972.rs +++ b/src/test/ui/borrowck/two-phase-method-receivers.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// This issue tracks a regression (a new warning) without -// feature(never_type). When we make that the default, please -// remove this test. +// revisions: lxl nll +//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows +//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll -enum Foo { } +// run-pass -fn make_foo() -> Option { None } +struct Foo<'a> { + x: &'a i32 +} -#[deny(warnings)] -fn main() { - match make_foo() { - None => {}, - Some(_) => {} +impl<'a> Foo<'a> { + fn method(&mut self, _: &i32) { } } + +fn main() { + let a = &mut Foo { x: &22 }; + Foo::method(a, a.x); +} diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index d07bdab087cb..f2f8ae8c08c2 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -9,4 +9,4 @@ LL | y.into_iter(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0507" +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/cast-as-bool.stderr b/src/test/ui/cast-as-bool.stderr index 1c60bc44d90f..050a18ec9d3e 100644 --- a/src/test/ui/cast-as-bool.stderr +++ b/src/test/ui/cast-as-bool.stderr @@ -8,4 +8,4 @@ LL | let u = 5 as bool; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0054" +For more information about this error, try `rustc --explain E0054`. diff --git a/src/test/ui/cast-errors-issue-43825.stderr b/src/test/ui/cast-errors-issue-43825.stderr index 3418472feafc..6dbbadde5c6f 100644 --- a/src/test/ui/cast-errors-issue-43825.stderr +++ b/src/test/ui/cast-errors-issue-43825.stderr @@ -6,4 +6,4 @@ LL | let error = error; //~ ERROR cannot find value `error` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/cast-rfc0401-2.stderr b/src/test/ui/cast-rfc0401-2.stderr index e0c39d84c193..f7ffa2459597 100644 --- a/src/test/ui/cast-rfc0401-2.stderr +++ b/src/test/ui/cast-rfc0401-2.stderr @@ -8,4 +8,4 @@ LL | let _ = 3 as bool; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0054" +For more information about this error, try `rustc --explain E0054`. diff --git a/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr index b2497dfeb287..67c33740f196 100644 --- a/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr @@ -16,4 +16,4 @@ LL | Box::new(1) as Send; //~ ERROR cast to unsized error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0620" +For more information about this error, try `rustc --explain E0620`. diff --git a/src/test/ui/casts-differing-anon.rs b/src/test/ui/casts-differing-anon.rs index 74c8ff370f98..05a03d3b1796 100644 --- a/src/test/ui/casts-differing-anon.rs +++ b/src/test/ui/casts-differing-anon.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - use std::fmt; fn foo() -> Box { diff --git a/src/test/ui/casts-differing-anon.stderr b/src/test/ui/casts-differing-anon.stderr index c5fbbbc0e9eb..dac24af671cf 100644 --- a/src/test/ui/casts-differing-anon.stderr +++ b/src/test/ui/casts-differing-anon.stderr @@ -1,5 +1,5 @@ error[E0606]: casting `*mut impl std::fmt::Debug+?Sized` as `*mut impl std::fmt::Debug+?Sized` is invalid - --> $DIR/casts-differing-anon.rs:33:13 + --> $DIR/casts-differing-anon.rs:31:13 | LL | b_raw = f_raw as *mut _; //~ ERROR is invalid | ^^^^^^^^^^^^^^^ @@ -8,4 +8,4 @@ LL | b_raw = f_raw as *mut _; //~ ERROR is invalid error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0606" +For more information about this error, try `rustc --explain E0606`. diff --git a/src/test/ui/casts-issue-46365.stderr b/src/test/ui/casts-issue-46365.stderr index 138388f29765..08ba5e4b3210 100644 --- a/src/test/ui/casts-issue-46365.stderr +++ b/src/test/ui/casts-issue-46365.stderr @@ -6,4 +6,4 @@ LL | ipsum: Ipsum //~ ERROR cannot find type `Ipsum` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0412" +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs new file mode 100644 index 000000000000..2083ada6d2de --- /dev/null +++ b/src/test/ui/chalkify/lower_impl.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +trait Foo { } + +#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- +impl Foo for T where T: Iterator { } + +fn main() { + println!("hello"); +} diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr new file mode 100644 index 000000000000..b5d791d640ad --- /dev/null +++ b/src/test/ui/chalkify/lower_impl.stderr @@ -0,0 +1,8 @@ +error: Implemented(T: Foo) :- ProjectionEq(::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). + --> $DIR/lower_impl.rs:15:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs new file mode 100644 index 000000000000..010cb77edc3f --- /dev/null +++ b/src/test/ui/chalkify/lower_trait.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- +trait Foo { + fn s(S) -> S; + fn t(T) -> T; + fn u(U) -> U; +} + +fn main() { + println!("hello"); +} diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr new file mode 100644 index 000000000000..6da1e2fd8edd --- /dev/null +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -0,0 +1,8 @@ +error: Implemented(Self: Foo) :- FromEnv(Self: Foo). + --> $DIR/lower_trait.rs:13:1 + | +LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo) :- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/changing-crates.stderr b/src/test/ui/changing-crates.stderr index 436335aa917d..d8de685c7d7a 100644 --- a/src/test/ui/changing-crates.stderr +++ b/src/test/ui/changing-crates.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr index 3768d5782e76..418573171f1e 100644 --- a/src/test/ui/check_match/issue-35609.stderr +++ b/src/test/ui/check_match/issue-35609.stderr @@ -48,4 +48,4 @@ LL | match Some(A) { //~ ERROR non-exhaustive error: aborting due to 8 previous errors -If you want more information on this error, try using "rustc --explain E0004" +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr index 20661cae5ca2..8184616c97ff 100644 --- a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr +++ b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr @@ -84,4 +84,4 @@ LL | f = Some(x); error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closure-move-sync.rs b/src/test/ui/closure-move-sync.rs new file mode 100644 index 000000000000..e096e7ca3a06 --- /dev/null +++ b/src/test/ui/closure-move-sync.rs @@ -0,0 +1,32 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::thread; +use std::sync::mpsc::channel; + +fn bar() { + let (send, recv) = channel(); + let t = thread::spawn(|| { + recv.recv().unwrap(); + //~^^ ERROR `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + }); + + send.send(()); + + t.join().unwrap(); +} + +fn foo() { + let (tx, _rx) = channel(); + thread::spawn(|| tx.send(()).unwrap()); + //~^ ERROR `std::sync::mpsc::Sender<()>` cannot be shared between threads safely +} + +fn main() {} diff --git a/src/test/ui/closure-move-sync.stderr b/src/test/ui/closure-move-sync.stderr new file mode 100644 index 000000000000..076bae8dbd7a --- /dev/null +++ b/src/test/ui/closure-move-sync.stderr @@ -0,0 +1,25 @@ +error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + --> $DIR/closure-move-sync.rs:16:13 + | +LL | let t = thread::spawn(|| { + | ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<()>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Receiver<()>` + = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:16:27: 19:6 recv:&std::sync::mpsc::Receiver<()>]` + = note: required by `std::thread::spawn` + +error[E0277]: `std::sync::mpsc::Sender<()>` cannot be shared between threads safely + --> $DIR/closure-move-sync.rs:28:5 + | +LL | thread::spawn(|| tx.send(()).unwrap()); + | ^^^^^^^^^^^^^ `std::sync::mpsc::Sender<()>` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>` + = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<()>` + = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:28:19: 28:42 tx:&std::sync::mpsc::Sender<()>]` + = note: required by `std::thread::spawn` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr index 9cc0f1bf9df7..ac98d9427e45 100644 --- a/src/test/ui/closure_context/issue-26046-fn-mut.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr @@ -11,4 +11,4 @@ LL | Box::new(closure) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0525" +For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr index 0facdaf3c70a..e09fdb5fb778 100644 --- a/src/test/ui/closure_context/issue-26046-fn-once.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr @@ -11,4 +11,4 @@ LL | Box::new(closure) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0525" +For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr index fdbec34ca7ed..5c2105c4f795 100644 --- a/src/test/ui/closure_context/issue-42065.stderr +++ b/src/test/ui/closure_context/issue-42065.stderr @@ -14,4 +14,4 @@ LL | for (key, value) in dict { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr index 6531e3b8f8b7..7975966bf809 100644 --- a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr +++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -8,4 +8,4 @@ LL | impl C { fn f() {} } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0592" +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr index 63b19c9e0c6a..9383bfc92a87 100644 --- a/src/test/ui/codemap_tests/empty_span.stderr +++ b/src/test/ui/codemap_tests/empty_span.stderr @@ -2,8 +2,8 @@ error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, --> $DIR/empty_span.rs:17:5 | LL | unsafe impl Send for &'static Foo { } //~ ERROR cross-crate traits with a default impl - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0321" +For more information about this error, try `rustc --explain E0321`. diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index 2fdd6906a564..68818f50cd27 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -9,4 +9,4 @@ LL | let y = &mut x; //~ ERROR cannot borrow error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr index d44dac0d5376..d9551d7918a9 100644 --- a/src/test/ui/codemap_tests/issue-11715.stderr +++ b/src/test/ui/codemap_tests/issue-11715.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0499" +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/codemap_tests/issue-28308.rs b/src/test/ui/codemap_tests/issue-28308.rs index e3a4920d951f..c71c28ed6252 100644 --- a/src/test/ui/codemap_tests/issue-28308.rs +++ b/src/test/ui/codemap_tests/issue-28308.rs @@ -10,4 +10,5 @@ fn main() { assert!("foo"); + //~^ ERROR cannot apply unary operator `!` } diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr index 947c8142e31f..2c8a33d95c03 100644 --- a/src/test/ui/codemap_tests/issue-28308.stderr +++ b/src/test/ui/codemap_tests/issue-28308.stderr @@ -3,9 +3,7 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` | LL | assert!("foo"); | ^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0600" +For more information about this error, try `rustc --explain E0600`. diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr index a31a5318b41e..5a6d474ed166 100644 --- a/src/test/ui/codemap_tests/one_line.stderr +++ b/src/test/ui/codemap_tests/one_line.stderr @@ -9,4 +9,4 @@ LL | v.push(v.pop().unwrap()); //~ ERROR cannot borrow error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0499" +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr index d11ac5463f03..db729ac34f32 100644 --- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -29,4 +29,4 @@ LL | fn baz(&self) {} error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0592" +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/codemap_tests/overlapping_spans.stderr b/src/test/ui/codemap_tests/overlapping_spans.stderr index c585964a5274..62a4f08e1566 100644 --- a/src/test/ui/codemap_tests/overlapping_spans.stderr +++ b/src/test/ui/codemap_tests/overlapping_spans.stderr @@ -9,4 +9,4 @@ LL | S {f:_s} => {} //~ ERROR cannot move out error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0509" +For more information about this error, try `rustc --explain E0509`. diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr index 0f683bd68415..c466610bcec8 100644 --- a/src/test/ui/codemap_tests/tab.stderr +++ b/src/test/ui/codemap_tests/tab.stderr @@ -17,5 +17,5 @@ LL | "bar boo" //~ ERROR mismatched types error: aborting due to 2 previous errors -You've got a few errors: E0308, E0425 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr index c2826359e080..d960c0b7da80 100644 --- a/src/test/ui/codemap_tests/tab_3.stderr +++ b/src/test/ui/codemap_tests/tab_3.stderr @@ -11,4 +11,4 @@ LL | println!("{:?}", some_vec); //~ ERROR use of moved error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr index a7fa82a0ba15..e247e86fbcb2 100644 --- a/src/test/ui/codemap_tests/two_files.stderr +++ b/src/test/ui/codemap_tests/two_files.stderr @@ -4,6 +4,6 @@ error[E0404]: expected trait, found type alias `Bar` LL | impl Bar for Baz { } //~ ERROR expected trait, found type alias | ^^^ type aliases cannot be used for traits -error: cannot continue compilation due to previous error +error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0404" +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/codemap_tests/unicode_2.stderr b/src/test/ui/codemap_tests/unicode_2.stderr index b75245589b02..b7f7f7fc5ce9 100644 --- a/src/test/ui/codemap_tests/unicode_2.stderr +++ b/src/test/ui/codemap_tests/unicode_2.stderr @@ -22,4 +22,4 @@ LL | let _ = a̐é; //~ ERROR cannot find error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index 74b6f083f38d..84b6c961a253 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -26,4 +26,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coherence-error-suppression.stderr b/src/test/ui/coherence-error-suppression.stderr index e195e9452e5a..8cf3fe760f12 100644 --- a/src/test/ui/coherence-error-suppression.stderr +++ b/src/test/ui/coherence-error-suppression.stderr @@ -6,4 +6,4 @@ LL | impl Foo for DoesNotExist {} //~ ERROR cannot find type `DoesNotExist` in t error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0412" +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/coherence-impls-copy.rs b/src/test/ui/coherence-impls-copy.rs index 51f43d27c34d..f48790d1f403 100644 --- a/src/test/ui/coherence-impls-copy.rs +++ b/src/test/ui/coherence-impls-copy.rs @@ -12,6 +12,10 @@ use std::marker::Copy; +impl Copy for i32 {} +//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `i32`: +//~| ERROR only traits defined in the current crate can be implemented for arbitrary types + enum TestE { A } @@ -35,14 +39,14 @@ impl Copy for (MyType, MyType) {} //~| ERROR only traits defined in the current crate can be implemented for arbitrary types impl Copy for &'static NotSync {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&NotSync`: impl Copy for [MyType] {} //~^ ERROR the trait `Copy` may not be implemented for this type //~| ERROR only traits defined in the current crate can be implemented for arbitrary types impl Copy for &'static [NotSync] {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`: //~| ERROR only traits defined in the current crate can be implemented for arbitrary types fn main() { diff --git a/src/test/ui/coherence-impls-copy.stderr b/src/test/ui/coherence-impls-copy.stderr index 029b04789525..24e7e85b1a96 100644 --- a/src/test/ui/coherence-impls-copy.stderr +++ b/src/test/ui/coherence-impls-copy.stderr @@ -1,47 +1,64 @@ +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`: + --> $DIR/coherence-impls-copy.rs:15:1 + | +LL | impl Copy for i32 {} + | ^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl std::marker::Copy for i32; + +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`: + --> $DIR/coherence-impls-copy.rs:41:1 + | +LL | impl Copy for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<'a, T> std::marker::Copy for &'a T + where T: ?Sized; + +error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`: + --> $DIR/coherence-impls-copy.rs:48:1 + | +LL | impl Copy for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<'a, T> std::marker::Copy for &'a T + where T: ?Sized; + error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:29:15 + --> $DIR/coherence-impls-copy.rs:33:15 | LL | impl Copy for &'static mut MyType {} | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:33:15 + --> $DIR/coherence-impls-copy.rs:37:15 | LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:37:15 - | -LL | impl Copy for &'static NotSync {} - | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration - -error[E0206]: the trait `Copy` may not be implemented for this type - --> $DIR/coherence-impls-copy.rs:40:15 - | -LL | impl Copy for [MyType] {} - | ^^^^^^^^ type is not a structure or enumeration - error[E0206]: the trait `Copy` may not be implemented for this type --> $DIR/coherence-impls-copy.rs:44:15 | -LL | impl Copy for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration +LL | impl Copy for [MyType] {} + | ^^^^^^^^ type is not a structure or enumeration error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:33:1 + --> $DIR/coherence-impls-copy.rs:15:1 | -LL | impl Copy for (MyType, MyType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate +LL | impl Copy for i32 {} + | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence-impls-copy.rs:40:1 + --> $DIR/coherence-impls-copy.rs:37:1 | -LL | impl Copy for [MyType] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate +LL | impl Copy for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead @@ -49,13 +66,22 @@ LL | impl Copy for [MyType] {} error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence-impls-copy.rs:44:1 | -LL | impl Copy for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate +LL | impl Copy for [MyType] {} + | ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead -error: aborting due to 8 previous errors +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-copy.rs:48:1 + | +LL | impl Copy for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead -You've got a few errors: E0117, E0206 -If you want more information on an error, try using "rustc --explain E0117" +error: aborting due to 10 previous errors + +Some errors occurred: E0117, E0119, E0206. +For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence-overlap-downstream-inherent.stderr b/src/test/ui/coherence-overlap-downstream-inherent.stderr index ec315d897ac1..29df3f9c37a3 100644 --- a/src/test/ui/coherence-overlap-downstream-inherent.stderr +++ b/src/test/ui/coherence-overlap-downstream-inherent.stderr @@ -20,4 +20,4 @@ LL | impl A { fn f(&self) {} } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0592" +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/coherence-overlap-downstream.stderr b/src/test/ui/coherence-overlap-downstream.stderr index 1fac596ed300..8e14e4f9bda1 100644 --- a/src/test/ui/coherence-overlap-downstream.stderr +++ b/src/test/ui/coherence-overlap-downstream.stderr @@ -18,4 +18,4 @@ LL | impl Foo for i32 {} error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence-overlap-issue-23516-inherent.stderr b/src/test/ui/coherence-overlap-issue-23516-inherent.stderr index 6bb73e6d3833..d217a4d2cdf9 100644 --- a/src/test/ui/coherence-overlap-issue-23516-inherent.stderr +++ b/src/test/ui/coherence-overlap-issue-23516-inherent.stderr @@ -11,4 +11,4 @@ LL | impl Cake> { fn dummy(&self) { } } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0592" +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/coherence-overlap-issue-23516.stderr b/src/test/ui/coherence-overlap-issue-23516.stderr index fe4e7cf34873..ea2ecda6f0de 100644 --- a/src/test/ui/coherence-overlap-issue-23516.stderr +++ b/src/test/ui/coherence-overlap-issue-23516.stderr @@ -10,4 +10,4 @@ LL | impl Sweet for Box { } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence-overlap-upstream-inherent.stderr b/src/test/ui/coherence-overlap-upstream-inherent.stderr index a7a6003b06c8..6c6f0dc24833 100644 --- a/src/test/ui/coherence-overlap-upstream-inherent.stderr +++ b/src/test/ui/coherence-overlap-upstream-inherent.stderr @@ -11,4 +11,4 @@ LL | impl A { fn dummy(&self) { } } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0592" +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/coherence-overlap-upstream.stderr b/src/test/ui/coherence-overlap-upstream.stderr index cc199548f062..794c830cc5bf 100644 --- a/src/test/ui/coherence-overlap-upstream.stderr +++ b/src/test/ui/coherence-overlap-upstream.stderr @@ -10,4 +10,4 @@ LL | impl Foo for i16 {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/command-line-diagnostics.stderr b/src/test/ui/command-line-diagnostics.stderr index 9e9e03373e88..2a45edae3256 100644 --- a/src/test/ui/command-line-diagnostics.stderr +++ b/src/test/ui/command-line-diagnostics.stderr @@ -8,4 +8,4 @@ LL | x = 43; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0384" +For more information about this error, try `rustc --explain E0384`. diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index 9abecb2e03c8..5d734a25fe88 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -9,4 +9,4 @@ LL | fn foo() where U: 'a { } //~ ERROR E0276 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index 32d7024db35d..4e4f0d7c7bce 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -9,4 +9,4 @@ LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index ce62cc62e222..a366fe746766 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -9,4 +9,4 @@ LL | fn foo() where 'a: 'b { } //~ ERROR impl has stricter error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index 2026dd1f1ccc..6448e0fb25ab 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -9,4 +9,4 @@ LL | fn foo() where V: 'a { } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index 8f0744fa56db..1efd5f2fb258 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -12,4 +12,4 @@ LL | fn b(&self, _x: G) -> G { panic!() } //~ ERROR method `b` has error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0053" +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr index 53aced771ccb..4530cb187183 100644 --- a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -9,4 +9,4 @@ LL | fn b(&self, _x: F) -> F { panic!() } //~ ERROR E0276 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr index a0c333c3a53f..e99ce95b371c 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr @@ -63,4 +63,4 @@ LL | fn method>(&self) {} error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr index 921b0e5d1c49..1de5b1a8a1a9 100644 --- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr @@ -9,4 +9,4 @@ LL | fn zip>(self, other: U) -> ZipIterator { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/const-deref-ptr.stderr b/src/test/ui/const-deref-ptr.stderr index 8a80802c52ca..61db58104d2d 100644 --- a/src/test/ui/const-deref-ptr.stderr +++ b/src/test/ui/const-deref-ptr.stderr @@ -6,4 +6,4 @@ LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; //~ ERROR E0396 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0396" +For more information about this error, try `rustc --explain E0396`. diff --git a/src/test/ui/const-eval-overflow-2.stderr b/src/test/ui/const-eval-overflow-2.stderr index f376de7cc4c1..9cee718c286b 100644 --- a/src/test/ui/const-eval-overflow-2.stderr +++ b/src/test/ui/const-eval-overflow-2.stderr @@ -12,4 +12,4 @@ LL | NEG_NEG_128 => println!("A"), error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-eval-overflow-4.stderr b/src/test/ui/const-eval-overflow-4.stderr index 14753038fef0..db0a6fc82044 100644 --- a/src/test/ui/const-eval-overflow-4.stderr +++ b/src/test/ui/const-eval-overflow-4.stderr @@ -14,4 +14,4 @@ LL | : [u32; (i8::MAX as i8 + 1i8) as usize] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-eval-span.stderr b/src/test/ui/const-eval-span.stderr index e3c28cafc628..afe8d1bc0b5b 100644 --- a/src/test/ui/const-eval-span.stderr +++ b/src/test/ui/const-eval-span.stderr @@ -9,4 +9,4 @@ LL | V = CONSTANT, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index 4cf12e222831..9270dafbe651 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -14,4 +14,4 @@ LL | println!("{}", FOO); //~ E0080 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-eval/index_out_of_bound.stderr b/src/test/ui/const-eval/index_out_of_bound.stderr index 7651fb257e3c..793e0a7ace8d 100644 --- a/src/test/ui/const-eval/index_out_of_bound.stderr +++ b/src/test/ui/const-eval/index_out_of_bound.stderr @@ -6,4 +6,4 @@ LL | static FOO: i32 = [][0]; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index 3f1082687475..2d51e6603b59 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -26,4 +26,4 @@ LL | println!("{} {}", X, Y); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-fn-error.stderr b/src/test/ui/const-fn-error.stderr index d57efce0dffc..077c4d60e649 100644 --- a/src/test/ui/const-fn-error.stderr +++ b/src/test/ui/const-fn-error.stderr @@ -33,5 +33,5 @@ LL | let a : [i32; f(X)]; error: aborting due to 4 previous errors -You've got a few errors: E0015, E0016, E0019, E0080 -If you want more information on an error, try using "rustc --explain E0015" +Some errors occurred: E0015, E0016, E0019, E0080. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/const-fn-mismatch.stderr b/src/test/ui/const-fn-mismatch.stderr index efbf701120d2..1c9728fec9ec 100644 --- a/src/test/ui/const-fn-mismatch.stderr +++ b/src/test/ui/const-fn-mismatch.stderr @@ -6,4 +6,4 @@ LL | const fn f() -> u32 { 22 } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0379" +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/const-fn-not-in-trait.stderr b/src/test/ui/const-fn-not-in-trait.stderr index 4a77862c3122..5801f701ff8f 100644 --- a/src/test/ui/const-fn-not-in-trait.stderr +++ b/src/test/ui/const-fn-not-in-trait.stderr @@ -12,4 +12,4 @@ LL | const fn g() -> u32 { 0 } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0379" +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/const-len-underflow-separate-spans.stderr b/src/test/ui/const-len-underflow-separate-spans.stderr index 98f4ac9e83fb..8d737dbfc085 100644 --- a/src/test/ui/const-len-underflow-separate-spans.stderr +++ b/src/test/ui/const-len-underflow-separate-spans.stderr @@ -20,4 +20,4 @@ LL | let a: [i8; LEN] = unimplemented!(); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-pattern-irrefutable.stderr b/src/test/ui/const-pattern-irrefutable.stderr index 9a05d4c76c49..6d5738f33287 100644 --- a/src/test/ui/const-pattern-irrefutable.stderr +++ b/src/test/ui/const-pattern-irrefutable.stderr @@ -18,4 +18,4 @@ LL | let d = 4; //~ ERROR refutable pattern in local binding: `_` not covere error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0005" +For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/const-unsized.stderr b/src/test/ui/const-unsized.stderr index 478539c88eac..0bbb5debbba6 100644 --- a/src/test/ui/const-unsized.stderr +++ b/src/test/ui/const-unsized.stderr @@ -36,4 +36,4 @@ LL | static STATIC_BAR: str = *"bar"; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/cross-file-errors/main.stderr b/src/test/ui/cross-file-errors/main.stderr index a9db5214e6a2..a64595fbb402 100644 --- a/src/test/ui/cross-file-errors/main.stderr +++ b/src/test/ui/cross-file-errors/main.stderr @@ -1,4 +1,4 @@ -error: expected expression, found `_` +error: expected expression, found reserved identifier `_` --> $DIR/underscore.rs:18:9 | LL | _ @@ -9,3 +9,5 @@ LL | _ LL | underscore!(); | -------------- in this macro invocation +error: aborting due to previous error + diff --git a/src/test/ui/cycle-trait-supertrait-indirect.stderr b/src/test/ui/cycle-trait-supertrait-indirect.stderr index 388da3f860e0..68c20df5f721 100644 --- a/src/test/ui/cycle-trait-supertrait-indirect.stderr +++ b/src/test/ui/cycle-trait-supertrait-indirect.stderr @@ -18,4 +18,4 @@ LL | trait B: C { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 620cbd9d3364..a5f87928924c 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -60,4 +60,4 @@ LL | foo3(borrow!(0)); error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/derived-errors/issue-31997-1.stderr b/src/test/ui/derived-errors/issue-31997-1.stderr index 92c025046a22..7cdcac3891fc 100644 --- a/src/test/ui/derived-errors/issue-31997-1.stderr +++ b/src/test/ui/derived-errors/issue-31997-1.stderr @@ -6,4 +6,4 @@ LL | let mut map = HashMap::new(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0433" +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/did_you_mean/E0178.stderr b/src/test/ui/did_you_mean/E0178.stderr index 293cf7444f4a..29e7aeb45ca7 100644 --- a/src/test/ui/did_you_mean/E0178.stderr +++ b/src/test/ui/did_you_mean/E0178.stderr @@ -24,4 +24,4 @@ LL | z: fn() -> Foo + 'a, //~ ERROR expected a path error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0178" +For more information about this error, try `rustc --explain E0178`. diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr index 80caa86fde55..10ee175a97e1 100644 --- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr @@ -48,4 +48,4 @@ LL | &(u8,)::AssocItem => {} error: aborting due to 8 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index b584fa16988e..169a12ef92e9 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -46,7 +46,7 @@ error[E0223]: ambiguous associated type LL | type A = [u8; 4]::AssocTy; | ^^^^^^^^^^^^^^^^ ambiguous associated type | - = note: specify the type using the syntax `<[u8; ] as Trait>::AssocTy` + = note: specify the type using the syntax `<[u8; _] as Trait>::AssocTy` error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:15:10 @@ -104,5 +104,5 @@ LL | type H = Fn(u8) -> (u8)::Output; error: aborting due to 15 previous errors -You've got a few errors: E0121, E0223 -If you want more information on an error, try using "rustc --explain E0121" +Some errors occurred: E0121, E0223. +For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 5290b388e476..1e55b0c024fb 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -10,4 +10,4 @@ LL | f1.foo(1usize); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index d1b3b2031f6c..eee7f32032b6 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -13,4 +13,4 @@ LL | f1.foo(1usize); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr index eb2659e1fcaa..a80593e05f10 100644 --- a/src/test/ui/did_you_mean/issue-31424.stderr +++ b/src/test/ui/did_you_mean/issue-31424.stderr @@ -17,4 +17,4 @@ LL | (&mut self).bar(); //~ ERROR cannot borrow error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr index b99b1b54d538..08ece78b7888 100644 --- a/src/test/ui/did_you_mean/issue-34126.stderr +++ b/src/test/ui/did_you_mean/issue-34126.stderr @@ -9,4 +9,4 @@ LL | self.run(&mut self); //~ ERROR cannot borrow error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/did_you_mean/issue-34337.stderr b/src/test/ui/did_you_mean/issue-34337.stderr index 3b73132423d4..7a4a03ce5d7e 100644 --- a/src/test/ui/did_you_mean/issue-34337.stderr +++ b/src/test/ui/did_you_mean/issue-34337.stderr @@ -9,4 +9,4 @@ LL | get(&mut key); //~ ERROR cannot borrow error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 7894ca208818..4a29cd81425c 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -24,5 +24,5 @@ LL | s.x += 1; //~ ERROR cannot assign error: aborting due to 3 previous errors -You've got a few errors: E0594, E0596 -If you want more information on an error, try using "rustc --explain E0594" +Some errors occurred: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index 100f93d2e31c..c0a73abdf725 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -6,4 +6,4 @@ LL | f.baz; //~ ERROR no field error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0609" +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr index 4bbadf3a7906..4cf0df443512 100644 --- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -8,4 +8,4 @@ LL | f.zz; //~ ERROR no field error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0609" +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/did_you_mean/issue-37139.stderr b/src/test/ui/did_you_mean/issue-37139.stderr index 9d918964ce6c..7cf3326f9d61 100644 --- a/src/test/ui/did_you_mean/issue-37139.stderr +++ b/src/test/ui/did_you_mean/issue-37139.stderr @@ -9,4 +9,4 @@ LL | test(&mut x); //~ ERROR cannot borrow immutable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr index 5a9fbafb8eb5..e3c75599a415 100644 --- a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -12,4 +12,4 @@ LL | use Foo1; //~ ERROR unresolved error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0432" +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index ca842b396465..4ebb5683405d 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -8,4 +8,4 @@ LL | self.s.push('x'); //~ ERROR cannot borrow data mutably error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0389" +For more information about this error, try `rustc --explain E0389`. diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr index 606f1dd52232..31433cf83c3b 100644 --- a/src/test/ui/did_you_mean/issue-38147-2.stderr +++ b/src/test/ui/did_you_mean/issue-38147-2.stderr @@ -9,4 +9,4 @@ LL | self.s.push('x'); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr index cf075204e8b7..8bb23acdc407 100644 --- a/src/test/ui/did_you_mean/issue-38147-3.stderr +++ b/src/test/ui/did_you_mean/issue-38147-3.stderr @@ -9,4 +9,4 @@ LL | self.s.push('x'); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index a10acf1460dc..e78cea14a7b5 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -8,4 +8,4 @@ LL | f.s.push('x'); //~ ERROR cannot borrow data mutably error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0389" +For more information about this error, try `rustc --explain E0389`. diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index a05b70b2eb86..dfa9cb880e56 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -98,5 +98,5 @@ LL | *x.0 = 1; error: aborting due to 12 previous errors -You've got a few errors: E0594, E0596 -If you want more information on an error, try using "rustc --explain E0594" +Some errors occurred: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index c08ee4247c7b..3f955da86ba0 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -53,4 +53,4 @@ LL | fn bar(&self){} error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index e576393500fe..a3433939573a 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -66,4 +66,4 @@ LL | impl X { //~ ERROR cannot be made into an object error: aborting due to 9 previous errors -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index 3aece9908a9c..20e95513ec2f 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -6,4 +6,4 @@ LL | buf.iter_mut(); //~ ERROR cannot borrow immutable borrowed content error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/compile-fail/feature-gate-termination_trait.rs b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs similarity index 86% rename from src/test/compile-fail/feature-gate-termination_trait.rs rename to src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs index 5a56445b64e5..e8fd248011cb 100644 --- a/src/test/compile-fail/feature-gate-termination_trait.rs +++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() -> i32 { //~ ERROR main function has wrong type [E0580] - 0 +fn main() { + let x = ~1; //~ ERROR cannot be used as a unary operator } diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr new file mode 100644 index 000000000000..f13f15f63771 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr @@ -0,0 +1,8 @@ +error: `~` cannot be used as a unary operator + --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:12:13 + | +LL | let x = ~1; //~ ERROR cannot be used as a unary operator + | ^ help: use `!` to perform bitwise negation + +error: aborting due to previous error + diff --git a/src/test/ui/did_you_mean/issue-41679.stderr b/src/test/ui/did_you_mean/issue-41679.stderr deleted file mode 100644 index c17812fc0cb9..000000000000 --- a/src/test/ui/did_you_mean/issue-41679.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: `~` can not be used as a unary operator - --> $DIR/issue-41679.rs:12:13 - | -LL | let x = ~1; //~ ERROR can not be used as a unary operator - | ^ did you mean `!`? - | - = help: use `!` instead of `~` if you meant to perform bitwise negation - -error: aborting due to previous error - diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr index 64c20ff8e078..c4b282bde528 100644 --- a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr +++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr @@ -28,5 +28,5 @@ LL | let egregious_field_misaccess = demo.egregiously_nonexistent_field; error: aborting due to 4 previous errors -You've got a few errors: E0560, E0609 -If you want more information on an error, try using "rustc --explain E0560" +Some errors occurred: E0560, E0609. +For more information about an error, try `rustc --explain E0560`. diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr index 390b214e62e0..f1da920872d7 100644 --- a/src/test/ui/did_you_mean/issue-42764.stderr +++ b/src/test/ui/did_you_mean/issue-42764.stderr @@ -15,4 +15,4 @@ LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr index 1f653c908866..779ae31ca300 100644 --- a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr +++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr @@ -30,5 +30,5 @@ LL | if let Example(_) = y { //~ ERROR expected tuple struct/variant, found error: aborting due to 3 previous errors -You've got a few errors: E0423, E0532 -If you want more information on an error, try using "rustc --explain E0423" +Some errors occurred: E0423, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/parse-fail/match-refactor-to-expr.rs b/src/test/ui/did_you_mean/match-refactor-to-expr.rs similarity index 91% rename from src/test/parse-fail/match-refactor-to-expr.rs rename to src/test/ui/did_you_mean/match-refactor-to-expr.rs index e2fee1d18959..3c88608697aa 100644 --- a/src/test/parse-fail/match-refactor-to-expr.rs +++ b/src/test/ui/did_you_mean/match-refactor-to-expr.rs @@ -12,7 +12,7 @@ fn main() { let foo = - match //~ NOTE did you mean to remove this `match` keyword? + match Some(4).unwrap_or_else(5) //~^ NOTE expected one of `.`, `?`, `{`, or an operator here ; //~ NOTE unexpected token diff --git a/src/test/ui/did_you_mean/match-refactor-to-expr.stderr b/src/test/ui/did_you_mean/match-refactor-to-expr.stderr new file mode 100644 index 000000000000..ecca781684ce --- /dev/null +++ b/src/test/ui/did_you_mean/match-refactor-to-expr.stderr @@ -0,0 +1,13 @@ +error: expected one of `.`, `?`, `{`, or an operator, found `;` + --> $DIR/match-refactor-to-expr.rs:18:9 + | +LL | match + | ----- help: try removing this `match` +LL | Some(4).unwrap_or_else(5) + | - expected one of `.`, `?`, `{`, or an operator here +LL | //~^ NOTE expected one of `.`, `?`, `{`, or an operator here +LL | ; //~ NOTE unexpected token + | ^ unexpected token + +error: aborting due to previous error + diff --git a/src/test/parse-fail/pub-macro-rules.rs b/src/test/ui/did_you_mean/pub-macro-rules.rs similarity index 91% rename from src/test/parse-fail/pub-macro-rules.rs rename to src/test/ui/did_you_mean/pub-macro-rules.rs index 93b992f2f8af..65a0d642cd7d 100644 --- a/src/test/parse-fail/pub-macro-rules.rs +++ b/src/test/ui/did_you_mean/pub-macro-rules.rs @@ -9,8 +9,7 @@ // except according to those terms. #[macro_use] mod bleh { - pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation with `pub` - //~^ HELP did you mean #[macro_export]? + pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation ($n:ident) => ( fn $n () -> i32 { 1 diff --git a/src/test/ui/did_you_mean/pub-macro-rules.stderr b/src/test/ui/did_you_mean/pub-macro-rules.stderr new file mode 100644 index 000000000000..dfeab75525ba --- /dev/null +++ b/src/test/ui/did_you_mean/pub-macro-rules.stderr @@ -0,0 +1,8 @@ +error: can't qualify macro_rules invocation with `pub` + --> $DIR/pub-macro-rules.rs:12:5 + | +LL | pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation + | ^^^ help: try exporting the macro: `#[macro_export]` + +error: aborting due to previous error + diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index 8b34c533d8b4..691c7ccd9fdf 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -23,4 +23,4 @@ LL | fn is_send() { } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0275" +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs index 3e261ec636c0..f5e75f40fca0 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.rs +++ b/src/test/ui/did_you_mean/recursion_limit_deref.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//~^^^^^^^^^^ ERROR reached the recursion limit - // Test that the recursion limit can be changed and that the compiler // suggests a fix. In this case, we have a long chain of Deref impls // which will cause an overflow during the autoderef loop. diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index a4048fbfb265..20a94f7aac19 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -1,17 +1,13 @@ error[E0055]: reached the recursion limit while auto-dereferencing I - --> $DIR/recursion_limit_deref.rs:62:22 + --> $DIR/recursion_limit_deref.rs:60:22 | LL | let x: &Bottom = &t; //~ ERROR mismatched types | ^^ deref recursion limit reached | = help: consider adding a `#![recursion_limit="20"]` attribute to your crate -error[E0055]: reached the recursion limit while auto-dereferencing I - | - = help: consider adding a `#![recursion_limit="20"]` attribute to your crate - error[E0308]: mismatched types - --> $DIR/recursion_limit_deref.rs:62:22 + --> $DIR/recursion_limit_deref.rs:60:22 | LL | let x: &Bottom = &t; //~ ERROR mismatched types | ^^ expected struct `Bottom`, found struct `Top` @@ -19,7 +15,7 @@ LL | let x: &Bottom = &t; //~ ERROR mismatched types = note: expected type `&Bottom` found type `&Top` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -You've got a few errors: E0055, E0308 -If you want more information on an error, try using "rustc --explain E0055" +Some errors occurred: E0055, E0308. +For more information about an error, try `rustc --explain E0055`. diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr index f6bce55528c7..265a688df991 100644 --- a/src/test/ui/did_you_mean/recursion_limit_macro.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr @@ -9,3 +9,5 @@ LL | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); | = help: consider adding a `#![recursion_limit="20"]` attribute to your crate +error: aborting due to previous error + diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index fcfa80e1c9d8..6dd216489313 100644 --- a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -20,5 +20,5 @@ LL | let _: &Copy + 'static; //~ ERROR expected a path error: aborting due to 3 previous errors -You've got a few errors: E0038, E0178 -If you want more information on an error, try using "rustc --explain E0038" +Some errors occurred: E0038, E0178. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/discrim-overflow-2.stderr b/src/test/ui/discrim-overflow-2.stderr index 6162766b5870..bd610bc7163d 100644 --- a/src/test/ui/discrim-overflow-2.stderr +++ b/src/test/ui/discrim-overflow-2.stderr @@ -64,4 +64,4 @@ LL | OhNo, //~ ERROR enum discriminant overflowed [E0370] error: aborting due to 8 previous errors -If you want more information on this error, try using "rustc --explain E0370" +For more information about this error, try `rustc --explain E0370`. diff --git a/src/test/ui/discrim-overflow.stderr b/src/test/ui/discrim-overflow.stderr index a713aea1b21e..ef784679ce02 100644 --- a/src/test/ui/discrim-overflow.stderr +++ b/src/test/ui/discrim-overflow.stderr @@ -64,4 +64,4 @@ LL | OhNo, //~ ERROR enum discriminant overflowed [E0370] error: aborting due to 8 previous errors -If you want more information on this error, try using "rustc --explain E0370" +For more information about this error, try `rustc --explain E0370`. diff --git a/src/test/ui/double-import.stderr b/src/test/ui/double-import.stderr index ceddff4047b1..df6463a7e288 100644 --- a/src/test/ui/double-import.stderr +++ b/src/test/ui/double-import.stderr @@ -14,4 +14,4 @@ LL | use sub2::foo as other_foo; //~ ERROR the name `foo` is defined multiple ti error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0252" +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs b/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs index 1b00d88dcb3d..08722ca62ac4 100644 --- a/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs +++ b/src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // This is a support file for ../dropck-eyepatch-extern-crate.rs diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr index 454ee6afe24b..668fbf9521b1 100644 --- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr @@ -44,4 +44,4 @@ LL | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs index f92c8703dc92..cba438b02a92 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // This test ensures that a use of `#[may_dangle]` is rejected if diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr index d5b4e85ce5e4..9d68ff13ef34 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -1,5 +1,5 @@ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute - --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:32:1 + --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:31:1 | LL | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { LL | | //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute @@ -10,7 +10,7 @@ LL | | } | |_^ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute - --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:38:1 + --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:37:1 | LL | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { LL | | //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute @@ -22,4 +22,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0569" +For more information about this error, try `rustc --explain E0569`. diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.rs b/src/test/ui/dropck/dropck-eyepatch-reorder.rs index 3bd9efb32b3b..eda8d85f6ec9 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.rs +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // The point of this test is to test uses of `#[may_dangle]` attribute diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr index 6fac358e21af..1a35996a0cad 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch-reorder.rs:57:20 + --> $DIR/dropck-eyepatch-reorder.rs:56:20 | LL | dt = Dt("dt", &c); | ^ borrowed value does not live long enough @@ -10,7 +10,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch-reorder.rs:59:20 + --> $DIR/dropck-eyepatch-reorder.rs:58:20 | LL | dr = Dr("dr", &c); | ^ borrowed value does not live long enough @@ -21,7 +21,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch-reorder.rs:67:29 + --> $DIR/dropck-eyepatch-reorder.rs:66:29 | LL | pt = Pt("pt", &c_long, &c); | ^ borrowed value does not live long enough @@ -32,7 +32,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch-reorder.rs:69:29 + --> $DIR/dropck-eyepatch-reorder.rs:68:29 | LL | pr = Pr("pr", &c_long, &c); | ^ borrowed value does not live long enough @@ -44,4 +44,4 @@ LL | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/dropck/dropck-eyepatch.rs b/src/test/ui/dropck/dropck-eyepatch.rs index abaae47189f8..af173a2e9791 100644 --- a/src/test/ui/dropck/dropck-eyepatch.rs +++ b/src/test/ui/dropck/dropck-eyepatch.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generic_param_attrs)] #![feature(dropck_eyepatch)] // The point of this test is to illustrate that the `#[may_dangle]` diff --git a/src/test/ui/dropck/dropck-eyepatch.stderr b/src/test/ui/dropck/dropck-eyepatch.stderr index d8cc5bf23730..4d2916420229 100644 --- a/src/test/ui/dropck/dropck-eyepatch.stderr +++ b/src/test/ui/dropck/dropck-eyepatch.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch.rs:80:20 + --> $DIR/dropck-eyepatch.rs:79:20 | LL | dt = Dt("dt", &c); | ^ borrowed value does not live long enough @@ -10,7 +10,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch.rs:82:20 + --> $DIR/dropck-eyepatch.rs:81:20 | LL | dr = Dr("dr", &c); | ^ borrowed value does not live long enough @@ -21,7 +21,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch.rs:90:29 + --> $DIR/dropck-eyepatch.rs:89:29 | LL | pt = Pt("pt", &c_long, &c); | ^ borrowed value does not live long enough @@ -32,7 +32,7 @@ LL | } = note: values in a scope are dropped in the opposite order they are created error[E0597]: `c` does not live long enough - --> $DIR/dropck-eyepatch.rs:92:29 + --> $DIR/dropck-eyepatch.rs:91:29 | LL | pr = Pr("pr", &c_long, &c); | ^ borrowed value does not live long enough @@ -44,4 +44,4 @@ LL | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/e0119/complex-impl.stderr b/src/test/ui/e0119/complex-impl.stderr index b268c7554045..1fc4c28d67c5 100644 --- a/src/test/ui/e0119/complex-impl.stderr +++ b/src/test/ui/e0119/complex-impl.stderr @@ -8,13 +8,15 @@ LL | impl External for (Q, R) {} //~ ERROR must be used - impl<'a, 'b, 'c, T, U, V, W> complex_impl_support::External for (T, complex_impl_support::M<'a, 'b, 'c, std::boxed::Box, V, W>) where >::Output == V, ::Item == T, 'b : 'a, T : 'a, U: std::ops::FnOnce<(T,)>, U : 'static, V: std::iter::Iterator, V: std::clone::Clone, W: std::ops::Add, ::Output: std::marker::Copy; -error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g. `MyStruct`); only traits defined in the current crate can be implemented for a type parameter +error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g. `MyStruct`) --> $DIR/complex-impl.rs:19:1 | LL | impl External for (Q, R) {} //~ ERROR must be used - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `R` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors -You've got a few errors: E0119, E0210 -If you want more information on an error, try using "rustc --explain E0119" +Some errors occurred: E0119, E0210. +For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/e0119/conflict-with-std.rs b/src/test/ui/e0119/conflict-with-std.rs index ed9033ad53d5..a9f747d09ec2 100644 --- a/src/test/ui/e0119/conflict-with-std.rs +++ b/src/test/ui/e0119/conflict-with-std.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(try_from)] - use std::marker::PhantomData; use std::convert::{TryFrom, AsRef}; diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr index ff17643f1210..417ff1de3f81 100644 --- a/src/test/ui/e0119/conflict-with-std.stderr +++ b/src/test/ui/e0119/conflict-with-std.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `std::convert::AsRef` for type `std::boxed::Box`: - --> $DIR/conflict-with-std.rs:17:1 + --> $DIR/conflict-with-std.rs:15:1 | LL | impl AsRef for Box { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | impl AsRef for Box { //~ ERROR conflicting implementations where T: ?Sized; error[E0119]: conflicting implementations of trait `std::convert::From` for type `S`: - --> $DIR/conflict-with-std.rs:24:1 + --> $DIR/conflict-with-std.rs:22:1 | LL | impl From for S { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | impl From for S { //~ ERROR conflicting implementations - impl std::convert::From for T; error[E0119]: conflicting implementations of trait `std::convert::TryFrom` for type `X`: - --> $DIR/conflict-with-std.rs:31:1 + --> $DIR/conflict-with-std.rs:29:1 | LL | impl TryFrom for X { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^^^^ @@ -29,4 +29,4 @@ LL | impl TryFrom for X { //~ ERROR conflicting implementations error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/e0119/issue-23563.stderr b/src/test/ui/e0119/issue-23563.stderr index 9ad866253446..0630b76882e7 100644 --- a/src/test/ui/e0119/issue-23563.stderr +++ b/src/test/ui/e0119/issue-23563.stderr @@ -10,4 +10,4 @@ LL | impl<'a, T> LolFrom<&'a [T]> for LocalType { //~ ERROR conflicting imple error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/e0119/issue-27403.stderr b/src/test/ui/e0119/issue-27403.stderr index 4f4a9e97d6bb..9dea60a72b50 100644 --- a/src/test/ui/e0119/issue-27403.stderr +++ b/src/test/ui/e0119/issue-27403.stderr @@ -10,4 +10,4 @@ LL | impl Into for GenX { //~ ERROR conflicting implementations error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/e0119/issue-28981.stderr b/src/test/ui/e0119/issue-28981.stderr index b1ec1111ede9..afcbab4a5c6c 100644 --- a/src/test/ui/e0119/issue-28981.stderr +++ b/src/test/ui/e0119/issue-28981.stderr @@ -8,13 +8,15 @@ LL | impl Deref for Foo { } //~ ERROR must be used - impl<'a, T> std::ops::Deref for &'a T where T: ?Sized; -error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct`); only traits defined in the current crate can be implemented for a type parameter +error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct`) --> $DIR/issue-28981.rs:15:1 | LL | impl Deref for Foo { } //~ ERROR must be used - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ type parameter `Foo` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter error: aborting due to 2 previous errors -You've got a few errors: E0119, E0210 -If you want more information on an error, try using "rustc --explain E0119" +Some errors occurred: E0119, E0210. +For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/e0119/so-37347311.stderr b/src/test/ui/e0119/so-37347311.stderr index 8be27adc4a2f..6c14b200ee5b 100644 --- a/src/test/ui/e0119/so-37347311.stderr +++ b/src/test/ui/e0119/so-37347311.stderr @@ -9,4 +9,4 @@ LL | impl From for MyError { //~ ERROR conflicting impl error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/empty-struct-unit-expr.stderr b/src/test/ui/empty-struct-unit-expr.stderr index e64f383f91b9..fff696fc80f0 100644 --- a/src/test/ui/empty-struct-unit-expr.stderr +++ b/src/test/ui/empty-struct-unit-expr.stderr @@ -38,4 +38,4 @@ LL | let xe4 = XE::XEmpty4; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0618" +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/enum-and-module-in-same-scope.stderr b/src/test/ui/enum-and-module-in-same-scope.stderr index 86f7ee5bb0e5..230872abe0b3 100644 --- a/src/test/ui/enum-and-module-in-same-scope.stderr +++ b/src/test/ui/enum-and-module-in-same-scope.stderr @@ -11,4 +11,4 @@ LL | mod Foo { //~ ERROR the name `Foo` is defined multiple times error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0428" +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr index c3412e73599b..6a4392df35d8 100644 --- a/src/test/ui/error-codes/E0004-2.stderr +++ b/src/test/ui/error-codes/E0004-2.stderr @@ -12,4 +12,4 @@ LL | match x { } //~ ERROR E0004 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0004" +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/error-codes/E0004.stderr b/src/test/ui/error-codes/E0004.stderr index 56351f80f9d2..cf364a886891 100644 --- a/src/test/ui/error-codes/E0004.stderr +++ b/src/test/ui/error-codes/E0004.stderr @@ -6,4 +6,4 @@ LL | match x { //~ ERROR E0004 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0004" +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index d02817a66755..b321a69805eb 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -6,4 +6,4 @@ LL | let Some(y) = x; //~ ERROR E0005 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0005" +For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/error-codes/E0007.stderr b/src/test/ui/error-codes/E0007.stderr index c5cf140bab50..f662365b8f18 100644 --- a/src/test/ui/error-codes/E0007.stderr +++ b/src/test/ui/error-codes/E0007.stderr @@ -12,5 +12,5 @@ LL | op_string @ Some(s) => {}, error: aborting due to 2 previous errors -You've got a few errors: E0007, E0303 -If you want more information on an error, try using "rustc --explain E0007" +Some errors occurred: E0007, E0303. +For more information about an error, try `rustc --explain E0007`. diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr index cdf6eff0fabb..e9af3166ed5e 100644 --- a/src/test/ui/error-codes/E0008.stderr +++ b/src/test/ui/error-codes/E0008.stderr @@ -6,4 +6,4 @@ LL | Some(s) if s.len() == 0 => {}, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0008" +For more information about this error, try `rustc --explain E0008`. diff --git a/src/test/ui/error-codes/E0009.stderr b/src/test/ui/error-codes/E0009.stderr index ac6c2ace1f8d..8b3071420dd8 100644 --- a/src/test/ui/error-codes/E0009.stderr +++ b/src/test/ui/error-codes/E0009.stderr @@ -8,4 +8,4 @@ LL | Some((y, ref z)) => {}, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0009" +For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/error-codes/E0010-teach.stderr b/src/test/ui/error-codes/E0010-teach.stderr index 0d97a56b1b42..fa5c767caf24 100644 --- a/src/test/ui/error-codes/E0010-teach.stderr +++ b/src/test/ui/error-codes/E0010-teach.stderr @@ -8,4 +8,4 @@ LL | const CON : Box = box 0; //~ ERROR E0010 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0010" +For more information about this error, try `rustc --explain E0010`. diff --git a/src/test/ui/error-codes/E0010.stderr b/src/test/ui/error-codes/E0010.stderr index 0d8b0800b089..83c1b409a517 100644 --- a/src/test/ui/error-codes/E0010.stderr +++ b/src/test/ui/error-codes/E0010.stderr @@ -6,4 +6,4 @@ LL | const CON : Box = box 0; //~ ERROR E0010 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0010" +For more information about this error, try `rustc --explain E0010`. diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr index 540d76a6d450..411b9f313978 100644 --- a/src/test/ui/error-codes/E0017.stderr +++ b/src/test/ui/error-codes/E0017.stderr @@ -24,5 +24,5 @@ LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 error: aborting due to 4 previous errors -You've got a few errors: E0017, E0596 -If you want more information on an error, try using "rustc --explain E0017" +Some errors occurred: E0017, E0596. +For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 2f69db3e7ef1..26f7baeb1a46 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -18,4 +18,4 @@ LL | Fruit::Pear(1, 2) => {}, //~ ERROR E0023 error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0023" +For more information about this error, try `rustc --explain E0023`. diff --git a/src/test/ui/error-codes/E0025.stderr b/src/test/ui/error-codes/E0025.stderr index 2e32ccab0dd3..f60372559a33 100644 --- a/src/test/ui/error-codes/E0025.stderr +++ b/src/test/ui/error-codes/E0025.stderr @@ -8,4 +8,4 @@ LL | let Foo { a: x, a: y, b: 0 } = x; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0025" +For more information about this error, try `rustc --explain E0025`. diff --git a/src/test/ui/error-codes/E0026-teach.stderr b/src/test/ui/error-codes/E0026-teach.stderr index e7ab3fbf307f..67ea32fba86d 100644 --- a/src/test/ui/error-codes/E0026-teach.stderr +++ b/src/test/ui/error-codes/E0026-teach.stderr @@ -2,7 +2,7 @@ error[E0026]: struct `Thing` does not have a field named `z` --> $DIR/E0026-teach.rs:21:23 | LL | Thing { x, y, z } => {} - | ^ struct `Thing` does not have field `z` + | ^ struct `Thing` does not have this field | = note: This error indicates that a struct pattern attempted to extract a non-existent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched. @@ -10,4 +10,4 @@ LL | Thing { x, y, z } => {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0026" +For more information about this error, try `rustc --explain E0026`. diff --git a/src/test/ui/error-codes/E0026.stderr b/src/test/ui/error-codes/E0026.stderr index 9415da2a819f..9dabbc8a775f 100644 --- a/src/test/ui/error-codes/E0026.stderr +++ b/src/test/ui/error-codes/E0026.stderr @@ -2,8 +2,8 @@ error[E0026]: struct `Thing` does not have a field named `z` --> $DIR/E0026.rs:19:23 | LL | Thing { x, y, z } => {} - | ^ struct `Thing` does not have field `z` + | ^ struct `Thing` does not have this field error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0026" +For more information about this error, try `rustc --explain E0026`. diff --git a/src/test/ui/error-codes/E0027-teach.stderr b/src/test/ui/error-codes/E0027-teach.stderr index d9c6a865dad8..1c5333d76a85 100644 --- a/src/test/ui/error-codes/E0027-teach.stderr +++ b/src/test/ui/error-codes/E0027-teach.stderr @@ -8,4 +8,4 @@ LL | Dog { age: x } => {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0027" +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/error-codes/E0027.stderr b/src/test/ui/error-codes/E0027.stderr index 6959324ccdec..208b263e0f89 100644 --- a/src/test/ui/error-codes/E0027.stderr +++ b/src/test/ui/error-codes/E0027.stderr @@ -6,4 +6,4 @@ LL | Dog { age: x } => {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0027" +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/error-codes/E0029-teach.rs b/src/test/ui/error-codes/E0029-teach.rs index ca85f58133cc..1bc2c2d58b19 100644 --- a/src/test/ui/error-codes/E0029-teach.rs +++ b/src/test/ui/error-codes/E0029-teach.rs @@ -16,7 +16,6 @@ fn main() { match s { "hello" ... "world" => {} //~^ ERROR only char and numeric types are allowed in range patterns - //~| ERROR non-reference pattern used to match a reference _ => {} } } diff --git a/src/test/ui/error-codes/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr index d4e9a1c30400..4bb71f68a98b 100644 --- a/src/test/ui/error-codes/E0029-teach.stderr +++ b/src/test/ui/error-codes/E0029-teach.stderr @@ -1,11 +1,3 @@ -error[E0658]: non-reference pattern used to match a reference (see issue #42640) - --> $DIR/E0029-teach.rs:17:9 - | -LL | "hello" ... "world" => {} - | ^^^^^^^^^^^^^^^^^^^ help: consider using a reference: `&"hello" ... "world"` - | - = help: add #![feature(match_default_bindings)] to the crate attributes to enable - error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/E0029-teach.rs:17:9 | @@ -16,7 +8,6 @@ LL | "hello" ... "world" => {} = note: end type: &'static str = note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard. -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0029, E0658 -If you want more information on an error, try using "rustc --explain E0029" +For more information about this error, try `rustc --explain E0029`. diff --git a/src/test/ui/error-codes/E0029.rs b/src/test/ui/error-codes/E0029.rs index 80d215bd327c..29b6fe441135 100644 --- a/src/test/ui/error-codes/E0029.rs +++ b/src/test/ui/error-codes/E0029.rs @@ -14,7 +14,6 @@ fn main() { match s { "hello" ... "world" => {} //~^ ERROR only char and numeric types are allowed in range patterns - //~| ERROR non-reference pattern used to match a reference _ => {} } } diff --git a/src/test/ui/error-codes/E0029.stderr b/src/test/ui/error-codes/E0029.stderr index ab1fa321dbde..bcdfa3871110 100644 --- a/src/test/ui/error-codes/E0029.stderr +++ b/src/test/ui/error-codes/E0029.stderr @@ -1,11 +1,3 @@ -error[E0658]: non-reference pattern used to match a reference (see issue #42640) - --> $DIR/E0029.rs:15:9 - | -LL | "hello" ... "world" => {} - | ^^^^^^^^^^^^^^^^^^^ help: consider using a reference: `&"hello" ... "world"` - | - = help: add #![feature(match_default_bindings)] to the crate attributes to enable - error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/E0029.rs:15:9 | @@ -15,7 +7,6 @@ LL | "hello" ... "world" => {} = note: start type: &'static str = note: end type: &'static str -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0029, E0658 -If you want more information on an error, try using "rustc --explain E0029" +For more information about this error, try `rustc --explain E0029`. diff --git a/src/test/ui/error-codes/E0030-teach.stderr b/src/test/ui/error-codes/E0030-teach.stderr index e23bf89be29b..8b262d5b296b 100644 --- a/src/test/ui/error-codes/E0030-teach.stderr +++ b/src/test/ui/error-codes/E0030-teach.stderr @@ -8,4 +8,4 @@ LL | 1000 ... 5 => {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0030" +For more information about this error, try `rustc --explain E0030`. diff --git a/src/test/ui/error-codes/E0030.stderr b/src/test/ui/error-codes/E0030.stderr index 9d4352888cb8..0949cfb50b68 100644 --- a/src/test/ui/error-codes/E0030.stderr +++ b/src/test/ui/error-codes/E0030.stderr @@ -6,4 +6,4 @@ LL | 1000 ... 5 => {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0030" +For more information about this error, try `rustc --explain E0030`. diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index 9f2a9595b390..c74485781c12 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -24,5 +24,5 @@ LL | let &invalid = trait_obj; error: aborting due to 3 previous errors -You've got a few errors: E0033, E0038, E0423 -If you want more information on an error, try using "rustc --explain E0033" +Some errors occurred: E0033, E0038, E0423. +For more information about an error, try `rustc --explain E0033`. diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index a0d73c074f82..a1e72d6f6695 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -20,5 +20,5 @@ LL | let &invalid = trait_obj; error: aborting due to 3 previous errors -You've got a few errors: E0033, E0038, E0423 -If you want more information on an error, try using "rustc --explain E0033" +Some errors occurred: E0033, E0038, E0423. +For more information about an error, try `rustc --explain E0033`. diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr index f457dfded7cd..cec0f2d2a80b 100644 --- a/src/test/ui/error-codes/E0034.stderr +++ b/src/test/ui/error-codes/E0034.stderr @@ -17,4 +17,4 @@ LL | fn foo() {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0034" +For more information about this error, try `rustc --explain E0034`. diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index b3f3ea57a346..bc76323f1839 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -8,4 +8,4 @@ LL | fn call_foo(x: Box) { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/error-codes/E0040.stderr b/src/test/ui/error-codes/E0040.stderr index a2f6174e9185..01636ae98b81 100644 --- a/src/test/ui/error-codes/E0040.stderr +++ b/src/test/ui/error-codes/E0040.stderr @@ -6,4 +6,4 @@ LL | x.drop(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0040" +For more information about this error, try `rustc --explain E0040`. diff --git a/src/test/ui/error-codes/E0044.rs b/src/test/ui/error-codes/E0044.rs index 48fe23000312..35e3c7685589 100644 --- a/src/test/ui/error-codes/E0044.rs +++ b/src/test/ui/error-codes/E0044.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern { fn some_func(x: T); } //~ ERROR E0044 +extern { + fn sqrt(f: T) -> T; + //~^ ERROR foreign items may not have type parameters [E0044] + //~| HELP use specialization instead of type parameters by replacing them with concrete types + //~| NOTE can't have type parameters +} fn main() { } diff --git a/src/test/ui/error-codes/E0044.stderr b/src/test/ui/error-codes/E0044.stderr index b823f3717b35..ce966251bf45 100644 --- a/src/test/ui/error-codes/E0044.stderr +++ b/src/test/ui/error-codes/E0044.stderr @@ -1,15 +1,11 @@ error[E0044]: foreign items may not have type parameters - --> $DIR/E0044.rs:11:10 + --> $DIR/E0044.rs:12:5 | -LL | extern { fn some_func(x: T); } //~ ERROR E0044 - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn sqrt(f: T) -> T; + | ^^^^^^^^^^^^^^^^^^^^^^ can't have type parameters | -help: consider using specialization instead of type parameters - --> $DIR/E0044.rs:11:10 - | -LL | extern { fn some_func(x: T); } //~ ERROR E0044 - | ^^^^^^^^^^^^^^^^^^^^^^ + = help: use specialization instead of type parameters by replacing them with concrete types like `u32` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0044" +For more information about this error, try `rustc --explain E0044`. diff --git a/src/test/ui/error-codes/E0045.stderr b/src/test/ui/error-codes/E0045.stderr index e79965aeff78..35a592a69860 100644 --- a/src/test/ui/error-codes/E0045.stderr +++ b/src/test/ui/error-codes/E0045.stderr @@ -6,4 +6,4 @@ LL | extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0045" +For more information about this error, try `rustc --explain E0045`. diff --git a/src/test/ui/error-codes/E0049.stderr b/src/test/ui/error-codes/E0049.stderr index cdc936df2704..b7eaad570438 100644 --- a/src/test/ui/error-codes/E0049.stderr +++ b/src/test/ui/error-codes/E0049.stderr @@ -9,4 +9,4 @@ LL | fn foo(x: bool) -> Self { Bar } //~ ERROR E0049 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0049" +For more information about this error, try `rustc --explain E0049`. diff --git a/src/test/ui/error-codes/E0050.stderr b/src/test/ui/error-codes/E0050.stderr index d5d1677f43f4..bff3b7b16b91 100644 --- a/src/test/ui/error-codes/E0050.stderr +++ b/src/test/ui/error-codes/E0050.stderr @@ -27,4 +27,4 @@ LL | fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050 error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0050" +For more information about this error, try `rustc --explain E0050`. diff --git a/src/test/ui/error-codes/E0054.stderr b/src/test/ui/error-codes/E0054.stderr index ed82704e6611..d5cf18460fd8 100644 --- a/src/test/ui/error-codes/E0054.stderr +++ b/src/test/ui/error-codes/E0054.stderr @@ -8,4 +8,4 @@ LL | let x_is_nonzero = x as bool; //~ ERROR E0054 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0054" +For more information about this error, try `rustc --explain E0054`. diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr index 3d13b1441062..9653f4eaeefd 100644 --- a/src/test/ui/error-codes/E0055.stderr +++ b/src/test/ui/error-codes/E0055.stderr @@ -8,4 +8,4 @@ LL | ref_foo.foo(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0055" +For more information about this error, try `rustc --explain E0055`. diff --git a/src/test/ui/error-codes/E0057.stderr b/src/test/ui/error-codes/E0057.stderr index 0d6cd77de070..fb3e710b8cf9 100644 --- a/src/test/ui/error-codes/E0057.stderr +++ b/src/test/ui/error-codes/E0057.stderr @@ -12,4 +12,4 @@ LL | let c = f(2, 3); //~ ERROR E0057 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0057" +For more information about this error, try `rustc --explain E0057`. diff --git a/src/test/ui/error-codes/E0059.stderr b/src/test/ui/error-codes/E0059.stderr index 5e2907eed692..abe8b729c93b 100644 --- a/src/test/ui/error-codes/E0059.stderr +++ b/src/test/ui/error-codes/E0059.stderr @@ -6,4 +6,4 @@ LL | fn foo>(f: F) -> F::Output { f(3) } //~ ERROR E0059 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0059" +For more information about this error, try `rustc --explain E0059`. diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr index 0493015cc765..c6aac6e41c62 100644 --- a/src/test/ui/error-codes/E0060.stderr +++ b/src/test/ui/error-codes/E0060.stderr @@ -9,4 +9,4 @@ LL | unsafe { printf(); } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0060" +For more information about this error, try `rustc --explain E0060`. diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr index 6ddd4be9d8e2..d5842a18bc8b 100644 --- a/src/test/ui/error-codes/E0061.stderr +++ b/src/test/ui/error-codes/E0061.stderr @@ -18,4 +18,4 @@ LL | f2(); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/error-codes/E0062.stderr b/src/test/ui/error-codes/E0062.stderr index a24c5e059147..c5c38c6f5ffe 100644 --- a/src/test/ui/error-codes/E0062.stderr +++ b/src/test/ui/error-codes/E0062.stderr @@ -8,4 +8,4 @@ LL | x: 0, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0062" +For more information about this error, try `rustc --explain E0062`. diff --git a/src/test/ui/error-codes/E0063.stderr b/src/test/ui/error-codes/E0063.stderr index 7f33223a7ea1..1ed54b4e7ba6 100644 --- a/src/test/ui/error-codes/E0063.stderr +++ b/src/test/ui/error-codes/E0063.stderr @@ -24,4 +24,4 @@ LL | let z = TruncatedPluralFoo{x:1}; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0063" +For more information about this error, try `rustc --explain E0063`. diff --git a/src/test/ui/error-codes/E0067.stderr b/src/test/ui/error-codes/E0067.stderr index b964b9dffc1f..76f06c7c4637 100644 --- a/src/test/ui/error-codes/E0067.stderr +++ b/src/test/ui/error-codes/E0067.stderr @@ -14,5 +14,5 @@ LL | LinkedList::new() += 1; //~ ERROR E0368 error: aborting due to 2 previous errors -You've got a few errors: E0067, E0368 -If you want more information on an error, try using "rustc --explain E0067" +Some errors occurred: E0067, E0368. +For more information about an error, try `rustc --explain E0067`. diff --git a/src/test/ui/error-codes/E0069.stderr b/src/test/ui/error-codes/E0069.stderr index 8a5b5984c33d..0ba1ed456635 100644 --- a/src/test/ui/error-codes/E0069.stderr +++ b/src/test/ui/error-codes/E0069.stderr @@ -6,4 +6,4 @@ LL | return; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0069" +For more information about this error, try `rustc --explain E0069`. diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index 33da9030c41d..892e6943112f 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -27,5 +27,5 @@ LL | some_other_func() = 4; //~ ERROR E0070 error: aborting due to 4 previous errors -You've got a few errors: E0070, E0308 -If you want more information on an error, try using "rustc --explain E0070" +Some errors occurred: E0070, E0308. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/error-codes/E0071.stderr b/src/test/ui/error-codes/E0071.stderr index b28dcf90c82f..637338672e0b 100644 --- a/src/test/ui/error-codes/E0071.stderr +++ b/src/test/ui/error-codes/E0071.stderr @@ -6,4 +6,4 @@ LL | let u = FooAlias { value: 0 }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0071" +For more information about this error, try `rustc --explain E0071`. diff --git a/src/test/ui/error-codes/E0075.stderr b/src/test/ui/error-codes/E0075.stderr index 4fd5b65f4a9c..d29d5d788036 100644 --- a/src/test/ui/error-codes/E0075.stderr +++ b/src/test/ui/error-codes/E0075.stderr @@ -6,4 +6,4 @@ LL | struct Bad; //~ ERROR E0075 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0075" +For more information about this error, try `rustc --explain E0075`. diff --git a/src/test/ui/error-codes/E0076.stderr b/src/test/ui/error-codes/E0076.stderr index 3cee6f4527cb..ae3494038109 100644 --- a/src/test/ui/error-codes/E0076.stderr +++ b/src/test/ui/error-codes/E0076.stderr @@ -6,4 +6,4 @@ LL | struct Bad(u16, u32, u32); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0076" +For more information about this error, try `rustc --explain E0076`. diff --git a/src/test/ui/error-codes/E0077.stderr b/src/test/ui/error-codes/E0077.stderr index 822efe9628bc..42a169f5a20a 100644 --- a/src/test/ui/error-codes/E0077.stderr +++ b/src/test/ui/error-codes/E0077.stderr @@ -6,4 +6,4 @@ LL | struct Bad(String); //~ ERROR E0077 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0077" +For more information about this error, try `rustc --explain E0077`. diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr index 6db53acd6b98..500e0e83a55f 100644 --- a/src/test/ui/error-codes/E0080.stderr +++ b/src/test/ui/error-codes/E0080.stderr @@ -34,4 +34,4 @@ LL | Y = (1 / 0) //~ ERROR E0080 error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr index e1133c1fc587..36150d7c5263 100644 --- a/src/test/ui/error-codes/E0081.stderr +++ b/src/test/ui/error-codes/E0081.stderr @@ -8,4 +8,4 @@ LL | X = 3, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0081" +For more information about this error, try `rustc --explain E0081`. diff --git a/src/test/ui/error-codes/E0084.stderr b/src/test/ui/error-codes/E0084.stderr index 5ebe03090a0a..d0bc519c9969 100644 --- a/src/test/ui/error-codes/E0084.stderr +++ b/src/test/ui/error-codes/E0084.stderr @@ -8,4 +8,4 @@ LL | enum Foo {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0084" +For more information about this error, try `rustc --explain E0084`. diff --git a/src/test/ui/error-codes/E0087.stderr b/src/test/ui/error-codes/E0087.stderr index b1ff92d8c276..cd1e99e7b411 100644 --- a/src/test/ui/error-codes/E0087.stderr +++ b/src/test/ui/error-codes/E0087.stderr @@ -12,4 +12,4 @@ LL | bar::(); //~ ERROR expected at most 1 type parameter, found 2 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0087" +For more information about this error, try `rustc --explain E0087`. diff --git a/src/test/ui/error-codes/E0088.stderr b/src/test/ui/error-codes/E0088.stderr index 5497eb028d86..4bf2760994eb 100644 --- a/src/test/ui/error-codes/E0088.stderr +++ b/src/test/ui/error-codes/E0088.stderr @@ -12,4 +12,4 @@ LL | g::<'static, 'static>(); //~ ERROR E0088 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0088" +For more information about this error, try `rustc --explain E0088`. diff --git a/src/test/ui/error-codes/E0089.stderr b/src/test/ui/error-codes/E0089.stderr index 3a3990879433..0b95033fb360 100644 --- a/src/test/ui/error-codes/E0089.stderr +++ b/src/test/ui/error-codes/E0089.stderr @@ -6,4 +6,4 @@ LL | foo::(); //~ ERROR expected 2 type parameters, found 1 type parame error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0089" +For more information about this error, try `rustc --explain E0089`. diff --git a/src/test/ui/error-codes/E0090.stderr b/src/test/ui/error-codes/E0090.stderr index 82e8eaf69ea2..f119d5fa4671 100644 --- a/src/test/ui/error-codes/E0090.stderr +++ b/src/test/ui/error-codes/E0090.stderr @@ -6,4 +6,4 @@ LL | foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lif error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0090" +For more information about this error, try `rustc --explain E0090`. diff --git a/src/test/ui/error-codes/E0091.stderr b/src/test/ui/error-codes/E0091.stderr index 003e9e7efcd1..2116f8f64760 100644 --- a/src/test/ui/error-codes/E0091.stderr +++ b/src/test/ui/error-codes/E0091.stderr @@ -12,4 +12,4 @@ LL | type Foo2 = Box; //~ ERROR E0091 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0091" +For more information about this error, try `rustc --explain E0091`. diff --git a/src/test/ui/error-codes/E0092.stderr b/src/test/ui/error-codes/E0092.stderr index 8b53a029c35d..50d6d63b99c2 100644 --- a/src/test/ui/error-codes/E0092.stderr +++ b/src/test/ui/error-codes/E0092.stderr @@ -6,4 +6,4 @@ LL | fn atomic_foo(); //~ ERROR E0092 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0092" +For more information about this error, try `rustc --explain E0092`. diff --git a/src/test/ui/error-codes/E0093.stderr b/src/test/ui/error-codes/E0093.stderr index 4e2016508376..f261b83a0b88 100644 --- a/src/test/ui/error-codes/E0093.stderr +++ b/src/test/ui/error-codes/E0093.stderr @@ -6,4 +6,4 @@ LL | fn foo(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0093" +For more information about this error, try `rustc --explain E0093`. diff --git a/src/test/ui/error-codes/E0094.stderr b/src/test/ui/error-codes/E0094.stderr index 7a2dfaae279e..322802fc44f0 100644 --- a/src/test/ui/error-codes/E0094.stderr +++ b/src/test/ui/error-codes/E0094.stderr @@ -6,4 +6,4 @@ LL | fn size_of() -> usize; //~ ERROR E0094 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0094" +For more information about this error, try `rustc --explain E0094`. diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr index 645414ca1ea3..9862dca3fdef 100644 --- a/src/test/ui/error-codes/E0106.stderr +++ b/src/test/ui/error-codes/E0106.stderr @@ -30,4 +30,4 @@ LL | buzz: Buzz, error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0106" +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/error-codes/E0107.stderr b/src/test/ui/error-codes/E0107.stderr index a695a593429a..76bb2667643e 100644 --- a/src/test/ui/error-codes/E0107.stderr +++ b/src/test/ui/error-codes/E0107.stderr @@ -18,4 +18,4 @@ LL | foo2: Foo<'a, 'b, 'c>, error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0107" +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr index 89f3154fb48b..6473517bfada 100644 --- a/src/test/ui/error-codes/E0109.stderr +++ b/src/test/ui/error-codes/E0109.stderr @@ -6,4 +6,4 @@ LL | type X = u32; //~ ERROR E0109 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0109" +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr index 3f4d525b6e50..10e06ee6d025 100644 --- a/src/test/ui/error-codes/E0110.stderr +++ b/src/test/ui/error-codes/E0110.stderr @@ -6,4 +6,4 @@ LL | type X = u32<'static>; //~ ERROR E0110 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0110" +For more information about this error, try `rustc --explain E0110`. diff --git a/src/test/ui/error-codes/E0116.stderr b/src/test/ui/error-codes/E0116.stderr index 88954b906c46..7c2f35a3305e 100644 --- a/src/test/ui/error-codes/E0116.stderr +++ b/src/test/ui/error-codes/E0116.stderr @@ -8,4 +8,4 @@ LL | impl Vec {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0116" +For more information about this error, try `rustc --explain E0116`. diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr index 240aa4240cc6..045ae700955d 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -8,12 +8,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar --> $DIR/E0117.rs:11:1 | LL | impl Drop for u32 {} //~ ERROR E0117 - | ^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead error: aborting due to 2 previous errors -You've got a few errors: E0117, E0120 -If you want more information on an error, try using "rustc --explain E0117" +Some errors occurred: E0117, E0120. +For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr index bb811ab6345e..896213e34874 100644 --- a/src/test/ui/error-codes/E0118.stderr +++ b/src/test/ui/error-codes/E0118.stderr @@ -8,4 +8,4 @@ LL | impl (u8, u8) { //~ ERROR E0118 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0118" +For more information about this error, try `rustc --explain E0118`. diff --git a/src/test/ui/error-codes/E0119.stderr b/src/test/ui/error-codes/E0119.stderr index 55ca8c5a7796..f1e942d4cf53 100644 --- a/src/test/ui/error-codes/E0119.stderr +++ b/src/test/ui/error-codes/E0119.stderr @@ -9,4 +9,4 @@ LL | impl MyTrait for Foo { //~ ERROR E0119 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr index cd69b8d67bf9..6237500c7ae3 100644 --- a/src/test/ui/error-codes/E0120.stderr +++ b/src/test/ui/error-codes/E0120.stderr @@ -6,4 +6,4 @@ LL | impl Drop for MyTrait { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0120" +For more information about this error, try `rustc --explain E0120`. diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index ca9557cdcdc4..019e637aa8c5 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -12,4 +12,4 @@ LL | static BAR: _ = "test"; //~ ERROR E0121 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0121" +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/error-codes/E0124.stderr b/src/test/ui/error-codes/E0124.stderr index 1f4b4ce0efae..c95162c9d214 100644 --- a/src/test/ui/error-codes/E0124.stderr +++ b/src/test/ui/error-codes/E0124.stderr @@ -8,4 +8,4 @@ LL | field1: i32, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0124" +For more information about this error, try `rustc --explain E0124`. diff --git a/src/test/ui/error-codes/E0128.stderr b/src/test/ui/error-codes/E0128.stderr index 632b11967232..81da580f0d51 100644 --- a/src/test/ui/error-codes/E0128.stderr +++ b/src/test/ui/error-codes/E0128.stderr @@ -6,4 +6,4 @@ LL | struct Foo { //~ ERROR E0128 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0128" +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/error-codes/E0130.stderr b/src/test/ui/error-codes/E0130.stderr index 3e00909109b5..3b54b1b86698 100644 --- a/src/test/ui/error-codes/E0130.stderr +++ b/src/test/ui/error-codes/E0130.stderr @@ -6,4 +6,4 @@ LL | fn foo((a, b): (u32, u32)); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0130" +For more information about this error, try `rustc --explain E0130`. diff --git a/src/test/ui/error-codes/E0131.stderr b/src/test/ui/error-codes/E0131.stderr index b9caca22aeb1..3774e21c2143 100644 --- a/src/test/ui/error-codes/E0131.stderr +++ b/src/test/ui/error-codes/E0131.stderr @@ -6,4 +6,4 @@ LL | fn main() { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0131" +For more information about this error, try `rustc --explain E0131`. diff --git a/src/test/ui/error-codes/E0132.stderr b/src/test/ui/error-codes/E0132.stderr index ce22a99e66c8..80d1c29d50f9 100644 --- a/src/test/ui/error-codes/E0132.stderr +++ b/src/test/ui/error-codes/E0132.stderr @@ -6,4 +6,4 @@ LL | fn f< T >() {} //~ ERROR E0132 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0132" +For more information about this error, try `rustc --explain E0132`. diff --git a/src/test/ui/error-codes/E0133.stderr b/src/test/ui/error-codes/E0133.stderr index d703ce6203ef..dc57a6274445 100644 --- a/src/test/ui/error-codes/E0133.stderr +++ b/src/test/ui/error-codes/E0133.stderr @@ -6,4 +6,4 @@ LL | f(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0133" +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/error-codes/E0137.stderr b/src/test/ui/error-codes/E0137.stderr index 4a5b4f6da86a..ab2f9ba5bea9 100644 --- a/src/test/ui/error-codes/E0137.stderr +++ b/src/test/ui/error-codes/E0137.stderr @@ -9,4 +9,4 @@ LL | fn f() {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0137" +For more information about this error, try `rustc --explain E0137`. diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr index 40b476afb9af..e713b11b37fe 100644 --- a/src/test/ui/error-codes/E0138.stderr +++ b/src/test/ui/error-codes/E0138.stderr @@ -9,4 +9,4 @@ LL | fn f(argc: isize, argv: *const *const u8) -> isize { 0 } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0138" +For more information about this error, try `rustc --explain E0138`. diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr index 99a9b85f41e2..f67022bd6d3f 100644 --- a/src/test/ui/error-codes/E0152.stderr +++ b/src/test/ui/error-codes/E0152.stderr @@ -8,4 +8,4 @@ LL | struct Foo; //~ ERROR E0152 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0152" +For more information about this error, try `rustc --explain E0152`. diff --git a/src/test/ui/error-codes/E0161.stderr b/src/test/ui/error-codes/E0161.stderr index fb8f3e0e1683..0135e495c16b 100644 --- a/src/test/ui/error-codes/E0161.stderr +++ b/src/test/ui/error-codes/E0161.stderr @@ -12,5 +12,5 @@ LL | let _x: Box = box *"hello"; //~ ERROR E0161 error: aborting due to 2 previous errors -You've got a few errors: E0161, E0507 -If you want more information on an error, try using "rustc --explain E0161" +Some errors occurred: E0161, E0507. +For more information about an error, try `rustc --explain E0161`. diff --git a/src/test/ui/error-codes/E0162.stderr b/src/test/ui/error-codes/E0162.stderr index e9a7b18fcdd9..91f402dad59b 100644 --- a/src/test/ui/error-codes/E0162.stderr +++ b/src/test/ui/error-codes/E0162.stderr @@ -6,4 +6,4 @@ LL | if let Irrefutable(x) = irr { //~ ERROR E0162 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0162" +For more information about this error, try `rustc --explain E0162`. diff --git a/src/test/ui/error-codes/E0164.stderr b/src/test/ui/error-codes/E0164.stderr index ec91d9b52a95..6eabace9b141 100644 --- a/src/test/ui/error-codes/E0164.stderr +++ b/src/test/ui/error-codes/E0164.stderr @@ -6,4 +6,4 @@ LL | Foo::B(i) => i, //~ ERROR E0164 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0164" +For more information about this error, try `rustc --explain E0164`. diff --git a/src/test/ui/error-codes/E0165.stderr b/src/test/ui/error-codes/E0165.stderr index ac6a88483ec5..66be95e38d2a 100644 --- a/src/test/ui/error-codes/E0165.stderr +++ b/src/test/ui/error-codes/E0165.stderr @@ -6,4 +6,4 @@ LL | while let Irrefutable(x) = irr { //~ ERROR E0165 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0165" +For more information about this error, try `rustc --explain E0165`. diff --git a/src/test/ui/error-codes/E0184.stderr b/src/test/ui/error-codes/E0184.stderr index bd67ed110646..eb6160bc0059 100644 --- a/src/test/ui/error-codes/E0184.stderr +++ b/src/test/ui/error-codes/E0184.stderr @@ -6,4 +6,4 @@ LL | #[derive(Copy)] //~ ERROR E0184 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0184" +For more information about this error, try `rustc --explain E0184`. diff --git a/src/test/ui/error-codes/E0185.stderr b/src/test/ui/error-codes/E0185.stderr index 12ecf25811e9..e5c92abc521b 100644 --- a/src/test/ui/error-codes/E0185.stderr +++ b/src/test/ui/error-codes/E0185.stderr @@ -9,4 +9,4 @@ LL | fn foo(&self) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0185" +For more information about this error, try `rustc --explain E0185`. diff --git a/src/test/ui/error-codes/E0186.stderr b/src/test/ui/error-codes/E0186.stderr index 015c6e5d0bc8..0556ef700ac1 100644 --- a/src/test/ui/error-codes/E0186.stderr +++ b/src/test/ui/error-codes/E0186.stderr @@ -9,4 +9,4 @@ LL | fn foo() {} //~ ERROR E0186 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0186" +For more information about this error, try `rustc --explain E0186`. diff --git a/src/test/ui/error-codes/E0191.stderr b/src/test/ui/error-codes/E0191.stderr index 14ae4469f12a..08b0a845814d 100644 --- a/src/test/ui/error-codes/E0191.stderr +++ b/src/test/ui/error-codes/E0191.stderr @@ -6,4 +6,4 @@ LL | type Foo = Trait; //~ ERROR E0191 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0191" +For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/error-codes/E0192.stderr b/src/test/ui/error-codes/E0192.stderr index 1b2d6eb0285f..fd8976271a51 100644 --- a/src/test/ui/error-codes/E0192.stderr +++ b/src/test/ui/error-codes/E0192.stderr @@ -6,4 +6,4 @@ LL | impl !Trait for Foo { } //~ ERROR E0192 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0192" +For more information about this error, try `rustc --explain E0192`. diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr index 9447b90355e9..6869f3c96f77 100644 --- a/src/test/ui/error-codes/E0194.stderr +++ b/src/test/ui/error-codes/E0194.stderr @@ -9,4 +9,4 @@ LL | fn do_something_else(&self, bar: T); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0194" +For more information about this error, try `rustc --explain E0194`. diff --git a/src/test/ui/error-codes/E0195.stderr b/src/test/ui/error-codes/E0195.stderr index 735aa4283ec3..f2cf661830d8 100644 --- a/src/test/ui/error-codes/E0195.stderr +++ b/src/test/ui/error-codes/E0195.stderr @@ -9,4 +9,4 @@ LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0195" +For more information about this error, try `rustc --explain E0195`. diff --git a/src/test/ui/error-codes/E0197.stderr b/src/test/ui/error-codes/E0197.stderr index 250101929eec..a18599e4f470 100644 --- a/src/test/ui/error-codes/E0197.stderr +++ b/src/test/ui/error-codes/E0197.stderr @@ -6,4 +6,4 @@ LL | unsafe impl Foo { } //~ ERROR E0197 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0197" +For more information about this error, try `rustc --explain E0197`. diff --git a/src/test/ui/error-codes/E0198.stderr b/src/test/ui/error-codes/E0198.stderr index 12120658d611..41ea0565cccb 100644 --- a/src/test/ui/error-codes/E0198.stderr +++ b/src/test/ui/error-codes/E0198.stderr @@ -6,4 +6,4 @@ LL | unsafe impl !Send for Foo { } //~ ERROR E0198 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0198" +For more information about this error, try `rustc --explain E0198`. diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr index 826d13a7a0ec..b3cfd0d21ddb 100644 --- a/src/test/ui/error-codes/E0199.stderr +++ b/src/test/ui/error-codes/E0199.stderr @@ -6,4 +6,4 @@ LL | unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not u error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0199" +For more information about this error, try `rustc --explain E0199`. diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr index 30731712045a..07f848b501e8 100644 --- a/src/test/ui/error-codes/E0200.stderr +++ b/src/test/ui/error-codes/E0200.stderr @@ -6,4 +6,4 @@ LL | impl Bar for Foo { } //~ ERROR E0200 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0200" +For more information about this error, try `rustc --explain E0200`. diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr index 730453c416e5..2b9e51f76fdd 100644 --- a/src/test/ui/error-codes/E0201.stderr +++ b/src/test/ui/error-codes/E0201.stderr @@ -25,4 +25,4 @@ LL | type Quux = u32; //~ ERROR E0201 error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0201" +For more information about this error, try `rustc --explain E0201`. diff --git a/src/test/ui/error-codes/E0206.rs b/src/test/ui/error-codes/E0206.rs index da0370b301b5..9b3d1b351ddd 100644 --- a/src/test/ui/error-codes/E0206.rs +++ b/src/test/ui/error-codes/E0206.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type Foo = i32; +type Foo = [u8; 256]; impl Copy for Foo { } //~^ ERROR the trait `Copy` may not be implemented for this type @@ -17,7 +17,7 @@ impl Copy for Foo { } #[derive(Copy, Clone)] struct Bar; -impl Copy for &'static Bar { } +impl Copy for &'static mut Bar { } //~^ ERROR the trait `Copy` may not be implemented for this type fn main() { diff --git a/src/test/ui/error-codes/E0206.stderr b/src/test/ui/error-codes/E0206.stderr index 0cd22a454e12..f2c23b0767af 100644 --- a/src/test/ui/error-codes/E0206.stderr +++ b/src/test/ui/error-codes/E0206.stderr @@ -7,19 +7,19 @@ LL | impl Copy for Foo { } error[E0206]: the trait `Copy` may not be implemented for this type --> $DIR/E0206.rs:20:15 | -LL | impl Copy for &'static Bar { } - | ^^^^^^^^^^^^ type is not a structure or enumeration +LL | impl Copy for &'static mut Bar { } + | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/E0206.rs:13:1 | LL | impl Copy for Foo { } - | ^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate | = note: the impl does not reference any types defined in this crate = note: define and implement a trait or new type instead error: aborting due to 3 previous errors -You've got a few errors: E0117, E0206 -If you want more information on an error, try using "rustc --explain E0117" +Some errors occurred: E0117, E0206. +For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/error-codes/E0207.stderr b/src/test/ui/error-codes/E0207.stderr index e1f8a68583fa..6ecab44878d9 100644 --- a/src/test/ui/error-codes/E0207.stderr +++ b/src/test/ui/error-codes/E0207.stderr @@ -6,4 +6,4 @@ LL | impl Foo { //~ ERROR E0207 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0207" +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr index 5fd3278dc883..c88e2d2077af 100644 --- a/src/test/ui/error-codes/E0214.stderr +++ b/src/test/ui/error-codes/E0214.stderr @@ -6,4 +6,4 @@ LL | let v: Vec(&str) = vec!["foo"]; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0214" +For more information about this error, try `rustc --explain E0214`. diff --git a/src/test/ui/error-codes/E0220.stderr b/src/test/ui/error-codes/E0220.stderr index 7a4f730c725a..c8a587f2b535 100644 --- a/src/test/ui/error-codes/E0220.stderr +++ b/src/test/ui/error-codes/E0220.stderr @@ -12,5 +12,5 @@ LL | type Foo = Trait; //~ ERROR E0220 error: aborting due to 2 previous errors -You've got a few errors: E0191, E0220 -If you want more information on an error, try using "rustc --explain E0191" +Some errors occurred: E0191, E0220. +For more information about an error, try `rustc --explain E0191`. diff --git a/src/test/ui/error-codes/E0221.stderr b/src/test/ui/error-codes/E0221.stderr index 07ce53e3b58c..fc9232e85ab4 100644 --- a/src/test/ui/error-codes/E0221.stderr +++ b/src/test/ui/error-codes/E0221.stderr @@ -27,4 +27,4 @@ LL | let _: Self::Err; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0221" +For more information about this error, try `rustc --explain E0221`. diff --git a/src/test/ui/error-codes/E0223.stderr b/src/test/ui/error-codes/E0223.stderr index 9df8c8975e55..f65e744c6259 100644 --- a/src/test/ui/error-codes/E0223.stderr +++ b/src/test/ui/error-codes/E0223.stderr @@ -8,4 +8,4 @@ LL | let foo: MyTrait::X; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0223" +For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index 8894791a2db6..6b9489c74c8a 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -6,4 +6,4 @@ LL | let _: Box; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0225" +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/error-codes/E0229.stderr b/src/test/ui/error-codes/E0229.stderr index 202007a6c7cb..218faf2dfdd6 100644 --- a/src/test/ui/error-codes/E0229.stderr +++ b/src/test/ui/error-codes/E0229.stderr @@ -6,4 +6,4 @@ LL | fn baz(x: &>::A) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0229" +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/error-codes/E0232.stderr b/src/test/ui/error-codes/E0232.stderr index 84f5e45bff78..cb6cc44a7359 100644 --- a/src/test/ui/error-codes/E0232.stderr +++ b/src/test/ui/error-codes/E0232.stderr @@ -8,4 +8,4 @@ LL | #[rustc_on_unimplemented] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0232" +For more information about this error, try `rustc --explain E0232`. diff --git a/src/test/ui/error-codes/E0243.stderr b/src/test/ui/error-codes/E0243.stderr index 26c19707fa8e..0477d1b844a1 100644 --- a/src/test/ui/error-codes/E0243.stderr +++ b/src/test/ui/error-codes/E0243.stderr @@ -6,4 +6,4 @@ LL | struct Bar { x: Foo } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0243" +For more information about this error, try `rustc --explain E0243`. diff --git a/src/test/ui/error-codes/E0244.stderr b/src/test/ui/error-codes/E0244.stderr index 078c8e592615..e32397039625 100644 --- a/src/test/ui/error-codes/E0244.stderr +++ b/src/test/ui/error-codes/E0244.stderr @@ -6,4 +6,4 @@ LL | struct Bar { x: Foo } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0244" +For more information about this error, try `rustc --explain E0244`. diff --git a/src/test/ui/error-codes/E0252.stderr b/src/test/ui/error-codes/E0252.stderr index 8186c4590f08..a4271bf3a4df 100644 --- a/src/test/ui/error-codes/E0252.stderr +++ b/src/test/ui/error-codes/E0252.stderr @@ -14,4 +14,4 @@ LL | use bar::baz as other_baz; //~ ERROR E0252 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0252" +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/error-codes/E0253.stderr b/src/test/ui/error-codes/E0253.stderr index 74e17e2aa957..9ab6c30eaa01 100644 --- a/src/test/ui/error-codes/E0253.stderr +++ b/src/test/ui/error-codes/E0253.stderr @@ -6,4 +6,4 @@ LL | use foo::MyTrait::do_something; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0253" +For more information about this error, try `rustc --explain E0253`. diff --git a/src/test/ui/error-codes/E0254.stderr b/src/test/ui/error-codes/E0254.stderr index f1e1b56a790d..a52215df0bbc 100644 --- a/src/test/ui/error-codes/E0254.stderr +++ b/src/test/ui/error-codes/E0254.stderr @@ -15,4 +15,4 @@ LL | use foo::alloc as other_alloc; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0254" +For more information about this error, try `rustc --explain E0254`. diff --git a/src/test/ui/error-codes/E0255.stderr b/src/test/ui/error-codes/E0255.stderr index 4d4053b1fb69..a077a43c152f 100644 --- a/src/test/ui/error-codes/E0255.stderr +++ b/src/test/ui/error-codes/E0255.stderr @@ -15,4 +15,4 @@ LL | use bar::foo as other_foo; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0255" +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/error-codes/E0259.stderr b/src/test/ui/error-codes/E0259.stderr index 2cdd9aa66835..24a73544a35f 100644 --- a/src/test/ui/error-codes/E0259.stderr +++ b/src/test/ui/error-codes/E0259.stderr @@ -14,4 +14,4 @@ LL | extern crate libc as alloc; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0259" +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/error-codes/E0260.stderr b/src/test/ui/error-codes/E0260.stderr index a249c80ea2c6..437794432b08 100644 --- a/src/test/ui/error-codes/E0260.stderr +++ b/src/test/ui/error-codes/E0260.stderr @@ -15,4 +15,4 @@ LL | extern crate alloc as other_alloc; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0260" +For more information about this error, try `rustc --explain E0260`. diff --git a/src/test/ui/error-codes/E0261.stderr b/src/test/ui/error-codes/E0261.stderr index a12878ab8964..e9140ec2c748 100644 --- a/src/test/ui/error-codes/E0261.stderr +++ b/src/test/ui/error-codes/E0261.stderr @@ -12,4 +12,4 @@ LL | x: &'a str, //~ ERROR E0261 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0261" +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/error-codes/E0262.stderr b/src/test/ui/error-codes/E0262.stderr index 8e9327b29f7b..1e5b5db692d8 100644 --- a/src/test/ui/error-codes/E0262.stderr +++ b/src/test/ui/error-codes/E0262.stderr @@ -6,4 +6,4 @@ LL | fn foo<'static>(x: &'static str) { } //~ ERROR E0262 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0262" +For more information about this error, try `rustc --explain E0262`. diff --git a/src/test/ui/error-codes/E0263.stderr b/src/test/ui/error-codes/E0263.stderr index 9cd41bed9845..1b52deea88d4 100644 --- a/src/test/ui/error-codes/E0263.stderr +++ b/src/test/ui/error-codes/E0263.stderr @@ -8,4 +8,4 @@ LL | fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0263" +For more information about this error, try `rustc --explain E0263`. diff --git a/src/test/ui/error-codes/E0264.stderr b/src/test/ui/error-codes/E0264.stderr index aad8002fc464..69863d7bb83e 100644 --- a/src/test/ui/error-codes/E0264.stderr +++ b/src/test/ui/error-codes/E0264.stderr @@ -6,4 +6,4 @@ LL | fn cake(); //~ ERROR E0264 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0264" +For more information about this error, try `rustc --explain E0264`. diff --git a/src/test/ui/error-codes/E0267.stderr b/src/test/ui/error-codes/E0267.stderr index fbd7364d966b..b72109f0644e 100644 --- a/src/test/ui/error-codes/E0267.stderr +++ b/src/test/ui/error-codes/E0267.stderr @@ -6,4 +6,4 @@ LL | let w = || { break; }; //~ ERROR E0267 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0267" +For more information about this error, try `rustc --explain E0267`. diff --git a/src/test/ui/error-codes/E0268.stderr b/src/test/ui/error-codes/E0268.stderr index 377ec21c1dd2..e1b5b52085bc 100644 --- a/src/test/ui/error-codes/E0268.stderr +++ b/src/test/ui/error-codes/E0268.stderr @@ -6,4 +6,4 @@ LL | break; //~ ERROR E0268 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0268" +For more information about this error, try `rustc --explain E0268`. diff --git a/src/test/ui/error-codes/E0271.stderr b/src/test/ui/error-codes/E0271.stderr index 1a99afd6a9b0..04c7d244376e 100644 --- a/src/test/ui/error-codes/E0271.stderr +++ b/src/test/ui/error-codes/E0271.stderr @@ -14,4 +14,4 @@ LL | fn foo(t: T) where T: Trait { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0271" +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 11ec85a5d09c..d5bcc94fb653 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -77,4 +77,4 @@ LL | trait Foo {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0275" +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/error-codes/E0276.stderr b/src/test/ui/error-codes/E0276.stderr index 849e2aafd5a4..4823adc250ae 100644 --- a/src/test/ui/error-codes/E0276.stderr +++ b/src/test/ui/error-codes/E0276.stderr @@ -9,4 +9,4 @@ LL | fn foo(x: T) where T: Copy {} //~ ERROR E0276 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0276" +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr index 987bb94bb958..bbe04cfc6e16 100644 --- a/src/test/ui/error-codes/E0277-2.stderr +++ b/src/test/ui/error-codes/E0277-2.stderr @@ -16,4 +16,4 @@ LL | fn is_send() { } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr index 7541e161670f..477128d7d9f0 100644 --- a/src/test/ui/error-codes/E0277.stderr +++ b/src/test/ui/error-codes/E0277.stderr @@ -22,4 +22,4 @@ LL | fn some_func(foo: T) { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr index da5a53a73590..f1319f413958 100644 --- a/src/test/ui/error-codes/E0282.stderr +++ b/src/test/ui/error-codes/E0282.stderr @@ -9,4 +9,4 @@ LL | let x = "hello".chars().rev().collect(); //~ ERROR E0282 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index 9de488cc7aa1..3f63881b61e4 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -12,4 +12,4 @@ LL | fn create() -> u32; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0283" +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/error-codes/E0296.stderr b/src/test/ui/error-codes/E0296.stderr index a35b634cc049..71db4b614a7c 100644 --- a/src/test/ui/error-codes/E0296.stderr +++ b/src/test/ui/error-codes/E0296.stderr @@ -6,4 +6,4 @@ LL | #![recursion_limit] //~ ERROR E0296 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0296" +For more information about this error, try `rustc --explain E0296`. diff --git a/src/test/ui/error-codes/E0297.stderr b/src/test/ui/error-codes/E0297.stderr index 67d5139d386c..d510fa99caec 100644 --- a/src/test/ui/error-codes/E0297.stderr +++ b/src/test/ui/error-codes/E0297.stderr @@ -6,4 +6,4 @@ LL | for Some(x) in xs {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0005" +For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr index 04ad3c972467..7d5100c516e5 100644 --- a/src/test/ui/error-codes/E0301.stderr +++ b/src/test/ui/error-codes/E0301.stderr @@ -6,4 +6,4 @@ LL | option if option.take().is_none() => {}, //~ ERROR E0301 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0301" +For more information about this error, try `rustc --explain E0301`. diff --git a/src/test/ui/error-codes/E0302.stderr b/src/test/ui/error-codes/E0302.stderr index a11b85850a9a..f55dd523f130 100644 --- a/src/test/ui/error-codes/E0302.stderr +++ b/src/test/ui/error-codes/E0302.stderr @@ -6,4 +6,4 @@ LL | option if { option = None; false } => { }, //~ ERROR E0302 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0302" +For more information about this error, try `rustc --explain E0302`. diff --git a/src/test/ui/error-codes/E0303.stderr b/src/test/ui/error-codes/E0303.stderr index c0a92ff55d1f..b9da037df0e6 100644 --- a/src/test/ui/error-codes/E0303.stderr +++ b/src/test/ui/error-codes/E0303.stderr @@ -15,5 +15,5 @@ LL | ref op_string_ref @ Some(s) => {}, error: aborting due to 2 previous errors -You've got a few errors: E0009, E0303 -If you want more information on an error, try using "rustc --explain E0009" +Some errors occurred: E0009, E0303. +For more information about an error, try `rustc --explain E0009`. diff --git a/src/test/ui/error-codes/E0308-4.stderr b/src/test/ui/error-codes/E0308-4.stderr index 057791b467f3..31875349bace 100644 --- a/src/test/ui/error-codes/E0308-4.stderr +++ b/src/test/ui/error-codes/E0308-4.stderr @@ -6,4 +6,4 @@ LL | 0u8...3i8 => (), //~ ERROR E0308 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0308.stderr b/src/test/ui/error-codes/E0308.stderr index 04e5f9da5997..490a8e0ff0f1 100644 --- a/src/test/ui/error-codes/E0308.stderr +++ b/src/test/ui/error-codes/E0308.stderr @@ -9,4 +9,4 @@ LL | fn size_of(); //~ ERROR E0308 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0328.rs b/src/test/ui/error-codes/E0328.rs new file mode 100644 index 000000000000..e08532b02491 --- /dev/null +++ b/src/test/ui/error-codes/E0328.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unsize)] + +use std::marker::Unsize; + +pub struct MyType; + +impl Unsize for MyType {} +//~^ ERROR explicit impls for the `Unsize` trait are not permitted [E0328] + +fn main() {} diff --git a/src/test/ui/error-codes/E0328.stderr b/src/test/ui/error-codes/E0328.stderr new file mode 100644 index 000000000000..ad3a224279ce --- /dev/null +++ b/src/test/ui/error-codes/E0328.stderr @@ -0,0 +1,9 @@ +error[E0328]: explicit impls for the `Unsize` trait are not permitted + --> $DIR/E0328.rs:17:1 + | +LL | impl Unsize for MyType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unsize` not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0328`. diff --git a/src/test/ui/error-codes/E0365.stderr b/src/test/ui/error-codes/E0365.stderr index ce646eb96be8..efa21aa2e22c 100644 --- a/src/test/ui/error-codes/E0365.stderr +++ b/src/test/ui/error-codes/E0365.stderr @@ -8,4 +8,4 @@ LL | pub use foo as foo2; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0365" +For more information about this error, try `rustc --explain E0365`. diff --git a/src/test/ui/error-codes/E0370.stderr b/src/test/ui/error-codes/E0370.stderr index 60e077e063e0..f85d2cf5d0b0 100644 --- a/src/test/ui/error-codes/E0370.stderr +++ b/src/test/ui/error-codes/E0370.stderr @@ -8,4 +8,4 @@ LL | Y, //~ ERROR E0370 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0370" +For more information about this error, try `rustc --explain E0370`. diff --git a/src/test/ui/error-codes/E0374.stderr b/src/test/ui/error-codes/E0374.stderr index 3441f71dcd18..002e2b003af8 100644 --- a/src/test/ui/error-codes/E0374.stderr +++ b/src/test/ui/error-codes/E0374.stderr @@ -7,4 +7,4 @@ LL | | where T: CoerceUnsized {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0374" +For more information about this error, try `rustc --explain E0374`. diff --git a/src/test/ui/error-codes/E0375.stderr b/src/test/ui/error-codes/E0375.stderr index 7e5ddda61d01..3ffd25084b82 100644 --- a/src/test/ui/error-codes/E0375.stderr +++ b/src/test/ui/error-codes/E0375.stderr @@ -9,4 +9,4 @@ LL | impl CoerceUnsized> for Foo {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0375" +For more information about this error, try `rustc --explain E0375`. diff --git a/src/test/ui/error-codes/E0376.stderr b/src/test/ui/error-codes/E0376.stderr index 13c2e443113a..c850d13e6337 100644 --- a/src/test/ui/error-codes/E0376.stderr +++ b/src/test/ui/error-codes/E0376.stderr @@ -6,4 +6,4 @@ LL | impl CoerceUnsized for Foo {} //~ ERROR E0376 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0376" +For more information about this error, try `rustc --explain E0376`. diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr index 7c327970b949..d2263cd4034b 100644 --- a/src/test/ui/error-codes/E0388.stderr +++ b/src/test/ui/error-codes/E0388.stderr @@ -24,5 +24,5 @@ LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017 error: aborting due to 4 previous errors -You've got a few errors: E0017, E0596 -If you want more information on an error, try using "rustc --explain E0017" +Some errors occurred: E0017, E0596. +For more information about an error, try `rustc --explain E0017`. diff --git a/src/test/ui/error-codes/E0389.stderr b/src/test/ui/error-codes/E0389.stderr index a24491770c86..29e1ea9dd169 100644 --- a/src/test/ui/error-codes/E0389.stderr +++ b/src/test/ui/error-codes/E0389.stderr @@ -6,4 +6,4 @@ LL | fancy_ref.num = 6; //~ ERROR E0389 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0389" +For more information about this error, try `rustc --explain E0389`. diff --git a/src/test/ui/error-codes/E0390.stderr b/src/test/ui/error-codes/E0390.stderr index 70b62f5771e3..fda2c2e2fe01 100644 --- a/src/test/ui/error-codes/E0390.stderr +++ b/src/test/ui/error-codes/E0390.stderr @@ -12,4 +12,4 @@ LL | impl *mut Foo {} //~ ERROR E0390 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0390" +For more information about this error, try `rustc --explain E0390`. diff --git a/src/test/ui/error-codes/E0392.stderr b/src/test/ui/error-codes/E0392.stderr index 9ee85aa4de3a..cfa9c49b2eeb 100644 --- a/src/test/ui/error-codes/E0392.stderr +++ b/src/test/ui/error-codes/E0392.stderr @@ -8,4 +8,4 @@ LL | enum Foo { Bar } //~ ERROR E0392 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0392" +For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/error-codes/E0393.stderr b/src/test/ui/error-codes/E0393.stderr index f6e77cbb8007..c0e282308c15 100644 --- a/src/test/ui/error-codes/E0393.stderr +++ b/src/test/ui/error-codes/E0393.stderr @@ -8,4 +8,4 @@ LL | fn together_we_will_rule_the_galaxy(son: &A) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0393" +For more information about this error, try `rustc --explain E0393`. diff --git a/src/test/ui/error-codes/E0394.stderr b/src/test/ui/error-codes/E0394.stderr index 74cb5ed03765..6c89957de07e 100644 --- a/src/test/ui/error-codes/E0394.stderr +++ b/src/test/ui/error-codes/E0394.stderr @@ -8,4 +8,4 @@ LL | static B: u32 = A; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0394" +For more information about this error, try `rustc --explain E0394`. diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 5f3d962877ac..ee90df798706 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -6,4 +6,4 @@ LL | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ER error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0395" +For more information about this error, try `rustc --explain E0395`. diff --git a/src/test/ui/error-codes/E0396.stderr b/src/test/ui/error-codes/E0396.stderr index fe20b984216c..87dfd50dc973 100644 --- a/src/test/ui/error-codes/E0396.stderr +++ b/src/test/ui/error-codes/E0396.stderr @@ -6,4 +6,4 @@ LL | const VALUE: u8 = unsafe { *REG_ADDR }; //~ ERROR E0396 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0396" +For more information about this error, try `rustc --explain E0396`. diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs index 15b946625778..4fc74f5ef221 100644 --- a/src/test/ui/error-codes/E0401.rs +++ b/src/test/ui/error-codes/E0401.rs @@ -11,14 +11,14 @@ trait Baz {} fn foo(x: T) { - fn bar, W: Fn()>(y: T) { //~ ERROR E0401 + fn bfnr, W: Fn()>(y: T) { //~ ERROR E0401 } fn baz, W: Fn()> (y: T) { //~ ERROR E0401 } - bar(x); + bfnr(x); } diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index c306ff4a04f6..5b66d1093408 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -1,12 +1,12 @@ error[E0401]: can't use type parameters from outer function - --> $DIR/E0401.rs:14:38 + --> $DIR/E0401.rs:14:39 | LL | fn foo(x: T) { | - type variable from outer function -LL | fn bar, W: Fn()>(y: T) { //~ ERROR E0401 - | -------------------------- ^ use of type variable from outer function +LL | fn bfnr, W: Fn()>(y: T) { //~ ERROR E0401 + | --------------------------- ^ use of type variable from outer function | | - | help: try using a local type parameter instead: `bar, W: Fn(), T>` + | help: try using a local type parameter instead: `bfnr, W: Fn(), T>` error[E0401]: can't use type parameters from outer function --> $DIR/E0401.rs:19:16 @@ -14,10 +14,11 @@ error[E0401]: can't use type parameters from outer function LL | fn foo(x: T) { | - type variable from outer function ... +LL | fn baz $DIR/E0401.rs:32:25 @@ -32,4 +33,4 @@ LL | fn helper(sel: &Self) -> u8 { //~ ERROR E0401 error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0401" +For more information about this error, try `rustc --explain E0401`. diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr index a83d6b674731..f9ccc31654aa 100644 --- a/src/test/ui/error-codes/E0403.stderr +++ b/src/test/ui/error-codes/E0403.stderr @@ -8,4 +8,4 @@ LL | fn foo(s: T, u: T) {} //~ ERROR E0403 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0403" +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/error-codes/E0404.stderr b/src/test/ui/error-codes/E0404.stderr index ac1d2a00cf44..afb748bedbe0 100644 --- a/src/test/ui/error-codes/E0404.stderr +++ b/src/test/ui/error-codes/E0404.stderr @@ -10,6 +10,6 @@ error[E0404]: expected trait, found struct `Foo` LL | fn baz(_: T) {} //~ ERROR E0404 | ^^^ not a trait -error: cannot continue compilation due to previous error +error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0404" +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/error-codes/E0405.stderr b/src/test/ui/error-codes/E0405.stderr index 0019e16d7f37..27190af1c6c1 100644 --- a/src/test/ui/error-codes/E0405.stderr +++ b/src/test/ui/error-codes/E0405.stderr @@ -4,6 +4,6 @@ error[E0405]: cannot find trait `SomeTrait` in this scope LL | impl SomeTrait for Foo {} //~ ERROR E0405 | ^^^^^^^^^ not found in this scope -error: cannot continue compilation due to previous error +error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0405" +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/error-codes/E0407.stderr b/src/test/ui/error-codes/E0407.stderr index 2e2bc3aeb55d..1be04a992c24 100644 --- a/src/test/ui/error-codes/E0407.stderr +++ b/src/test/ui/error-codes/E0407.stderr @@ -6,4 +6,4 @@ LL | fn b() {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0407" +For more information about this error, try `rustc --explain E0407`. diff --git a/src/test/ui/error-codes/E0408.stderr b/src/test/ui/error-codes/E0408.stderr index 1f928275bd5c..46845de1aadd 100644 --- a/src/test/ui/error-codes/E0408.stderr +++ b/src/test/ui/error-codes/E0408.stderr @@ -8,4 +8,4 @@ LL | Some(y) | None => {} //~ ERROR variable `y` is not bound in all pa error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0408" +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/error-codes/E0411.stderr b/src/test/ui/error-codes/E0411.stderr index b0336d7d6688..a5f2e3a7b93d 100644 --- a/src/test/ui/error-codes/E0411.stderr +++ b/src/test/ui/error-codes/E0411.stderr @@ -6,4 +6,4 @@ LL | ::foo; //~ ERROR E0411 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0411" +For more information about this error, try `rustc --explain E0411`. diff --git a/src/test/ui/error-codes/E0412.stderr b/src/test/ui/error-codes/E0412.stderr index 4444af73a7ef..61115c8b2920 100644 --- a/src/test/ui/error-codes/E0412.stderr +++ b/src/test/ui/error-codes/E0412.stderr @@ -6,4 +6,4 @@ LL | impl Something {} //~ ERROR E0412 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0412" +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/error-codes/E0415.stderr b/src/test/ui/error-codes/E0415.stderr index 82c6284e4339..3f036f3a534b 100644 --- a/src/test/ui/error-codes/E0415.stderr +++ b/src/test/ui/error-codes/E0415.stderr @@ -6,4 +6,4 @@ LL | fn foo(f: i32, f: i32) {} //~ ERROR E0415 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0415" +For more information about this error, try `rustc --explain E0415`. diff --git a/src/test/ui/error-codes/E0416.stderr b/src/test/ui/error-codes/E0416.stderr index 35daf20a2234..8815bb2ad840 100644 --- a/src/test/ui/error-codes/E0416.stderr +++ b/src/test/ui/error-codes/E0416.stderr @@ -6,4 +6,4 @@ LL | (x, x) => {} //~ ERROR E0416 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0416" +For more information about this error, try `rustc --explain E0416`. diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index 112754e75b83..ef24295332d5 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -6,4 +6,4 @@ LL | let f = Foo(); //~ ERROR E0423 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index 5f2d56730676..2c4f7f7c62b3 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -6,4 +6,4 @@ LL | self.bar(); //~ ERROR E0424 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0424" +For more information about this error, try `rustc --explain E0424`. diff --git a/src/test/ui/error-codes/E0425.stderr b/src/test/ui/error-codes/E0425.stderr index 9d27e4f59444..72756baf8efc 100644 --- a/src/test/ui/error-codes/E0425.stderr +++ b/src/test/ui/error-codes/E0425.stderr @@ -6,4 +6,4 @@ LL | elf; //~ ERROR E0425 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/error-codes/E0426.stderr b/src/test/ui/error-codes/E0426.stderr index 5e0bc69b1eb4..29249ab3919e 100644 --- a/src/test/ui/error-codes/E0426.stderr +++ b/src/test/ui/error-codes/E0426.stderr @@ -6,4 +6,4 @@ LL | break 'a; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0426" +For more information about this error, try `rustc --explain E0426`. diff --git a/src/test/ui/error-codes/E0428.stderr b/src/test/ui/error-codes/E0428.stderr index 20f734af0817..ebfe866625d8 100644 --- a/src/test/ui/error-codes/E0428.stderr +++ b/src/test/ui/error-codes/E0428.stderr @@ -10,4 +10,4 @@ LL | struct Bar; //~ ERROR E0428 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0428" +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/error-codes/E0429.stderr b/src/test/ui/error-codes/E0429.stderr index a72c77360b57..d36155fb466e 100644 --- a/src/test/ui/error-codes/E0429.stderr +++ b/src/test/ui/error-codes/E0429.stderr @@ -6,4 +6,4 @@ LL | use std::fmt::self; //~ ERROR E0429 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0429" +For more information about this error, try `rustc --explain E0429`. diff --git a/src/test/ui/error-codes/E0430.stderr b/src/test/ui/error-codes/E0430.stderr index b6448ec18c3d..c50ed4ea5de8 100644 --- a/src/test/ui/error-codes/E0430.stderr +++ b/src/test/ui/error-codes/E0430.stderr @@ -22,5 +22,5 @@ LL | use std::fmt::{self, self as other_fmt}; //~ ERROR E0430 error: aborting due to 2 previous errors -You've got a few errors: E0252, E0430 -If you want more information on an error, try using "rustc --explain E0252" +Some errors occurred: E0252, E0430. +For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/error-codes/E0431.stderr b/src/test/ui/error-codes/E0431.stderr index 364ba0aa9578..75b8486aa5cc 100644 --- a/src/test/ui/error-codes/E0431.stderr +++ b/src/test/ui/error-codes/E0431.stderr @@ -6,4 +6,4 @@ LL | use {self}; //~ ERROR E0431 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0431" +For more information about this error, try `rustc --explain E0431`. diff --git a/src/test/ui/error-codes/E0432.stderr b/src/test/ui/error-codes/E0432.stderr index 747b337d3635..291bb4507559 100644 --- a/src/test/ui/error-codes/E0432.stderr +++ b/src/test/ui/error-codes/E0432.stderr @@ -6,4 +6,4 @@ LL | use something::Foo; //~ ERROR E0432 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0432" +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/error-codes/E0433.stderr b/src/test/ui/error-codes/E0433.stderr index 7635d9738ad9..f8cf5f6f92f6 100644 --- a/src/test/ui/error-codes/E0433.stderr +++ b/src/test/ui/error-codes/E0433.stderr @@ -6,4 +6,4 @@ LL | let map = HashMap::new(); //~ ERROR E0433 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0433" +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/error-codes/E0434.stderr b/src/test/ui/error-codes/E0434.stderr index b13c0cf79717..bbbc7d16e3ba 100644 --- a/src/test/ui/error-codes/E0434.stderr +++ b/src/test/ui/error-codes/E0434.stderr @@ -8,4 +8,4 @@ LL | y //~ ERROR E0434 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0434" +For more information about this error, try `rustc --explain E0434`. diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr index 5ca79e72c2b4..517fddfa1ac1 100644 --- a/src/test/ui/error-codes/E0435.stderr +++ b/src/test/ui/error-codes/E0435.stderr @@ -6,4 +6,4 @@ LL | let _: [u8; foo]; //~ ERROR E0435 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0435" +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/error-codes/E0437.stderr b/src/test/ui/error-codes/E0437.stderr index 408924b0439a..790e306f121b 100644 --- a/src/test/ui/error-codes/E0437.stderr +++ b/src/test/ui/error-codes/E0437.stderr @@ -6,4 +6,4 @@ LL | type Bar = bool; //~ ERROR E0437 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0437" +For more information about this error, try `rustc --explain E0437`. diff --git a/src/test/ui/error-codes/E0438.stderr b/src/test/ui/error-codes/E0438.stderr index b636236e41ab..5f311e9bca98 100644 --- a/src/test/ui/error-codes/E0438.stderr +++ b/src/test/ui/error-codes/E0438.stderr @@ -6,4 +6,4 @@ LL | const BAR: bool = true; //~ ERROR E0438 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0438" +For more information about this error, try `rustc --explain E0438`. diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr index 27a090431258..1400633001ac 100644 --- a/src/test/ui/error-codes/E0439.stderr +++ b/src/test/ui/error-codes/E0439.stderr @@ -6,4 +6,4 @@ LL | fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0439" +For more information about this error, try `rustc --explain E0439`. diff --git a/src/test/ui/error-codes/E0440.stderr b/src/test/ui/error-codes/E0440.stderr index c9ac1b8261bd..acaa948a3315 100644 --- a/src/test/ui/error-codes/E0440.stderr +++ b/src/test/ui/error-codes/E0440.stderr @@ -6,4 +6,4 @@ LL | fn x86_mm_movemask_pd(x: f64x2) -> i32; //~ ERROR E0440 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0440" +For more information about this error, try `rustc --explain E0440`. diff --git a/src/test/ui/error-codes/E0441.stderr b/src/test/ui/error-codes/E0441.stderr index 1cb4193bd34b..8a01176dbbee 100644 --- a/src/test/ui/error-codes/E0441.stderr +++ b/src/test/ui/error-codes/E0441.stderr @@ -6,4 +6,4 @@ LL | fn x86_mm_adds_ep16(x: i16x8, y: i16x8) -> i16x8; //~ ERROR E0441 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0441" +For more information about this error, try `rustc --explain E0441`. diff --git a/src/test/ui/error-codes/E0442.stderr b/src/test/ui/error-codes/E0442.stderr index 2119ea11a663..01881e1b5c38 100644 --- a/src/test/ui/error-codes/E0442.stderr +++ b/src/test/ui/error-codes/E0442.stderr @@ -18,4 +18,4 @@ LL | fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2; error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0442" +For more information about this error, try `rustc --explain E0442`. diff --git a/src/test/ui/error-codes/E0443.stderr b/src/test/ui/error-codes/E0443.stderr index 8a08bd9762e0..b57c9423fce7 100644 --- a/src/test/ui/error-codes/E0443.stderr +++ b/src/test/ui/error-codes/E0443.stderr @@ -6,4 +6,4 @@ LL | fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i64x8; //~ ERROR E0443 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0443" +For more information about this error, try `rustc --explain E0443`. diff --git a/src/test/ui/error-codes/E0444.stderr b/src/test/ui/error-codes/E0444.stderr index 7e20e47b165f..338c9dac75e3 100644 --- a/src/test/ui/error-codes/E0444.stderr +++ b/src/test/ui/error-codes/E0444.stderr @@ -6,4 +6,4 @@ LL | fn x86_mm_movemask_pd(x: f64x2, y: f64x2, z: f64x2) -> i32; //~ ERROR E error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0444" +For more information about this error, try `rustc --explain E0444`. diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr index 6e0616277f4e..552de83a65e0 100644 --- a/src/test/ui/error-codes/E0445.stderr +++ b/src/test/ui/error-codes/E0445.stderr @@ -18,4 +18,4 @@ LL | pub fn foo (t: T) {} error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0445" +For more information about this error, try `rustc --explain E0445`. diff --git a/src/test/ui/error-codes/E0446.stderr b/src/test/ui/error-codes/E0446.stderr index 067fdb47da93..bb5ae494d6c8 100644 --- a/src/test/ui/error-codes/E0446.stderr +++ b/src/test/ui/error-codes/E0446.stderr @@ -8,4 +8,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0446" +For more information about this error, try `rustc --explain E0446`. diff --git a/src/test/ui/error-codes/E0449.stderr b/src/test/ui/error-codes/E0449.stderr index 68ec6379d711..df3b09ba7c9f 100644 --- a/src/test/ui/error-codes/E0449.stderr +++ b/src/test/ui/error-codes/E0449.stderr @@ -2,7 +2,7 @@ error[E0449]: unnecessary visibility qualifier --> $DIR/E0449.rs:17:1 | LL | pub impl Bar {} //~ ERROR E0449 - | ^^^ `pub` not needed here + | ^^^ `pub` not permitted here because it's implied | = note: place qualifiers on individual impl items instead @@ -10,14 +10,14 @@ error[E0449]: unnecessary visibility qualifier --> $DIR/E0449.rs:19:1 | LL | pub impl Foo for Bar { //~ ERROR E0449 - | ^^^ `pub` not needed here + | ^^^ `pub` not permitted here because it's implied error[E0449]: unnecessary visibility qualifier --> $DIR/E0449.rs:20:5 | LL | pub fn foo() {} //~ ERROR E0449 - | ^^^ `pub` not needed here + | ^^^ `pub` not permitted here because it's implied error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0449" +For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/error-codes/E0451.stderr b/src/test/ui/error-codes/E0451.stderr index 003a93811bd9..4d54e17d5070 100644 --- a/src/test/ui/error-codes/E0451.stderr +++ b/src/test/ui/error-codes/E0451.stderr @@ -12,4 +12,4 @@ LL | let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0451" +For more information about this error, try `rustc --explain E0451`. diff --git a/src/test/ui/error-codes/E0452.stderr b/src/test/ui/error-codes/E0452.stderr index 6e4b47e9631c..a915ca1d6746 100644 --- a/src/test/ui/error-codes/E0452.stderr +++ b/src/test/ui/error-codes/E0452.stderr @@ -6,4 +6,4 @@ LL | #![allow(foo = "")] //~ ERROR E0452 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0452" +For more information about this error, try `rustc --explain E0452`. diff --git a/src/test/ui/error-codes/E0453.stderr b/src/test/ui/error-codes/E0453.stderr index 646b98b84738..59e1a1cfdfc4 100644 --- a/src/test/ui/error-codes/E0453.stderr +++ b/src/test/ui/error-codes/E0453.stderr @@ -9,4 +9,4 @@ LL | #[allow(non_snake_case)] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0453" +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/error-codes/E0454.stderr b/src/test/ui/error-codes/E0454.stderr index 11f1958bf96c..44dde5386660 100644 --- a/src/test/ui/error-codes/E0454.stderr +++ b/src/test/ui/error-codes/E0454.stderr @@ -6,4 +6,4 @@ LL | #[link(name = "")] extern {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0454" +For more information about this error, try `rustc --explain E0454`. diff --git a/src/test/ui/error-codes/E0458.stderr b/src/test/ui/error-codes/E0458.stderr index 4bcafa47d358..5304e7c2d271 100644 --- a/src/test/ui/error-codes/E0458.stderr +++ b/src/test/ui/error-codes/E0458.stderr @@ -12,5 +12,5 @@ LL | #[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458 error: aborting due to 2 previous errors -You've got a few errors: E0458, E0459 -If you want more information on an error, try using "rustc --explain E0458" +Some errors occurred: E0458, E0459. +For more information about an error, try `rustc --explain E0458`. diff --git a/src/test/ui/error-codes/E0459.stderr b/src/test/ui/error-codes/E0459.stderr index c443e78ab3ad..8f31e7b4b13c 100644 --- a/src/test/ui/error-codes/E0459.stderr +++ b/src/test/ui/error-codes/E0459.stderr @@ -6,4 +6,4 @@ LL | #[link(kind = "dylib")] extern {} //~ ERROR E0459 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0459" +For more information about this error, try `rustc --explain E0459`. diff --git a/src/test/ui/error-codes/E0463.stderr b/src/test/ui/error-codes/E0463.stderr index 41575b70d15c..26403827e4a8 100644 --- a/src/test/ui/error-codes/E0463.stderr +++ b/src/test/ui/error-codes/E0463.stderr @@ -6,4 +6,4 @@ LL | #![plugin(cookie_monster)] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0463" +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/error-codes/E0478.stderr b/src/test/ui/error-codes/E0478.stderr index bbc243a37574..44d8151303f7 100644 --- a/src/test/ui/error-codes/E0478.stderr +++ b/src/test/ui/error-codes/E0478.stderr @@ -17,4 +17,4 @@ LL | struct Prince<'kiss, 'SnowWhite> { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0478" +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr index 359c63bb8ff7..157a19296902 100644 --- a/src/test/ui/error-codes/E0492.stderr +++ b/src/test/ui/error-codes/E0492.stderr @@ -6,4 +6,4 @@ LL | static B: &'static AtomicUsize = &A; //~ ERROR E0492 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0492" +For more information about this error, try `rustc --explain E0492`. diff --git a/src/test/ui/error-codes/E0494.stderr b/src/test/ui/error-codes/E0494.stderr index 82dd74c012b0..65e6b1fe670f 100644 --- a/src/test/ui/error-codes/E0494.stderr +++ b/src/test/ui/error-codes/E0494.stderr @@ -6,4 +6,4 @@ LL | static A : &'static u32 = &S.a; //~ ERROR E0494 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0494" +For more information about this error, try `rustc --explain E0494`. diff --git a/src/test/ui/error-codes/E0496.stderr b/src/test/ui/error-codes/E0496.stderr index 945c2391d030..198daa512bda 100644 --- a/src/test/ui/error-codes/E0496.stderr +++ b/src/test/ui/error-codes/E0496.stderr @@ -8,4 +8,4 @@ LL | fn f<'a>(x: &'a i32) { //~ ERROR E0496 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0496" +For more information about this error, try `rustc --explain E0496`. diff --git a/src/test/ui/error-codes/E0499.stderr b/src/test/ui/error-codes/E0499.stderr index 5332df0c2354..dcb477ab1cb8 100644 --- a/src/test/ui/error-codes/E0499.stderr +++ b/src/test/ui/error-codes/E0499.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0499" +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/error-codes/E0502.stderr b/src/test/ui/error-codes/E0502.stderr index 07430990f0a5..d377fa883dd8 100644 --- a/src/test/ui/error-codes/E0502.stderr +++ b/src/test/ui/error-codes/E0502.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0502" +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/error-codes/E0503.stderr b/src/test/ui/error-codes/E0503.stderr index ac6634cb64f2..0342ebc41936 100644 --- a/src/test/ui/error-codes/E0503.stderr +++ b/src/test/ui/error-codes/E0503.stderr @@ -8,4 +8,4 @@ LL | let _sum = value + 1; //~ ERROR E0503 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0503" +For more information about this error, try `rustc --explain E0503`. diff --git a/src/test/ui/error-codes/E0504.stderr b/src/test/ui/error-codes/E0504.stderr index 9f3bd79dcfe7..cd1d3ec5ba47 100644 --- a/src/test/ui/error-codes/E0504.stderr +++ b/src/test/ui/error-codes/E0504.stderr @@ -9,4 +9,4 @@ LL | println!("child function: {}", fancy_num.num); //~ ERROR E0504 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0504" +For more information about this error, try `rustc --explain E0504`. diff --git a/src/test/ui/error-codes/E0505.stderr b/src/test/ui/error-codes/E0505.stderr index 71392857d0ae..64558ba8c7c0 100644 --- a/src/test/ui/error-codes/E0505.stderr +++ b/src/test/ui/error-codes/E0505.stderr @@ -8,4 +8,4 @@ LL | eat(x); //~ ERROR E0505 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0505" +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/error-codes/E0507.stderr b/src/test/ui/error-codes/E0507.stderr index de94648ec0bc..3d9d8a5145d0 100644 --- a/src/test/ui/error-codes/E0507.stderr +++ b/src/test/ui/error-codes/E0507.stderr @@ -6,4 +6,4 @@ LL | x.borrow().nothing_is_true(); //~ ERROR E0507 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0507" +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/error-codes/E0509.stderr b/src/test/ui/error-codes/E0509.stderr index 3bc2a4450a18..3952081a2655 100644 --- a/src/test/ui/error-codes/E0509.stderr +++ b/src/test/ui/error-codes/E0509.stderr @@ -9,4 +9,4 @@ LL | let fancy_field = drop_struct.fancy; //~ ERROR E0509 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0509" +For more information about this error, try `rustc --explain E0509`. diff --git a/src/test/ui/error-codes/E0511.stderr b/src/test/ui/error-codes/E0511.stderr index 0273735562d9..1b8d125cf1a0 100644 --- a/src/test/ui/error-codes/E0511.stderr +++ b/src/test/ui/error-codes/E0511.stderr @@ -6,4 +6,4 @@ LL | unsafe { simd_add(0, 1); } //~ ERROR E0511 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0511" +For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/error-codes/E0512.stderr b/src/test/ui/error-codes/E0512.stderr index bcce48c0cd50..c91f6ad8f0af 100644 --- a/src/test/ui/error-codes/E0512.stderr +++ b/src/test/ui/error-codes/E0512.stderr @@ -9,4 +9,4 @@ LL | unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0512" +For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/ui/error-codes/E0516.stderr b/src/test/ui/error-codes/E0516.stderr index bae85cabced5..d298e288859d 100644 --- a/src/test/ui/error-codes/E0516.stderr +++ b/src/test/ui/error-codes/E0516.stderr @@ -6,4 +6,4 @@ LL | let x: typeof(92) = 92; //~ ERROR E0516 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0516" +For more information about this error, try `rustc --explain E0516`. diff --git a/src/test/ui/error-codes/E0517.stderr b/src/test/ui/error-codes/E0517.stderr index fbaeb6fabbbd..4779fd08c684 100644 --- a/src/test/ui/error-codes/E0517.stderr +++ b/src/test/ui/error-codes/E0517.stderr @@ -33,4 +33,4 @@ LL | | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0517" +For more information about this error, try `rustc --explain E0517`. diff --git a/src/test/ui/error-codes/E0518.stderr b/src/test/ui/error-codes/E0518.stderr index 3d199c7fa7fe..d8feec991406 100644 --- a/src/test/ui/error-codes/E0518.stderr +++ b/src/test/ui/error-codes/E0518.stderr @@ -17,4 +17,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0518" +For more information about this error, try `rustc --explain E0518`. diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr index a79f11f63e7c..67ec1d427157 100644 --- a/src/test/ui/error-codes/E0520.stderr +++ b/src/test/ui/error-codes/E0520.stderr @@ -13,4 +13,4 @@ LL | default fn fly(&self) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0520" +For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/error-codes/E0522.rs b/src/test/ui/error-codes/E0522.rs index 3d4377853464..c50cb759e05c 100644 --- a/src/test/ui/error-codes/E0522.rs +++ b/src/test/ui/error-codes/E0522.rs @@ -15,3 +15,5 @@ fn cookie() -> ! { //~^^ ERROR definition of an unknown language item: `cookie` [E0522] loop {} } + +fn main() {} diff --git a/src/test/ui/error-codes/E0522.stderr b/src/test/ui/error-codes/E0522.stderr index c67e7bea34d5..9f3f8968d734 100644 --- a/src/test/ui/error-codes/E0522.stderr +++ b/src/test/ui/error-codes/E0522.stderr @@ -1,12 +1,9 @@ -error[E0601]: main function not found - error[E0522]: definition of an unknown language item: `cookie` --> $DIR/E0522.rs:13:1 | LL | #[lang = "cookie"] | ^^^^^^^^^^^^^^^^^^ definition of unknown language item `cookie` -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0522, E0601 -If you want more information on an error, try using "rustc --explain E0522" +For more information about this error, try `rustc --explain E0522`. diff --git a/src/test/ui/error-codes/E0527.rs b/src/test/ui/error-codes/E0527.rs index 67d222e867e6..a90ccec9cf5e 100644 --- a/src/test/ui/error-codes/E0527.rs +++ b/src/test/ui/error-codes/E0527.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - fn main() { let r = &[1, 2, 3, 4]; match r { diff --git a/src/test/ui/error-codes/E0527.stderr b/src/test/ui/error-codes/E0527.stderr index d9f992240577..1e764c185877 100644 --- a/src/test/ui/error-codes/E0527.stderr +++ b/src/test/ui/error-codes/E0527.stderr @@ -1,9 +1,9 @@ error[E0527]: pattern requires 2 elements but array has 4 - --> $DIR/E0527.rs:16:10 + --> $DIR/E0527.rs:14:10 | LL | &[a, b] => { | ^^^^^^ expected 4 elements error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0527" +For more information about this error, try `rustc --explain E0527`. diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr index 824fae59588a..ca9f8f454575 100644 --- a/src/test/ui/error-codes/E0528.stderr +++ b/src/test/ui/error-codes/E0528.stderr @@ -6,4 +6,4 @@ LL | &[a, b, c, rest..] => { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0528" +For more information about this error, try `rustc --explain E0528`. diff --git a/src/test/ui/error-codes/E0529.rs b/src/test/ui/error-codes/E0529.rs index 5262ad7b716f..2459054da89a 100644 --- a/src/test/ui/error-codes/E0529.rs +++ b/src/test/ui/error-codes/E0529.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - fn main() { let r: f32 = 1.0; match r { diff --git a/src/test/ui/error-codes/E0529.stderr b/src/test/ui/error-codes/E0529.stderr index 5031f717c82a..b2e7ae23fb0e 100644 --- a/src/test/ui/error-codes/E0529.stderr +++ b/src/test/ui/error-codes/E0529.stderr @@ -1,9 +1,9 @@ error[E0529]: expected an array or slice, found `f32` - --> $DIR/E0529.rs:16:9 + --> $DIR/E0529.rs:14:9 | LL | [a, b] => { | ^^^^^^ pattern cannot match with input type `f32` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0529" +For more information about this error, try `rustc --explain E0529`. diff --git a/src/test/ui/error-codes/E0530.stderr b/src/test/ui/error-codes/E0530.stderr index 2a76eb140871..e157ca9042cd 100644 --- a/src/test/ui/error-codes/E0530.stderr +++ b/src/test/ui/error-codes/E0530.stderr @@ -9,4 +9,4 @@ LL | TEST => {} //~ ERROR E0530 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0530" +For more information about this error, try `rustc --explain E0530`. diff --git a/src/test/ui/error-codes/E0532.stderr b/src/test/ui/error-codes/E0532.stderr index 04102f4dbef1..faccd10ec6d0 100644 --- a/src/test/ui/error-codes/E0532.stderr +++ b/src/test/ui/error-codes/E0532.stderr @@ -6,4 +6,4 @@ LL | StructConst1(_) => { }, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0532" +For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/error-codes/E0534.stderr b/src/test/ui/error-codes/E0534.stderr index 7f56f6b11f17..30890882cc3e 100644 --- a/src/test/ui/error-codes/E0534.stderr +++ b/src/test/ui/error-codes/E0534.stderr @@ -6,4 +6,4 @@ LL | #[inline()] //~ ERROR E0534 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0534" +For more information about this error, try `rustc --explain E0534`. diff --git a/src/test/ui/error-codes/E0558.stderr b/src/test/ui/error-codes/E0558.stderr index cf2ee9a11600..0cb8af992941 100644 --- a/src/test/ui/error-codes/E0558.stderr +++ b/src/test/ui/error-codes/E0558.stderr @@ -6,4 +6,4 @@ LL | #[export_name] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0558" +For more information about this error, try `rustc --explain E0558`. diff --git a/src/test/ui/error-codes/E0559.stderr b/src/test/ui/error-codes/E0559.stderr index 5e0382de5c93..cb9059ee5380 100644 --- a/src/test/ui/error-codes/E0559.stderr +++ b/src/test/ui/error-codes/E0559.stderr @@ -8,4 +8,4 @@ LL | let s = Field::Fool { joke: 0 }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0559" +For more information about this error, try `rustc --explain E0559`. diff --git a/src/test/ui/error-codes/E0560.stderr b/src/test/ui/error-codes/E0560.stderr index 1b4e62425f0e..66fb04111dbd 100644 --- a/src/test/ui/error-codes/E0560.stderr +++ b/src/test/ui/error-codes/E0560.stderr @@ -8,4 +8,4 @@ LL | let s = Simba { mother: 1, father: 0 }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0560" +For more information about this error, try `rustc --explain E0560`. diff --git a/src/test/ui/error-codes/E0565-1.stderr b/src/test/ui/error-codes/E0565-1.stderr index f393aa56f9c7..745e79ba2ec0 100644 --- a/src/test/ui/error-codes/E0565-1.stderr +++ b/src/test/ui/error-codes/E0565-1.stderr @@ -6,4 +6,4 @@ LL | #[deprecated("since")] //~ ERROR E0565 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0565" +For more information about this error, try `rustc --explain E0565`. diff --git a/src/test/ui/error-codes/E0565.stderr b/src/test/ui/error-codes/E0565.stderr index c0c1b7b2743e..1d0f34be39be 100644 --- a/src/test/ui/error-codes/E0565.stderr +++ b/src/test/ui/error-codes/E0565.stderr @@ -6,4 +6,4 @@ LL | #[repr("C")] //~ ERROR E0565 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0565" +For more information about this error, try `rustc --explain E0565`. diff --git a/src/test/ui/error-codes/E0572.stderr b/src/test/ui/error-codes/E0572.stderr index 199476248a4f..b2896c3892d3 100644 --- a/src/test/ui/error-codes/E0572.stderr +++ b/src/test/ui/error-codes/E0572.stderr @@ -6,4 +6,4 @@ LL | const FOO: u32 = return 0; //~ ERROR E0572 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0572" +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/error-codes/E0582.stderr b/src/test/ui/error-codes/E0582.stderr index 1bb3049a3f75..c92e0b9f1370 100644 --- a/src/test/ui/error-codes/E0582.stderr +++ b/src/test/ui/error-codes/E0582.stderr @@ -12,4 +12,4 @@ LL | where F: for<'a> Iterator error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0582" +For more information about this error, try `rustc --explain E0582`. diff --git a/src/test/ui/error-codes/E0585.stderr b/src/test/ui/error-codes/E0585.stderr index 063acd2e653b..ef0825939c36 100644 --- a/src/test/ui/error-codes/E0585.stderr +++ b/src/test/ui/error-codes/E0585.stderr @@ -8,4 +8,4 @@ LL | /// Hello! I'm useless... error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0585" +For more information about this error, try `rustc --explain E0585`. diff --git a/src/test/ui/error-codes/E0586.stderr b/src/test/ui/error-codes/E0586.stderr index 352927244984..bd72fbee1604 100644 --- a/src/test/ui/error-codes/E0586.stderr +++ b/src/test/ui/error-codes/E0586.stderr @@ -8,4 +8,4 @@ LL | let x = &tmp[1..=]; //~ ERROR E0586 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0586" +For more information about this error, try `rustc --explain E0586`. diff --git a/src/test/ui/error-codes/E0597.stderr b/src/test/ui/error-codes/E0597.stderr index 41035493bfca..5897cc13c94e 100644 --- a/src/test/ui/error-codes/E0597.stderr +++ b/src/test/ui/error-codes/E0597.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr index a9bb3e502956..d118939d17a1 100644 --- a/src/test/ui/error-codes/E0599.stderr +++ b/src/test/ui/error-codes/E0599.stderr @@ -9,4 +9,4 @@ LL | || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/error-codes/E0600.stderr b/src/test/ui/error-codes/E0600.stderr index add05ac30622..500feb39f5e7 100644 --- a/src/test/ui/error-codes/E0600.stderr +++ b/src/test/ui/error-codes/E0600.stderr @@ -6,4 +6,4 @@ LL | !"a"; //~ ERROR E0600 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0600" +For more information about this error, try `rustc --explain E0600`. diff --git a/src/test/ui/error-codes/E0601.rs b/src/test/ui/error-codes/E0601.rs new file mode 100644 index 000000000000..37b3f523475f --- /dev/null +++ b/src/test/ui/error-codes/E0601.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test for main function not found. diff --git a/src/test/ui/error-codes/E0601.stderr b/src/test/ui/error-codes/E0601.stderr new file mode 100644 index 000000000000..cbc20db35da7 --- /dev/null +++ b/src/test/ui/error-codes/E0601.stderr @@ -0,0 +1,7 @@ +error[E0601]: `main` function not found in crate `E0601` + | + = note: consider adding a `main` function to `$DIR/E0601.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/error-codes/E0602.stderr b/src/test/ui/error-codes/E0602.stderr index fb1144b616d1..863600410261 100644 --- a/src/test/ui/error-codes/E0602.stderr +++ b/src/test/ui/error-codes/E0602.stderr @@ -4,4 +4,4 @@ error[E0602]: unknown lint: `bogus` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0602" +For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/error-codes/E0603.stderr b/src/test/ui/error-codes/E0603.stderr index db451cbc0fcd..3447f3378294 100644 --- a/src/test/ui/error-codes/E0603.stderr +++ b/src/test/ui/error-codes/E0603.stderr @@ -6,4 +6,4 @@ LL | SomeModule::PRIVATE; //~ ERROR E0603 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0603" +For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/error-codes/E0604.stderr b/src/test/ui/error-codes/E0604.stderr index 875f326df37e..6aa176d1313b 100644 --- a/src/test/ui/error-codes/E0604.stderr +++ b/src/test/ui/error-codes/E0604.stderr @@ -6,4 +6,4 @@ LL | 1u32 as char; //~ ERROR E0604 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0604" +For more information about this error, try `rustc --explain E0604`. diff --git a/src/test/ui/error-codes/E0605.stderr b/src/test/ui/error-codes/E0605.stderr index 4e1f47cebb72..e66e1c12d8f7 100644 --- a/src/test/ui/error-codes/E0605.stderr +++ b/src/test/ui/error-codes/E0605.stderr @@ -16,4 +16,4 @@ LL | v as &u8; //~ ERROR E0605 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0605" +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/error-codes/E0606.stderr b/src/test/ui/error-codes/E0606.stderr index 3c90e2d4beba..bd5bc908f729 100644 --- a/src/test/ui/error-codes/E0606.stderr +++ b/src/test/ui/error-codes/E0606.stderr @@ -12,4 +12,4 @@ LL | &0u8 as u8; //~ ERROR E0606 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0606" +For more information about this error, try `rustc --explain E0606`. diff --git a/src/test/ui/error-codes/E0607.stderr b/src/test/ui/error-codes/E0607.stderr index 62d2c2163bfa..d109908bc746 100644 --- a/src/test/ui/error-codes/E0607.stderr +++ b/src/test/ui/error-codes/E0607.stderr @@ -6,4 +6,4 @@ LL | v as *const [u8]; //~ ERROR E0607 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0607" +For more information about this error, try `rustc --explain E0607`. diff --git a/src/test/ui/error-codes/E0608.stderr b/src/test/ui/error-codes/E0608.stderr index 43227b4f0a35..d5955d1b0707 100644 --- a/src/test/ui/error-codes/E0608.stderr +++ b/src/test/ui/error-codes/E0608.stderr @@ -6,4 +6,4 @@ LL | 0u8[2]; //~ ERROR E0608 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0608" +For more information about this error, try `rustc --explain E0608`. diff --git a/src/test/ui/error-codes/E0609.stderr b/src/test/ui/error-codes/E0609.stderr index 70deb168168e..24581889ae95 100644 --- a/src/test/ui/error-codes/E0609.stderr +++ b/src/test/ui/error-codes/E0609.stderr @@ -14,4 +14,4 @@ LL | y.1; //~ ERROR E0609 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0609" +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/error-codes/E0610.stderr b/src/test/ui/error-codes/E0610.stderr index d6b14642546a..3f1cda3b447d 100644 --- a/src/test/ui/error-codes/E0610.stderr +++ b/src/test/ui/error-codes/E0610.stderr @@ -6,4 +6,4 @@ LL | let _ = x.foo; //~ ERROR E0610 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0610" +For more information about this error, try `rustc --explain E0610`. diff --git a/src/test/ui/error-codes/E0611.stderr b/src/test/ui/error-codes/E0611.stderr index 90194afe4ffe..c4b86e76c14e 100644 --- a/src/test/ui/error-codes/E0611.stderr +++ b/src/test/ui/error-codes/E0611.stderr @@ -6,4 +6,4 @@ LL | y.0; //~ ERROR E0611 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0611" +For more information about this error, try `rustc --explain E0611`. diff --git a/src/test/ui/error-codes/E0612.stderr b/src/test/ui/error-codes/E0612.stderr index 5c27635097f7..18013697a833 100644 --- a/src/test/ui/error-codes/E0612.stderr +++ b/src/test/ui/error-codes/E0612.stderr @@ -6,4 +6,4 @@ LL | y.1; //~ ERROR E0612 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0612" +For more information about this error, try `rustc --explain E0612`. diff --git a/src/test/ui/error-codes/E0614.stderr b/src/test/ui/error-codes/E0614.stderr index b68887ef36b7..571d6e76776a 100644 --- a/src/test/ui/error-codes/E0614.stderr +++ b/src/test/ui/error-codes/E0614.stderr @@ -6,4 +6,4 @@ LL | *y; //~ ERROR E0614 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0614" +For more information about this error, try `rustc --explain E0614`. diff --git a/src/test/ui/error-codes/E0615.stderr b/src/test/ui/error-codes/E0615.stderr index 39e63825d6a1..88317a34ee3f 100644 --- a/src/test/ui/error-codes/E0615.stderr +++ b/src/test/ui/error-codes/E0615.stderr @@ -8,4 +8,4 @@ LL | f.method; //~ ERROR E0615 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0615" +For more information about this error, try `rustc --explain E0615`. diff --git a/src/test/ui/error-codes/E0616.stderr b/src/test/ui/error-codes/E0616.stderr index 38065f048ad0..26525863c0d8 100644 --- a/src/test/ui/error-codes/E0616.stderr +++ b/src/test/ui/error-codes/E0616.stderr @@ -6,4 +6,4 @@ LL | f.x; //~ ERROR E0616 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0616" +For more information about this error, try `rustc --explain E0616`. diff --git a/src/test/ui/error-codes/E0617.stderr b/src/test/ui/error-codes/E0617.stderr index 11b1bf32ee01..114220532c3f 100644 --- a/src/test/ui/error-codes/E0617.stderr +++ b/src/test/ui/error-codes/E0617.stderr @@ -40,4 +40,4 @@ LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8 error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0617" +For more information about this error, try `rustc --explain E0617`. diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr index 41ef37dca543..ef7ace44d59a 100644 --- a/src/test/ui/error-codes/E0618.stderr +++ b/src/test/ui/error-codes/E0618.stderr @@ -21,4 +21,4 @@ LL | x(); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0618" +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/error-codes/E0620.stderr b/src/test/ui/error-codes/E0620.stderr index 310dddc26f08..f7450a331386 100644 --- a/src/test/ui/error-codes/E0620.stderr +++ b/src/test/ui/error-codes/E0620.stderr @@ -12,4 +12,4 @@ LL | let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0620" +For more information about this error, try `rustc --explain E0620`. diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr index fa11d7c77c0f..58f0ede63080 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr @@ -27,4 +27,4 @@ LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0495" +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/error-codes/E0622.stderr b/src/test/ui/error-codes/E0622.stderr index da4d43f60411..ef13084dea04 100644 --- a/src/test/ui/error-codes/E0622.stderr +++ b/src/test/ui/error-codes/E0622.stderr @@ -6,4 +6,4 @@ LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0622" +For more information about this error, try `rustc --explain E0622`. diff --git a/src/test/ui/error-codes/E0624.stderr b/src/test/ui/error-codes/E0624.stderr index 39061f9ec774..ac911b9b7c0b 100644 --- a/src/test/ui/error-codes/E0624.stderr +++ b/src/test/ui/error-codes/E0624.stderr @@ -6,4 +6,4 @@ LL | foo.method(); //~ ERROR method `method` is private [E0624] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0624" +For more information about this error, try `rustc --explain E0624`. diff --git a/src/test/ui/error-codes/E0637.rs b/src/test/ui/error-codes/E0637.rs index 455529b088a2..ee6a978d169a 100644 --- a/src/test/ui/error-codes/E0637.rs +++ b/src/test/ui/error-codes/E0637.rs @@ -7,7 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(underscore_lifetimes)] struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_` fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_` diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr index d44a60760a73..245729376df3 100644 --- a/src/test/ui/error-codes/E0637.stderr +++ b/src/test/ui/error-codes/E0637.stderr @@ -1,21 +1,21 @@ error[E0637]: invalid lifetime bound name: `'_` - --> $DIR/E0637.rs:12:16 + --> $DIR/E0637.rs:11:16 | LL | struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_` | ^^ `'_` is a reserved lifetime name error[E0637]: invalid lifetime bound name: `'_` - --> $DIR/E0637.rs:13:12 + --> $DIR/E0637.rs:12:12 | LL | fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_` | ^^ `'_` is a reserved lifetime name error[E0637]: invalid lifetime bound name: `'_` - --> $DIR/E0637.rs:16:10 + --> $DIR/E0637.rs:15:10 | LL | impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_` | ^^ `'_` is a reserved lifetime name error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0637" +For more information about this error, try `rustc --explain E0637`. diff --git a/src/test/ui/error-codes/E0657.rs b/src/test/ui/error-codes/E0657.rs index 31b3acd86ef5..c23aa40ee379 100644 --- a/src/test/ui/error-codes/E0657.rs +++ b/src/test/ui/error-codes/E0657.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(warnings)] -#![feature(conservative_impl_trait)] trait Id {} trait Lt<'a> {} diff --git a/src/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr index 34952dc73c20..737ae3a163ac 100644 --- a/src/test/ui/error-codes/E0657.stderr +++ b/src/test/ui/error-codes/E0657.stderr @@ -1,15 +1,15 @@ error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level - --> $DIR/E0657.rs:20:31 + --> $DIR/E0657.rs:19:31 | LL | -> Box Id>> | ^^ error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level - --> $DIR/E0657.rs:29:35 + --> $DIR/E0657.rs:28:35 | LL | -> Box Id>> | ^^ error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0657" +For more information about this error, try `rustc --explain E0657`. diff --git a/src/test/ui/error-codes/E0658.rs b/src/test/ui/error-codes/E0658.rs index d30068eb1fe2..dcfa25e528ac 100644 --- a/src/test/ui/error-codes/E0658.rs +++ b/src/test/ui/error-codes/E0658.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let _ = ::std::u128::MAX; //~ ERROR E0658 +#[repr(u128)] +enum Foo { //~ ERROR E0658 + Bar(u64), } + +fn main() {} diff --git a/src/test/ui/error-codes/E0658.stderr b/src/test/ui/error-codes/E0658.stderr index b3425b59f31f..b338b384a117 100644 --- a/src/test/ui/error-codes/E0658.stderr +++ b/src/test/ui/error-codes/E0658.stderr @@ -1,11 +1,13 @@ -error[E0658]: use of unstable library feature 'i128' (see issue #35118) - --> $DIR/E0658.rs:12:13 +error[E0658]: repr with 128-bit type is unstable (see issue #35118) + --> $DIR/E0658.rs:12:1 | -LL | let _ = ::std::u128::MAX; //~ ERROR E0658 - | ^^^^^^^^^^^^^^^^ +LL | / enum Foo { //~ ERROR E0658 +LL | | Bar(u64), +LL | | } + | |_^ | - = help: add #![feature(i128)] to the crate attributes to enable + = help: add #![feature(repr128)] to the crate attributes to enable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/error-codes/E0659.stderr b/src/test/ui/error-codes/E0659.stderr index 31a381a6edd1..06176085b381 100644 --- a/src/test/ui/error-codes/E0659.stderr +++ b/src/test/ui/error-codes/E0659.stderr @@ -18,4 +18,4 @@ LL | pub use earth::*; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0659" +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr index 231864e9655b..345691352b40 100644 --- a/src/test/ui/error-festival.stderr +++ b/src/test/ui/error-festival.stderr @@ -72,5 +72,5 @@ LL | v as *const [u8]; error: aborting due to 10 previous errors -You've got a few errors: E0054, E0368, E0425, E0599, E0600, E0603, E0604, E0605, E0606... -If you want more information on an error, try using "rustc --explain E0054" +Some errors occurred: E0054, E0368, E0425, E0599, E0600, E0603, E0604, E0605, E0606... +For more information about an error, try `rustc --explain E0054`. diff --git a/src/test/ui/fat-ptr-cast.stderr b/src/test/ui/fat-ptr-cast.stderr index 383b5eb46012..cf1dcfcb8ade 100644 --- a/src/test/ui/fat-ptr-cast.stderr +++ b/src/test/ui/fat-ptr-cast.stderr @@ -66,5 +66,5 @@ LL | let mut fail: *const str = 0 as *const str; //~ ERROR casting error: aborting due to 9 previous errors -You've got a few errors: E0605, E0606, E0607 -If you want more information on an error, try using "rustc --explain E0605" +Some errors occurred: E0605, E0606, E0607. +For more information about an error, try `rustc --explain E0605`. diff --git a/src/test/ui/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr index ca55e95b914f..26babb8c3ff4 100644 --- a/src/test/ui/feature-gate-abi-msp430-interrupt.stderr +++ b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr @@ -8,4 +8,4 @@ LL | extern "msp430-interrupt" fn foo() {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-abi.stderr b/src/test/ui/feature-gate-abi.stderr index c2d70cf8ec24..0f9309bfb0cf 100644 --- a/src/test/ui/feature-gate-abi.stderr +++ b/src/test/ui/feature-gate-abi.stderr @@ -448,4 +448,4 @@ LL | extern "thiscall" {} //~ ERROR thiscall is experimental and subject to chan error: aborting due to 56 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-abi_unadjusted.stderr b/src/test/ui/feature-gate-abi_unadjusted.stderr index 2382b931244d..467102d18477 100644 --- a/src/test/ui/feature-gate-abi_unadjusted.stderr +++ b/src/test/ui/feature-gate-abi_unadjusted.stderr @@ -10,4 +10,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-advanced-slice-features.stderr b/src/test/ui/feature-gate-advanced-slice-features.stderr deleted file mode 100644 index b589a01df175..000000000000 --- a/src/test/ui/feature-gate-advanced-slice-features.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121) - --> $DIR/feature-gate-advanced-slice-features.rs:18:9 - | -LL | [ xs.., 4, 5 ] => {} //~ ERROR multiple-element slice matches - | ^^^^^^^^^^^^^^ - | - = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable - -error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121) - --> $DIR/feature-gate-advanced-slice-features.rs:19:9 - | -LL | [ 1, xs.., 5 ] => {} //~ ERROR multiple-element slice matches - | ^^^^^^^^^^^^^^ - | - = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable - -error: aborting due to 2 previous errors - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-allocator_internals.stderr b/src/test/ui/feature-gate-allocator_internals.stderr index 53aa45e86724..a9667e8011a9 100644 --- a/src/test/ui/feature-gate-allocator_internals.stderr +++ b/src/test/ui/feature-gate-allocator_internals.stderr @@ -8,4 +8,4 @@ LL | #![default_lib_allocator] //~ ERROR: attribute is an experimental feature error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr index eab713ed79f9..97e414118546 100644 --- a/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr +++ b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -11,4 +11,4 @@ LL | bar!(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr index e2d48999be48..2ecaaae89d10 100644 --- a/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr +++ b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -11,4 +11,4 @@ LL | bar!(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr index 115927c04cd0..4ff5162b0c08 100644 --- a/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr +++ b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr @@ -8,4 +8,4 @@ LL | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-allow-internal-unstable.stderr b/src/test/ui/feature-gate-allow-internal-unstable.stderr index e46fce67aa9e..b691eed60d3d 100644 --- a/src/test/ui/feature-gate-allow-internal-unstable.stderr +++ b/src/test/ui/feature-gate-allow-internal-unstable.stderr @@ -8,4 +8,4 @@ LL | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-allow_fail.stderr b/src/test/ui/feature-gate-allow_fail.stderr index d73791fa7804..3f8ad32437df 100644 --- a/src/test/ui/feature-gate-allow_fail.stderr +++ b/src/test/ui/feature-gate-allow_fail.stderr @@ -8,4 +8,4 @@ LL | #[allow_fail] //~ ERROR allow_fail attribute is currently unstable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gate-arbitrary-self-types.stderr index b59c047e0649..ea259aa22adf 100644 --- a/src/test/ui/feature-gate-arbitrary-self-types.stderr +++ b/src/test/ui/feature-gate-arbitrary-self-types.stderr @@ -27,4 +27,4 @@ LL | fn bar(self: Box>) {} //~ ERROR arbitrary `self` types are uns error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr b/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr index 4748ebdad211..5ed9a0f4ed04 100644 --- a/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr +++ b/src/test/ui/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -27,4 +27,4 @@ LL | fn bar(self: *const Self) {} error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-asm.stderr b/src/test/ui/feature-gate-asm.stderr index 68fe0a71d5a5..3fab7c0ece58 100644 --- a/src/test/ui/feature-gate-asm.stderr +++ b/src/test/ui/feature-gate-asm.stderr @@ -8,4 +8,4 @@ LL | asm!(""); //~ ERROR inline assembly is not stable enough error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-asm2.stderr b/src/test/ui/feature-gate-asm2.stderr index 4d83ac6100ea..a0e881a3b99a 100644 --- a/src/test/ui/feature-gate-asm2.stderr +++ b/src/test/ui/feature-gate-asm2.stderr @@ -8,4 +8,4 @@ LL | println!("{}", asm!("")); //~ ERROR inline assembly is not stable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-assoc-type-defaults.stderr b/src/test/ui/feature-gate-assoc-type-defaults.stderr index 62a956d4aad5..86431842a836 100644 --- a/src/test/ui/feature-gate-assoc-type-defaults.stderr +++ b/src/test/ui/feature-gate-assoc-type-defaults.stderr @@ -8,4 +8,4 @@ LL | type Bar = u8; //~ ERROR associated type defaults are unstable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-box-expr.stderr b/src/test/ui/feature-gate-box-expr.stderr index db025be0ab2e..72f2f08b5b8e 100644 --- a/src/test/ui/feature-gate-box-expr.stderr +++ b/src/test/ui/feature-gate-box-expr.stderr @@ -8,4 +8,4 @@ LL | let x = box 'c'; //~ ERROR box expression syntax is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-box_patterns.stderr b/src/test/ui/feature-gate-box_patterns.stderr index 4e521f2519ca..a8edb842cfcd 100644 --- a/src/test/ui/feature-gate-box_patterns.stderr +++ b/src/test/ui/feature-gate-box_patterns.stderr @@ -8,4 +8,4 @@ LL | let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-box_syntax.stderr b/src/test/ui/feature-gate-box_syntax.stderr index 8835b2cb14c1..7058512417b1 100644 --- a/src/test/ui/feature-gate-box_syntax.stderr +++ b/src/test/ui/feature-gate-box_syntax.stderr @@ -8,4 +8,4 @@ LL | let x = box 3; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-catch_expr.stderr b/src/test/ui/feature-gate-catch_expr.stderr index 6d8b7f104d97..4ab71460c0da 100644 --- a/src/test/ui/feature-gate-catch_expr.stderr +++ b/src/test/ui/feature-gate-catch_expr.stderr @@ -12,4 +12,4 @@ LL | | }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-cfg-target-feature.stderr b/src/test/ui/feature-gate-cfg-target-feature.stderr index e990c38de19c..bf9e596e71a7 100644 --- a/src/test/ui/feature-gate-cfg-target-feature.stderr +++ b/src/test/ui/feature-gate-cfg-target-feature.stderr @@ -32,4 +32,4 @@ LL | cfg!(target_feature = "x"); error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr index 505f6b397242..f3975b7ce8b2 100644 --- a/src/test/ui/feature-gate-cfg-target-has-atomic.stderr +++ b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr @@ -120,4 +120,4 @@ LL | cfg!(target_has_atomic = "ptr"); error: aborting due to 15 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gate-cfg-target-thread-local.stderr index a6af55b1b265..3467d4e482da 100644 --- a/src/test/ui/feature-gate-cfg-target-thread-local.stderr +++ b/src/test/ui/feature-gate-cfg-target-thread-local.stderr @@ -8,4 +8,4 @@ LL | #[cfg_attr(target_thread_local, thread_local)] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-cfg-target-vendor.stderr b/src/test/ui/feature-gate-cfg-target-vendor.stderr index f19a2b7997af..a625c7e4b247 100644 --- a/src/test/ui/feature-gate-cfg-target-vendor.stderr +++ b/src/test/ui/feature-gate-cfg-target-vendor.stderr @@ -32,4 +32,4 @@ LL | cfg!(target_vendor = "x"); error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-clone-closures.stderr b/src/test/ui/feature-gate-clone-closures.stderr deleted file mode 100644 index 2b594f7faf38..000000000000 --- a/src/test/ui/feature-gate-clone-closures.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0599]: no method named `clone` found for type `[closure@$DIR/feature-gate-clone-closures.rs:16:17: 18:6 a:_]` in the current scope - --> $DIR/feature-gate-clone-closures.rs:20:23 - | -LL | let hello = hello.clone(); //~ ERROR no method named `clone` found for type - | ^^^^^ - | - = note: hello is a function, perhaps you wish to call it - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0599" diff --git a/src/test/ui/feature-gate-compiler-builtins.stderr b/src/test/ui/feature-gate-compiler-builtins.stderr index 3f8ef665d7ad..5330d83c284a 100644 --- a/src/test/ui/feature-gate-compiler-builtins.stderr +++ b/src/test/ui/feature-gate-compiler-builtins.stderr @@ -8,4 +8,4 @@ LL | #![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-concat_idents.stderr b/src/test/ui/feature-gate-concat_idents.stderr index 05e2e33e1915..2f1e3fe6a7d9 100644 --- a/src/test/ui/feature-gate-concat_idents.stderr +++ b/src/test/ui/feature-gate-concat_idents.stderr @@ -16,4 +16,4 @@ LL | let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gate-concat_idents2.stderr index 548e7dbdcca3..9312a6f5b361 100644 --- a/src/test/ui/feature-gate-concat_idents2.stderr +++ b/src/test/ui/feature-gate-concat_idents2.stderr @@ -8,4 +8,4 @@ LL | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gate-concat_idents3.stderr index 2f5411fa7a58..1a86032d8a32 100644 --- a/src/test/ui/feature-gate-concat_idents3.stderr +++ b/src/test/ui/feature-gate-concat_idents3.stderr @@ -16,4 +16,4 @@ LL | assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is no error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-conservative_impl_trait.stderr b/src/test/ui/feature-gate-conservative_impl_trait.stderr deleted file mode 100644 index 68cd13446809..000000000000 --- a/src/test/ui/feature-gate-conservative_impl_trait.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: `impl Trait` in return position is experimental (see issue #34511) - --> $DIR/feature-gate-conservative_impl_trait.rs:11:13 - | -LL | fn foo() -> impl Fn() { || {} } - | ^^^^^^^^^ - | - = help: add #![feature(conservative_impl_trait)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-const_fn.stderr b/src/test/ui/feature-gate-const_fn.stderr index 09d377c0ace5..d7c00a3e0cb4 100644 --- a/src/test/ui/feature-gate-const_fn.stderr +++ b/src/test/ui/feature-gate-const_fn.stderr @@ -58,5 +58,5 @@ LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable error: aborting due to 8 previous errors -You've got a few errors: E0379, E0658 -If you want more information on an error, try using "rustc --explain E0379" +Some errors occurred: E0379, E0658. +For more information about an error, try `rustc --explain E0379`. diff --git a/src/test/ui/feature-gate-copy-closures.stderr b/src/test/ui/feature-gate-copy-closures.stderr deleted file mode 100644 index b06ada022387..000000000000 --- a/src/test/ui/feature-gate-copy-closures.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0382]: use of moved value: `hello` - --> $DIR/feature-gate-copy-closures.rs:18:9 - | -LL | let b = hello; - | - value moved here -LL | let c = hello; //~ ERROR use of moved value: `hello` [E0382] - | ^ value used here after move - | - = note: move occurs because `hello` has type `[closure@$DIR/feature-gate-copy-closures.rs:13:17: 15:6 a:&i32]`, which does not implement the `Copy` trait - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0382" diff --git a/src/test/ui/feature-gate-crate_in_paths.stderr b/src/test/ui/feature-gate-crate_in_paths.stderr index 21ae346e9c8c..1d0eed531987 100644 --- a/src/test/ui/feature-gate-crate_in_paths.stderr +++ b/src/test/ui/feature-gate-crate_in_paths.stderr @@ -8,4 +8,4 @@ LL | let _ = ::crate::S; //~ ERROR `crate` in paths is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gate-crate_visibility_modifier.stderr index e5e7c8c74206..d0ee40504fb2 100644 --- a/src/test/ui/feature-gate-crate_visibility_modifier.stderr +++ b/src/test/ui/feature-gate-crate_visibility_modifier.stderr @@ -8,4 +8,4 @@ LL | crate struct Bender { //~ ERROR `crate` visibility modifier is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gate-custom_attribute.stderr index dd428e89ea27..36f5898f1c70 100644 --- a/src/test/ui/feature-gate-custom_attribute.stderr +++ b/src/test/ui/feature-gate-custom_attribute.stderr @@ -104,4 +104,4 @@ LL | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown error: aborting due to 13 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gate-custom_attribute2.rs index 0d89c52d885f..30fd89f091b4 100644 --- a/src/test/ui/feature-gate-custom_attribute2.rs +++ b/src/test/ui/feature-gate-custom_attribute2.rs @@ -10,16 +10,9 @@ // This test ensures that attributes on formals in generic parameter // lists are included when we are checking for unstable attributes. -// -// Note that feature(generic_param_attrs) *is* enabled here. We are -// checking feature-gating of the attributes themselves, not the -// capability to parse such attributes in that context. // gate-test-custom_attribute -#![feature(generic_param_attrs)] -#![allow(dead_code)] - struct StLt<#[lt_struct] 'a>(&'a u32); //~^ ERROR The attribute `lt_struct` is currently unknown to the compiler struct StTy<#[ty_struct] I>(I); diff --git a/src/test/ui/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gate-custom_attribute2.stderr index 29cde7042f60..1c1f50366d64 100644 --- a/src/test/ui/feature-gate-custom_attribute2.stderr +++ b/src/test/ui/feature-gate-custom_attribute2.stderr @@ -1,5 +1,5 @@ error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:23:13 + --> $DIR/feature-gate-custom_attribute2.rs:16:13 | LL | struct StLt<#[lt_struct] 'a>(&'a u32); | ^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | struct StLt<#[lt_struct] 'a>(&'a u32); = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:25:13 + --> $DIR/feature-gate-custom_attribute2.rs:18:13 | LL | struct StTy<#[ty_struct] I>(I); | ^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | struct StTy<#[ty_struct] I>(I); = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:28:11 + --> $DIR/feature-gate-custom_attribute2.rs:21:11 | LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } | ^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:30:11 + --> $DIR/feature-gate-custom_attribute2.rs:23:11 | LL | enum EnTy<#[ty_enum] J> { A(J), B } | ^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | enum EnTy<#[ty_enum] J> { A(J), B } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:33:12 + --> $DIR/feature-gate-custom_attribute2.rs:26:12 | LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } | ^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:35:12 + --> $DIR/feature-gate-custom_attribute2.rs:28:12 | LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } | ^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:38:11 + --> $DIR/feature-gate-custom_attribute2.rs:31:11 | LL | type TyLt<#[lt_type] 'd> = &'d u32; | ^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | type TyLt<#[lt_type] 'd> = &'d u32; = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:40:11 + --> $DIR/feature-gate-custom_attribute2.rs:33:11 | LL | type TyTy<#[ty_type] L> = (L, ); | ^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | type TyTy<#[ty_type] L> = (L, ); = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:43:6 + --> $DIR/feature-gate-custom_attribute2.rs:36:6 | LL | impl<#[lt_inherent] 'e> StLt<'e> { } | ^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | impl<#[lt_inherent] 'e> StLt<'e> { } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:45:6 + --> $DIR/feature-gate-custom_attribute2.rs:38:6 | LL | impl<#[ty_inherent] M> StTy { } | ^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | impl<#[ty_inherent] M> StTy { } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:48:6 + --> $DIR/feature-gate-custom_attribute2.rs:41:6 | LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { | ^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:52:6 + --> $DIR/feature-gate-custom_attribute2.rs:45:6 | LL | impl<#[ty_impl_for] N> TrTy for StTy { | ^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | impl<#[ty_impl_for] N> TrTy for StTy { = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:57:9 + --> $DIR/feature-gate-custom_attribute2.rs:50:9 | LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } | ^^^^^^^^ @@ -103,7 +103,7 @@ LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:59:9 + --> $DIR/feature-gate-custom_attribute2.rs:52:9 | LL | fn f_ty<#[ty_fn] O>(_: O) { } | ^^^^^^^^ @@ -111,7 +111,7 @@ LL | fn f_ty<#[ty_fn] O>(_: O) { } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:63:13 + --> $DIR/feature-gate-custom_attribute2.rs:56:13 | LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } | ^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:65:13 + --> $DIR/feature-gate-custom_attribute2.rs:58:13 | LL | fn m_ty<#[ty_meth] P>(_: P) { } | ^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | fn m_ty<#[ty_meth] P>(_: P) { } = help: add #![feature(custom_attribute)] to the crate attributes to enable error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/feature-gate-custom_attribute2.rs:70:19 + --> $DIR/feature-gate-custom_attribute2.rs:63:19 | LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 | ^^^^^^^^^ @@ -136,4 +136,4 @@ LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 error: aborting due to 17 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-custom_derive.stderr b/src/test/ui/feature-gate-custom_derive.stderr index 18c8a081b235..e633a5a9c993 100644 --- a/src/test/ui/feature-gate-custom_derive.stderr +++ b/src/test/ui/feature-gate-custom_derive.stderr @@ -8,4 +8,4 @@ LL | #[derive_Clone] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-decl_macro.stderr b/src/test/ui/feature-gate-decl_macro.stderr index 6438e81610e8..56c0dea02369 100644 --- a/src/test/ui/feature-gate-decl_macro.stderr +++ b/src/test/ui/feature-gate-decl_macro.stderr @@ -8,4 +8,4 @@ LL | macro m() {} //~ ERROR `macro` is experimental (see issue #39412) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gate-doc_cfg.stderr index 0eaaab03eb58..5839e1dd611e 100644 --- a/src/test/ui/feature-gate-doc_cfg.stderr +++ b/src/test/ui/feature-gate-doc_cfg.stderr @@ -8,4 +8,4 @@ LL | #[doc(cfg(unix))] //~ ERROR: #[doc(cfg(...))] is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-doc_masked.stderr b/src/test/ui/feature-gate-doc_masked.stderr index f8885587115f..043397efde25 100644 --- a/src/test/ui/feature-gate-doc_masked.stderr +++ b/src/test/ui/feature-gate-doc_masked.stderr @@ -8,4 +8,4 @@ LL | #[doc(masked)] //~ ERROR: #[doc(masked)] is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gate-doc_spotlight.stderr index ed69f7edf0b5..98e7f38a4418 100644 --- a/src/test/ui/feature-gate-doc_spotlight.stderr +++ b/src/test/ui/feature-gate-doc_spotlight.stderr @@ -8,4 +8,4 @@ LL | #[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr deleted file mode 100644 index ef88d3307d23..000000000000 --- a/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: `..=` syntax in patterns is experimental (see issue #28237) - --> $DIR/feature-gate-dotdoteq_in_patterns.rs:13:9 - | -LL | 0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental - | ^^^^^^^ - | - = help: add #![feature(dotdoteq_in_patterns)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-dropck-ugeh.stderr b/src/test/ui/feature-gate-dropck-ugeh.stderr index c200de766154..33bb5f2d9897 100644 --- a/src/test/ui/feature-gate-dropck-ugeh.stderr +++ b/src/test/ui/feature-gate-dropck-ugeh.stderr @@ -8,4 +8,4 @@ LL | #[unsafe_destructor_blind_to_params] // This is the UGEH attribute error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr index d8db0bd55367..6e6bdf1cbf0d 100644 --- a/src/test/ui/feature-gate-dyn-trait.stderr +++ b/src/test/ui/feature-gate-dyn-trait.stderr @@ -8,4 +8,4 @@ LL | type A = Box; //~ ERROR `dyn Trait` syntax is unstable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gate-exclusive-range-pattern.stderr index 5a5ecb698a40..27fd49edcc69 100644 --- a/src/test/ui/feature-gate-exclusive-range-pattern.stderr +++ b/src/test/ui/feature-gate-exclusive-range-pattern.stderr @@ -8,4 +8,4 @@ LL | 0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experiment error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generator/unsafe-immovable.rs b/src/test/ui/feature-gate-exhaustive-patterns.rs similarity index 68% rename from src/test/ui/generator/unsafe-immovable.rs rename to src/test/ui/feature-gate-exhaustive-patterns.rs index 45acbf50931b..477dd1b38eb0 100644 --- a/src/test/ui/generator/unsafe-immovable.rs +++ b/src/test/ui/feature-gate-exhaustive-patterns.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generators)] +fn foo() -> Result { + Ok(123) +} fn main() { - static || { //~ ERROR: construction of immovable generator requires unsafe - yield; - }; + let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding } + diff --git a/src/test/ui/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gate-exhaustive-patterns.stderr new file mode 100644 index 000000000000..4afe5b5d5e01 --- /dev/null +++ b/src/test/ui/feature-gate-exhaustive-patterns.stderr @@ -0,0 +1,9 @@ +error[E0005]: refutable pattern in local binding: `Err(_)` not covered + --> $DIR/feature-gate-exhaustive-patterns.rs:16:9 + | +LL | let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding + | ^^^^^^ pattern `Err(_)` not covered + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/feature-gate-extern_absolute_paths.stderr b/src/test/ui/feature-gate-extern_absolute_paths.stderr index 730cfb9747ba..7a996abc7675 100644 --- a/src/test/ui/feature-gate-extern_absolute_paths.stderr +++ b/src/test/ui/feature-gate-extern_absolute_paths.stderr @@ -12,5 +12,5 @@ LL | let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve error: aborting due to 2 previous errors -You've got a few errors: E0432, E0433 -If you want more information on an error, try using "rustc --explain E0432" +Some errors occurred: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/feature-gate-extern_in_paths.stderr b/src/test/ui/feature-gate-extern_in_paths.stderr index 11387e81de2b..535ed94565c6 100644 --- a/src/test/ui/feature-gate-extern_in_paths.stderr +++ b/src/test/ui/feature-gate-extern_in_paths.stderr @@ -8,4 +8,4 @@ LL | let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is ex error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-extern_types.stderr b/src/test/ui/feature-gate-extern_types.stderr index 6dabd6ab4a40..47c74bda1779 100644 --- a/src/test/ui/feature-gate-extern_types.stderr +++ b/src/test/ui/feature-gate-extern_types.stderr @@ -8,4 +8,4 @@ LL | type T; //~ ERROR extern types are experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-external_doc.stderr b/src/test/ui/feature-gate-external_doc.stderr index 0582548b5ba7..272380f2336e 100644 --- a/src/test/ui/feature-gate-external_doc.stderr +++ b/src/test/ui/feature-gate-external_doc.stderr @@ -8,4 +8,4 @@ LL | #[doc(include="asdf.md")] //~ ERROR: #[doc(include = "...")] is experimenta error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr index a9952ff4fac1..a2c1dedff385 100644 --- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr +++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr @@ -4,3 +4,5 @@ error: compilation successful LL | fn main() {} //~ ERROR compilation successful | ^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr index 4772cf28f6c1..431c57abd265 100644 --- a/src/test/ui/feature-gate-fn_must_use.stderr +++ b/src/test/ui/feature-gate-fn_must_use.stderr @@ -20,3 +20,5 @@ error: compilation successful LL | fn main() {} //~ ERROR compilation successful | ^^^^^^^^^^^^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate-fundamental.stderr b/src/test/ui/feature-gate-fundamental.stderr index 2e91f1abbbd3..ac8430d7c1c0 100644 --- a/src/test/ui/feature-gate-fundamental.stderr +++ b/src/test/ui/feature-gate-fundamental.stderr @@ -8,4 +8,4 @@ LL | #[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-generators.stderr b/src/test/ui/feature-gate-generators.stderr index ec7aad53b764..91749894eb64 100644 --- a/src/test/ui/feature-gate-generators.stderr +++ b/src/test/ui/feature-gate-generators.stderr @@ -8,4 +8,4 @@ LL | yield true; //~ ERROR yield syntax is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gate-generic_associated_types.stderr index f545da0be968..5f23def88eb0 100644 --- a/src/test/ui/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gate-generic_associated_types.stderr @@ -32,4 +32,4 @@ LL | type Pointer2 = Box; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-generic_param_attrs.stderr b/src/test/ui/feature-gate-generic_param_attrs.stderr deleted file mode 100644 index 2d05d96549cd..000000000000 --- a/src/test/ui/feature-gate-generic_param_attrs.stderr +++ /dev/null @@ -1,139 +0,0 @@ -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:22:13 - | -LL | struct StLt<#[rustc_lt_struct] 'a>(&'a u32); - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:24:13 - | -LL | struct StTy<#[rustc_ty_struct] I>(I); - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:27:11 - | -LL | enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B } - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:29:11 - | -LL | enum EnTy<#[rustc_ty_enum] J> { A(J), B } - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:32:12 - | -LL | trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } - | ^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:34:12 - | -LL | trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); } - | ^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:37:11 - | -LL | type TyLt<#[rustc_lt_type] 'd> = &'d u32; - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:39:11 - | -LL | type TyTy<#[rustc_ty_type] L> = (L, ); - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:42:6 - | -LL | impl<#[rustc_lt_inherent] 'e> StLt<'e> { } - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:44:6 - | -LL | impl<#[rustc_ty_inherent] M> StTy { } - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:47:6 - | -LL | impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> { - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:51:6 - | -LL | impl<#[rustc_ty_impl_for] N> TrTy for StTy { - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:56:9 - | -LL | fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } - | ^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:58:9 - | -LL | fn f_ty<#[rustc_ty_fn] O>(_: O) { } - | ^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:62:13 - | -LL | fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on type parameter bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:64:13 - | -LL | fn m_ty<#[rustc_ty_meth] P>(_: P) { } - | ^^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error[E0658]: attributes on lifetime bindings are experimental (see issue #34761) - --> $DIR/feature-gate-generic_param_attrs.rs:69:19 - | -LL | where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 - | ^^^^^^^^^^^^^^^ - | - = help: add #![feature(generic_param_attrs)] to the crate attributes to enable - -error: aborting due to 17 previous errors - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-global_allocator.stderr b/src/test/ui/feature-gate-global_allocator.stderr index 400af3a33bd4..5a3fd67d27bc 100644 --- a/src/test/ui/feature-gate-global_allocator.stderr +++ b/src/test/ui/feature-gate-global_allocator.stderr @@ -8,4 +8,4 @@ LL | #[global_allocator] //~ ERROR: attribute is an experimental feature error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-global_asm.stderr b/src/test/ui/feature-gate-global_asm.stderr index b506a8e60d7b..2219d49a2636 100644 --- a/src/test/ui/feature-gate-global_asm.stderr +++ b/src/test/ui/feature-gate-global_asm.stderr @@ -8,4 +8,4 @@ LL | global_asm!(""); //~ ERROR `global_asm!` is not stable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-i128_type.stderr b/src/test/ui/feature-gate-i128_type.stderr deleted file mode 100644 index 31802ff350a1..000000000000 --- a/src/test/ui/feature-gate-i128_type.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0658]: 128-bit integers are not stable (see issue #35118) - --> $DIR/feature-gate-i128_type.rs:12:5 - | -LL | 0i128; //~ ERROR 128-bit integers are not stable - | ^^^^^ - | - = help: add #![feature(i128_type)] to the crate attributes to enable - -error[E0658]: 128-bit integers are not stable (see issue #35118) - --> $DIR/feature-gate-i128_type.rs:16:5 - | -LL | 0u128; //~ ERROR 128-bit integers are not stable - | ^^^^^ - | - = help: add #![feature(i128_type)] to the crate attributes to enable - -error: aborting due to 2 previous errors - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-i128_type2.rs b/src/test/ui/feature-gate-i128_type2.rs deleted file mode 100644 index d3bd810ceb2b..000000000000 --- a/src/test/ui/feature-gate-i128_type2.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// gate-test-i128_type - -fn test1() -> i128 { //~ ERROR 128-bit type is unstable - 0 -} - -fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable - 0 -} - -fn test3() { - let x: i128 = 0; //~ ERROR 128-bit type is unstable -} - -fn test3_2() { - let x: u128 = 0; //~ ERROR 128-bit type is unstable -} - -#[repr(u128)] -enum A { //~ ERROR 128-bit type is unstable - A(u64) -} diff --git a/src/test/ui/feature-gate-i128_type2.stderr b/src/test/ui/feature-gate-i128_type2.stderr deleted file mode 100644 index e3a7cf06cdfd..000000000000 --- a/src/test/ui/feature-gate-i128_type2.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0658]: 128-bit type is unstable (see issue #35118) - --> $DIR/feature-gate-i128_type2.rs:13:15 - | -LL | fn test1() -> i128 { //~ ERROR 128-bit type is unstable - | ^^^^ - | - = help: add #![feature(i128_type)] to the crate attributes to enable - -error[E0658]: 128-bit type is unstable (see issue #35118) - --> $DIR/feature-gate-i128_type2.rs:17:17 - | -LL | fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable - | ^^^^ - | - = help: add #![feature(i128_type)] to the crate attributes to enable - -error[E0658]: 128-bit type is unstable (see issue #35118) - --> $DIR/feature-gate-i128_type2.rs:22:12 - | -LL | let x: i128 = 0; //~ ERROR 128-bit type is unstable - | ^^^^ - | - = help: add #![feature(i128_type)] to the crate attributes to enable - -error[E0658]: 128-bit type is unstable (see issue #35118) - --> $DIR/feature-gate-i128_type2.rs:26:12 - | -LL | let x: u128 = 0; //~ ERROR 128-bit type is unstable - | ^^^^ - | - = help: add #![feature(i128_type)] to the crate attributes to enable - -error[E0601]: main function not found - -error[E0658]: repr with 128-bit type is unstable (see issue #35118) - --> $DIR/feature-gate-i128_type2.rs:30:1 - | -LL | / enum A { //~ ERROR 128-bit type is unstable -LL | | A(u64) -LL | | } - | |_^ - | - = help: add #![feature(repr128)] to the crate attributes to enable - -error: aborting due to 6 previous errors - -You've got a few errors: E0601, E0658 -If you want more information on an error, try using "rustc --explain E0601" diff --git a/src/test/ui/feature-gate-if_while_or_patterns.stderr b/src/test/ui/feature-gate-if_while_or_patterns.stderr index 6096804190ed..909046812d3b 100644 --- a/src/test/ui/feature-gate-if_while_or_patterns.stderr +++ b/src/test/ui/feature-gate-if_while_or_patterns.stderr @@ -20,4 +20,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-universal.rs b/src/test/ui/feature-gate-in_band_lifetimes-impl.rs similarity index 71% rename from src/test/ui/feature-gate-universal.rs rename to src/test/ui/feature-gate-in_band_lifetimes-impl.rs index e5bdf3a42eb3..3eb2ac1b0085 100644 --- a/src/test/ui/feature-gate-universal.rs +++ b/src/test/ui/feature-gate-in_band_lifetimes-impl.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-universal_impl_trait +#![allow(warnings)] -fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); } -//~^ ERROR `impl Trait` in argument position is experimental +trait MyTrait<'a> { } + +impl<'a> MyTrait<'a> for &u32 { } +//~^ ERROR missing lifetime specifier + +impl<'a> MyTrait<'_> for &'a f32 { } +//~^ ERROR missing lifetime specifier fn main() {} diff --git a/src/test/ui/feature-gate-in_band_lifetimes-impl.stderr b/src/test/ui/feature-gate-in_band_lifetimes-impl.stderr new file mode 100644 index 000000000000..95bf81f41f80 --- /dev/null +++ b/src/test/ui/feature-gate-in_band_lifetimes-impl.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/feature-gate-in_band_lifetimes-impl.rs:15:26 + | +LL | impl<'a> MyTrait<'a> for &u32 { } + | ^ expected lifetime parameter + +error[E0106]: missing lifetime specifier + --> $DIR/feature-gate-in_band_lifetimes-impl.rs:18:18 + | +LL | impl<'a> MyTrait<'_> for &'a f32 { } + | ^^ expected lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gate-in_band_lifetimes.stderr index 2b72d13ae5ef..cc0855306e16 100644 --- a/src/test/ui/feature-gate-in_band_lifetimes.stderr +++ b/src/test/ui/feature-gate-in_band_lifetimes.stderr @@ -102,4 +102,4 @@ LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } error: aborting due to 17 previous errors -If you want more information on this error, try using "rustc --explain E0261" +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/feature-gate-intrinsics.stderr b/src/test/ui/feature-gate-intrinsics.stderr index bd8774a0941f..e583569cb99f 100644 --- a/src/test/ui/feature-gate-intrinsics.stderr +++ b/src/test/ui/feature-gate-intrinsics.stderr @@ -19,4 +19,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-lang-items.stderr b/src/test/ui/feature-gate-lang-items.stderr index 3c7000447d94..ef3e79472808 100644 --- a/src/test/ui/feature-gate-lang-items.stderr +++ b/src/test/ui/feature-gate-lang-items.stderr @@ -8,4 +8,4 @@ LL | #[lang="foo"] //~ ERROR language items are subject to change error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-link_args.stderr b/src/test/ui/feature-gate-link_args.stderr index dbf5086d02aa..86a2818b3442 100644 --- a/src/test/ui/feature-gate-link_args.stderr +++ b/src/test/ui/feature-gate-link_args.stderr @@ -24,4 +24,4 @@ LL | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"] error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-link_cfg.stderr b/src/test/ui/feature-gate-link_cfg.stderr index 91c3a7a21a26..1da8c3e922dd 100644 --- a/src/test/ui/feature-gate-link_cfg.stderr +++ b/src/test/ui/feature-gate-link_cfg.stderr @@ -8,4 +8,4 @@ LL | #[link(name = "foo", cfg(foo))] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-link_llvm_intrinsics.stderr b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr index 4072ce3cefb0..7a9c5955958a 100644 --- a/src/test/ui/feature-gate-link_llvm_intrinsics.stderr +++ b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr @@ -8,4 +8,4 @@ LL | fn sqrt(x: f32) -> f32; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-linkage.stderr b/src/test/ui/feature-gate-linkage.stderr index a598ca97aeee..2fc1a3e1ae53 100644 --- a/src/test/ui/feature-gate-linkage.stderr +++ b/src/test/ui/feature-gate-linkage.stderr @@ -8,4 +8,4 @@ LL | #[linkage = "extern_weak"] static foo: isize; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-linker-flavor.stderr b/src/test/ui/feature-gate-linker-flavor.stderr index d2f124397ccc..b8bccece2927 100644 --- a/src/test/ui/feature-gate-linker-flavor.stderr +++ b/src/test/ui/feature-gate-linker-flavor.stderr @@ -8,4 +8,4 @@ LL | #[used] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-log_syntax.stderr b/src/test/ui/feature-gate-log_syntax.stderr index 070fe99512e5..d9934be778e6 100644 --- a/src/test/ui/feature-gate-log_syntax.stderr +++ b/src/test/ui/feature-gate-log_syntax.stderr @@ -8,4 +8,4 @@ LL | log_syntax!() //~ ERROR `log_syntax!` is not stable enough error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gate-log_syntax2.stderr index 8aedddcc8862..19e7de1a824f 100644 --- a/src/test/ui/feature-gate-log_syntax2.stderr +++ b/src/test/ui/feature-gate-log_syntax2.stderr @@ -8,4 +8,4 @@ LL | println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr b/src/test/ui/feature-gate-macro-lifetime-matcher.stderr index 0e0977b2d1ac..b7805f6f5fbf 100644 --- a/src/test/ui/feature-gate-macro-lifetime-matcher.stderr +++ b/src/test/ui/feature-gate-macro-lifetime-matcher.stderr @@ -8,4 +8,4 @@ LL | macro_rules! m { ($lt:lifetime) => {} } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-macro-vis-matcher.stderr b/src/test/ui/feature-gate-macro-vis-matcher.stderr index 70a1374b0202..9d98091674e7 100644 --- a/src/test/ui/feature-gate-macro-vis-matcher.stderr +++ b/src/test/ui/feature-gate-macro-vis-matcher.stderr @@ -8,4 +8,4 @@ LL | macro_rules! m { ($v:vis) => {} } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-macro_at_most_once_rep.stderr b/src/test/ui/feature-gate-macro_at_most_once_rep.stderr index 6089b25ac444..8eba07e6c088 100644 --- a/src/test/ui/feature-gate-macro_at_most_once_rep.stderr +++ b/src/test/ui/feature-gate-macro_at_most_once_rep.stderr @@ -8,4 +8,4 @@ LL | macro_rules! m { ($(a)?) => {} } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-main.stderr b/src/test/ui/feature-gate-main.stderr index f6513f203d0d..34c9fd15f7cf 100644 --- a/src/test/ui/feature-gate-main.stderr +++ b/src/test/ui/feature-gate-main.stderr @@ -8,4 +8,4 @@ LL | fn foo() {} //~ ERROR: declaration of a nonstandard #[main] function may ch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-match_default_bindings.stderr b/src/test/ui/feature-gate-match_default_bindings.stderr deleted file mode 100644 index 51f0b8cd98fd..000000000000 --- a/src/test/ui/feature-gate-match_default_bindings.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: non-reference pattern used to match a reference (see issue #42640) - --> $DIR/feature-gate-match_default_bindings.rs:13:9 - | -LL | Some(n) => {}, - | ^^^^^^^ help: consider using a reference: `&Some(n)` - | - = help: add #![feature(match_default_bindings)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-may-dangle.rs b/src/test/ui/feature-gate-may-dangle.rs index ace9fe9ab275..a67ece044883 100644 --- a/src/test/ui/feature-gate-may-dangle.rs +++ b/src/test/ui/feature-gate-may-dangle.rs @@ -12,8 +12,6 @@ // Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent. -#![feature(generic_param_attrs)] - struct Pt(A); impl<#[may_dangle] A> Drop for Pt { //~^ ERROR may_dangle has unstable semantics and may be removed in the future diff --git a/src/test/ui/feature-gate-may-dangle.stderr b/src/test/ui/feature-gate-may-dangle.stderr index 555f4f456140..aad725dfe65e 100644 --- a/src/test/ui/feature-gate-may-dangle.stderr +++ b/src/test/ui/feature-gate-may-dangle.stderr @@ -1,5 +1,5 @@ error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761) - --> $DIR/feature-gate-may-dangle.rs:18:6 + --> $DIR/feature-gate-may-dangle.rs:16:6 | LL | impl<#[may_dangle] A> Drop for Pt { | ^^^^^^^^^^^^^ @@ -8,4 +8,4 @@ LL | impl<#[may_dangle] A> Drop for Pt { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-naked_functions.stderr b/src/test/ui/feature-gate-naked_functions.stderr index d4ba8ff4d73c..a2d3dfc83ae3 100644 --- a/src/test/ui/feature-gate-naked_functions.stderr +++ b/src/test/ui/feature-gate-naked_functions.stderr @@ -16,4 +16,4 @@ LL | #[naked] error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-needs-allocator.stderr b/src/test/ui/feature-gate-needs-allocator.stderr index a526873f42d3..13665b2a0eb2 100644 --- a/src/test/ui/feature-gate-needs-allocator.stderr +++ b/src/test/ui/feature-gate-needs-allocator.stderr @@ -8,4 +8,4 @@ LL | #![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-negate-unsigned.stderr b/src/test/ui/feature-gate-negate-unsigned.stderr index 3c3056f9748b..1025b56f55bc 100644 --- a/src/test/ui/feature-gate-negate-unsigned.stderr +++ b/src/test/ui/feature-gate-negate-unsigned.stderr @@ -12,4 +12,4 @@ LL | let _y = -x; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0600" +For more information about this error, try `rustc --explain E0600`. diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr deleted file mode 100644 index e0a194ca6e99..000000000000 --- a/src/test/ui/feature-gate-never_type.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0658]: The `!` type is experimental (see issue #35121) - --> $DIR/feature-gate-never_type.rs:17:17 - | -LL | type Ma = (u32, !, i32); //~ ERROR type is experimental - | ^ - | - = help: add #![feature(never_type)] to the crate attributes to enable - -error[E0658]: The `!` type is experimental (see issue #35121) - --> $DIR/feature-gate-never_type.rs:18:20 - | -LL | type Meeshka = Vec; //~ ERROR type is experimental - | ^ - | - = help: add #![feature(never_type)] to the crate attributes to enable - -error[E0658]: The `!` type is experimental (see issue #35121) - --> $DIR/feature-gate-never_type.rs:19:16 - | -LL | type Mow = &fn(!) -> !; //~ ERROR type is experimental - | ^ - | - = help: add #![feature(never_type)] to the crate attributes to enable - -error[E0658]: The `!` type is experimental (see issue #35121) - --> $DIR/feature-gate-never_type.rs:20:19 - | -LL | type Skwoz = &mut !; //~ ERROR type is experimental - | ^ - | - = help: add #![feature(never_type)] to the crate attributes to enable - -error[E0658]: The `!` type is experimental (see issue #35121) - --> $DIR/feature-gate-never_type.rs:23:16 - | -LL | type Wub = !; //~ ERROR type is experimental - | ^ - | - = help: add #![feature(never_type)] to the crate attributes to enable - -error: aborting due to 5 previous errors - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-nll.stderr b/src/test/ui/feature-gate-nll.stderr index 8194680cef7a..f7b431d19be7 100644 --- a/src/test/ui/feature-gate-nll.stderr +++ b/src/test/ui/feature-gate-nll.stderr @@ -8,4 +8,4 @@ LL | x = 22; //~ ERROR cannot assign to `x` because it is borrowed [E0506] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/feature-gate-no-debug.stderr b/src/test/ui/feature-gate-no-debug.stderr index 943d3530d156..55fad0d99cf0 100644 --- a/src/test/ui/feature-gate-no-debug.stderr +++ b/src/test/ui/feature-gate-no-debug.stderr @@ -8,4 +8,4 @@ LL | #[no_debug] //~ ERROR the `#[no_debug]` attribute was error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-no_core.stderr b/src/test/ui/feature-gate-no_core.stderr index caadb98a7107..c8813dcd991f 100644 --- a/src/test/ui/feature-gate-no_core.stderr +++ b/src/test/ui/feature-gate-no_core.stderr @@ -8,4 +8,4 @@ LL | #![no_core] //~ ERROR no_core is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gate-non_ascii_idents.stderr index 38a2623267fd..69d7e38d431f 100644 --- a/src/test/ui/feature-gate-non_ascii_idents.stderr +++ b/src/test/ui/feature-gate-non_ascii_idents.stderr @@ -110,4 +110,4 @@ LL | fn qüx(); //~ ERROR non-ascii idents error: aborting due to 13 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gate-non_exhaustive.stderr index 468ef6e273c3..67f103d852a0 100644 --- a/src/test/ui/feature-gate-non_exhaustive.stderr +++ b/src/test/ui/feature-gate-non_exhaustive.stderr @@ -8,4 +8,4 @@ LL | #[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see i error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr index ad8b12ea2548..253811400efd 100644 --- a/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr +++ b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr @@ -8,4 +8,4 @@ LL | #[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gate-on-unimplemented.stderr index 7cc956fa1f0e..a059f5e3c4d2 100644 --- a/src/test/ui/feature-gate-on-unimplemented.stderr +++ b/src/test/ui/feature-gate-on-unimplemented.stderr @@ -8,4 +8,4 @@ LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gate-optin-builtin-traits.stderr index ec7856338fb9..8bd07ffd1229 100644 --- a/src/test/ui/feature-gate-optin-builtin-traits.stderr +++ b/src/test/ui/feature-gate-optin-builtin-traits.stderr @@ -16,4 +16,4 @@ LL | impl !DummyTrait for DummyStruct {} error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-overlapping_marker_traits.stderr b/src/test/ui/feature-gate-overlapping_marker_traits.stderr index 2b30691c40d8..040ad019b9fc 100644 --- a/src/test/ui/feature-gate-overlapping_marker_traits.stderr +++ b/src/test/ui/feature-gate-overlapping_marker_traits.stderr @@ -8,4 +8,4 @@ LL | impl MyMarker for T {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/feature-gate-pattern_parentheses.stderr b/src/test/ui/feature-gate-pattern_parentheses.stderr index 4fc1441a0fad..fce024d20f4f 100644 --- a/src/test/ui/feature-gate-pattern_parentheses.stderr +++ b/src/test/ui/feature-gate-pattern_parentheses.stderr @@ -8,4 +8,4 @@ LL | (pat) => {} //~ ERROR parentheses in patterns are unstable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-placement-expr.rs b/src/test/ui/feature-gate-placement-expr.rs deleted file mode 100644 index e3478876763b..000000000000 --- a/src/test/ui/feature-gate-placement-expr.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// gate-test-placement_in_syntax - -// Check that `in PLACE { EXPR }` is feature-gated. -// -// See also feature-gate-box-expr.rs -// -// (Note that the two tests are separated since the checks appear to -// be performed at distinct phases, with an abort_if_errors call -// separating them.) - -fn main() { - use std::boxed::HEAP; - - let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental - println!("x: {}", x); -} diff --git a/src/test/ui/feature-gate-placement-expr.stderr b/src/test/ui/feature-gate-placement-expr.stderr deleted file mode 100644 index 96b38812cb0b..000000000000 --- a/src/test/ui/feature-gate-placement-expr.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: placement-in expression syntax is experimental and subject to change. (see issue #27779) - --> $DIR/feature-gate-placement-expr.rs:24:13 - | -LL | let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental - | ^^^^^^^^^^^ - | - = help: add #![feature(placement_in_syntax)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-plugin.stderr b/src/test/ui/feature-gate-plugin.stderr index f9a98b130440..366e293c1826 100644 --- a/src/test/ui/feature-gate-plugin.stderr +++ b/src/test/ui/feature-gate-plugin.stderr @@ -8,4 +8,4 @@ LL | #![plugin(foo)] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gate-plugin_registrar.stderr index 731cca8f6a92..3e6ffb6ef1a5 100644 --- a/src/test/ui/feature-gate-plugin_registrar.stderr +++ b/src/test/ui/feature-gate-plugin_registrar.stderr @@ -8,4 +8,4 @@ LL | pub fn registrar() {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-prelude_import.stderr b/src/test/ui/feature-gate-prelude_import.stderr index 6b791ee23808..6841df54067a 100644 --- a/src/test/ui/feature-gate-prelude_import.stderr +++ b/src/test/ui/feature-gate-prelude_import.stderr @@ -8,4 +8,4 @@ LL | #[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-profiler-runtime.stderr b/src/test/ui/feature-gate-profiler-runtime.stderr index ea321591143e..dd395742b4f4 100644 --- a/src/test/ui/feature-gate-profiler-runtime.stderr +++ b/src/test/ui/feature-gate-profiler-runtime.stderr @@ -8,4 +8,4 @@ LL | #![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-raw-identifiers.rs b/src/test/ui/feature-gate-raw-identifiers.rs new file mode 100644 index 000000000000..38024feb432d --- /dev/null +++ b/src/test/ui/feature-gate-raw-identifiers.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let r#foo = 3; //~ ERROR raw identifiers are experimental and subject to change + println!("{}", foo); +} diff --git a/src/test/ui/feature-gate-raw-identifiers.stderr b/src/test/ui/feature-gate-raw-identifiers.stderr new file mode 100644 index 000000000000..02eff7247c47 --- /dev/null +++ b/src/test/ui/feature-gate-raw-identifiers.stderr @@ -0,0 +1,11 @@ +error[E0658]: raw identifiers are experimental and subject to change (see issue #48589) + --> $DIR/feature-gate-raw-identifiers.rs:12:9 + | +LL | let r#foo = 3; //~ ERROR raw identifiers are experimental and subject to change + | ^^^^^ + | + = help: add #![feature(raw_identifiers)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-repr-simd.stderr b/src/test/ui/feature-gate-repr-simd.stderr index 280dc4518dd4..8174f82060a1 100644 --- a/src/test/ui/feature-gate-repr-simd.stderr +++ b/src/test/ui/feature-gate-repr-simd.stderr @@ -8,4 +8,4 @@ LL | #[repr(simd)] //~ error: SIMD types are experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-repr128.stderr b/src/test/ui/feature-gate-repr128.stderr index fef28398df68..29cba831f545 100644 --- a/src/test/ui/feature-gate-repr128.stderr +++ b/src/test/ui/feature-gate-repr128.stderr @@ -10,4 +10,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-repr_transparent.stderr b/src/test/ui/feature-gate-repr_transparent.stderr index 161ab0af3416..a4ffaa266906 100644 --- a/src/test/ui/feature-gate-repr_transparent.stderr +++ b/src/test/ui/feature-gate-repr_transparent.stderr @@ -8,4 +8,4 @@ LL | #[repr(transparent)] //~ error: the `#[repr(transparent)]` attribute is exp error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gate-rustc-attrs.stderr index 6743f328f392..fda95a5b97a5 100644 --- a/src/test/ui/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gate-rustc-attrs.stderr @@ -24,4 +24,4 @@ LL | #[rustc_foo] error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-rustc_const_unstable.stderr b/src/test/ui/feature-gate-rustc_const_unstable.stderr index 25cc2e41016c..fa3f9807a04e 100644 --- a/src/test/ui/feature-gate-rustc_const_unstable.stderr +++ b/src/test/ui/feature-gate-rustc_const_unstable.stderr @@ -8,4 +8,4 @@ LL | #[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gate-sanitizer-runtime.stderr index 6640f59255a8..fc93e1030053 100644 --- a/src/test/ui/feature-gate-sanitizer-runtime.stderr +++ b/src/test/ui/feature-gate-sanitizer-runtime.stderr @@ -8,4 +8,4 @@ LL | #![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-simd.stderr b/src/test/ui/feature-gate-simd.stderr index b4ed7ee43c77..414a5d9eb5d0 100644 --- a/src/test/ui/feature-gate-simd.stderr +++ b/src/test/ui/feature-gate-simd.stderr @@ -8,4 +8,4 @@ LL | #[repr(simd)] //~ ERROR SIMD types are experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-slice-patterns.rs b/src/test/ui/feature-gate-slice-patterns.rs index 625cb2d35155..fd058f651721 100644 --- a/src/test/ui/feature-gate-slice-patterns.rs +++ b/src/test/ui/feature-gate-slice-patterns.rs @@ -8,11 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that slice pattern syntax is gated by `slice_patterns` feature gate +// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate fn main() { let x = [1, 2, 3, 4, 5]; match x { - [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental + [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + } + + let x = [ 1, 2, 3, 4, 5 ]; + match x { + [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized } } diff --git a/src/test/ui/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gate-slice-patterns.stderr index 0f61313e092c..d560dcd54eef 100644 --- a/src/test/ui/feature-gate-slice-patterns.stderr +++ b/src/test/ui/feature-gate-slice-patterns.stderr @@ -1,11 +1,51 @@ -error[E0658]: slice pattern syntax is experimental (see issue #23121) - --> $DIR/feature-gate-slice-patterns.rs:16:9 +error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:16:16 | -LL | [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental - | ^^^^^^^^^^^^ +LL | [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + | ^^ | = help: add #![feature(slice_patterns)] to the crate attributes to enable -error: aborting due to previous error +error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:17:13 + | +LL | [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + | ^^ + | + = help: add #![feature(slice_patterns)] to the crate attributes to enable -If you want more information on this error, try using "rustc --explain E0658" +error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:18:10 + | +LL | [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + | ^^ + | + = help: add #![feature(slice_patterns)] to the crate attributes to enable + +error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:23:11 + | +LL | [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + | ^^ + | + = help: add #![feature(slice_patterns)] to the crate attributes to enable + +error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:24:14 + | +LL | [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + | ^^ + | + = help: add #![feature(slice_patterns)] to the crate attributes to enable + +error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121) + --> $DIR/feature-gate-slice-patterns.rs:25:17 + | +LL | [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + | ^^ + | + = help: add #![feature(slice_patterns)] to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-start.stderr b/src/test/ui/feature-gate-start.stderr index 533cc31fb0a3..cf590d2a0e3a 100644 --- a/src/test/ui/feature-gate-start.stderr +++ b/src/test/ui/feature-gate-start.stderr @@ -8,4 +8,4 @@ LL | fn foo() {} //~ ERROR: a #[start] function is an experimental feature error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gate-static-nobundle.stderr index d872b8f4c52b..fd9f2b371f60 100644 --- a/src/test/ui/feature-gate-static-nobundle.stderr +++ b/src/test/ui/feature-gate-static-nobundle.stderr @@ -8,4 +8,4 @@ LL | #[link(name="foo", kind="static-nobundle")] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-stmt_expr_attributes.rs b/src/test/ui/feature-gate-stmt_expr_attributes.rs index 831d8862e109..55706938ae8f 100644 --- a/src/test/ui/feature-gate-stmt_expr_attributes.rs +++ b/src/test/ui/feature-gate-stmt_expr_attributes.rs @@ -9,6 +9,6 @@ // except according to those terms. const X: i32 = #[allow(dead_code)] 8; -//~^ ERROR attributes on non-item statements and expressions are experimental. (see issue #15701) +//~^ ERROR attributes on expressions are experimental. (see issue #15701) fn main() {} diff --git a/src/test/ui/feature-gate-stmt_expr_attributes.stderr b/src/test/ui/feature-gate-stmt_expr_attributes.stderr index 8aca511ec160..ad5c263403df 100644 --- a/src/test/ui/feature-gate-stmt_expr_attributes.stderr +++ b/src/test/ui/feature-gate-stmt_expr_attributes.stderr @@ -1,4 +1,4 @@ -error[E0658]: attributes on non-item statements and expressions are experimental. (see issue #15701) +error[E0658]: attributes on expressions are experimental. (see issue #15701) --> $DIR/feature-gate-stmt_expr_attributes.rs:11:16 | LL | const X: i32 = #[allow(dead_code)] 8; @@ -8,4 +8,4 @@ LL | const X: i32 = #[allow(dead_code)] 8; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-target_feature.stderr b/src/test/ui/feature-gate-target_feature.stderr index 0b7313de04d9..0f31abf7b42c 100644 --- a/src/test/ui/feature-gate-target_feature.stderr +++ b/src/test/ui/feature-gate-target_feature.stderr @@ -8,4 +8,4 @@ LL | #[target_feature = "+sse2"] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-thread_local.stderr b/src/test/ui/feature-gate-thread_local.stderr index 0bbcb6a24b21..9b44c3f95901 100644 --- a/src/test/ui/feature-gate-thread_local.stderr +++ b/src/test/ui/feature-gate-thread_local.stderr @@ -8,4 +8,4 @@ LL | #[thread_local] //~ ERROR `#[thread_local]` is an experimental feature error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-trace_macros.stderr b/src/test/ui/feature-gate-trace_macros.stderr index 56d69bbbb405..a31f618bbbe9 100644 --- a/src/test/ui/feature-gate-trace_macros.stderr +++ b/src/test/ui/feature-gate-trace_macros.stderr @@ -8,4 +8,4 @@ LL | trace_macros!(true); //~ ERROR: `trace_macros` is not stable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-conservative_impl_trait.rs b/src/test/ui/feature-gate-try_reserve.rs similarity index 79% rename from src/test/ui/feature-gate-conservative_impl_trait.rs rename to src/test/ui/feature-gate-try_reserve.rs index 7a3ae639bfc8..9322dbd272f7 100644 --- a/src/test/ui/feature-gate-conservative_impl_trait.rs +++ b/src/test/ui/feature-gate-try_reserve.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo() -> impl Fn() { || {} } -//~^ ERROR `impl Trait` in return position is experimental - -fn main() {} +fn main() { + let v = Vec::new(); + v.try_reserve(10); //~ ERROR: use of unstable library feature 'try_reserve' +} diff --git a/src/test/ui/feature-gate-try_reserve.stderr b/src/test/ui/feature-gate-try_reserve.stderr new file mode 100644 index 000000000000..928d266b37ae --- /dev/null +++ b/src/test/ui/feature-gate-try_reserve.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'try_reserve': new API (see issue #48043) + --> $DIR/feature-gate-try_reserve.rs:13:7 + | +LL | v.try_reserve(10); //~ ERROR: use of unstable library feature 'try_reserve' + | ^^^^^^^^^^^ + | + = help: add #![feature(try_reserve)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-type_ascription.stderr b/src/test/ui/feature-gate-type_ascription.stderr index bd0ff84c4385..2bd475b68b20 100644 --- a/src/test/ui/feature-gate-type_ascription.stderr +++ b/src/test/ui/feature-gate-type_ascription.stderr @@ -8,4 +8,4 @@ LL | let a = 10: u8; //~ ERROR type ascription is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr index 5d1f4d092279..6dfcdfc25671 100644 --- a/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr +++ b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr @@ -32,4 +32,4 @@ LL | extern "rust-call" fn call_once(&self, args: ()) -> () {} error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr index 7eb938110f3a..cc8615d3620e 100644 --- a/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr +++ b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr @@ -24,4 +24,4 @@ LL | f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits' error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr index 5db2ea6167cb..26dd983e877d 100644 --- a/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr +++ b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr @@ -24,4 +24,4 @@ LL | FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gate-unboxed-closures.stderr index 54e75ce8ef4c..a5b1ed9bbc4f 100644 --- a/src/test/ui/feature-gate-unboxed-closures.stderr +++ b/src/test/ui/feature-gate-unboxed-closures.stderr @@ -10,4 +10,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-underscore-imports.rs b/src/test/ui/feature-gate-underscore-imports.rs new file mode 100644 index 000000000000..ceb8afe124a8 --- /dev/null +++ b/src/test/ui/feature-gate-underscore-imports.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable +use std::vec as _; //~ ERROR renaming imports with `_` is unstable + +fn main() {} diff --git a/src/test/ui/feature-gate-underscore-imports.stderr b/src/test/ui/feature-gate-underscore-imports.stderr new file mode 100644 index 000000000000..2eea95260d5e --- /dev/null +++ b/src/test/ui/feature-gate-underscore-imports.stderr @@ -0,0 +1,19 @@ +error[E0658]: renaming extern crates with `_` is unstable (see issue #48216) + --> $DIR/feature-gate-underscore-imports.rs:11:1 + | +LL | extern crate std as _; //~ ERROR renaming extern crates with `_` is unstable + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(underscore_imports)] to the crate attributes to enable + +error[E0658]: renaming imports with `_` is unstable (see issue #48216) + --> $DIR/feature-gate-underscore-imports.rs:12:5 + | +LL | use std::vec as _; //~ ERROR renaming imports with `_` is unstable + | ^^^^^^^^^^^^^ + | + = help: add #![feature(underscore_imports)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-underscore-lifetimes.stderr b/src/test/ui/feature-gate-underscore-lifetimes.stderr deleted file mode 100644 index b92662f8a82e..000000000000 --- a/src/test/ui/feature-gate-underscore-lifetimes.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: underscore lifetimes are unstable (see issue #44524) - --> $DIR/feature-gate-underscore-lifetimes.rs:13:23 - | -LL | fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable - | ^^ - | - = help: add #![feature(underscore_lifetimes)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-universal.stderr b/src/test/ui/feature-gate-universal.stderr deleted file mode 100644 index 8d2e81055fe5..000000000000 --- a/src/test/ui/feature-gate-universal.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: `impl Trait` in argument position is experimental (see issue #34511) - --> $DIR/feature-gate-universal.rs:13:11 - | -LL | fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); } - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(universal_impl_trait)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/feature-gate-unsized_tuple_coercion.stderr b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr index e0bfab164ff2..bf790a3b0039 100644 --- a/src/test/ui/feature-gate-unsized_tuple_coercion.stderr +++ b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr @@ -8,4 +8,4 @@ LL | let _ : &(Send,) = &((),); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gate-untagged_unions.stderr index eef42e8b6fd6..e0c845b77685 100644 --- a/src/test/ui/feature-gate-untagged_unions.stderr +++ b/src/test/ui/feature-gate-untagged_unions.stderr @@ -30,4 +30,4 @@ LL | | } error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gate-unwind-attributes.stderr index d22b56ca386a..4c6e6f420de3 100644 --- a/src/test/ui/feature-gate-unwind-attributes.stderr +++ b/src/test/ui/feature-gate-unwind-attributes.stderr @@ -8,4 +8,4 @@ LL | #[unwind] //~ ERROR #[unwind] is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-used.stderr b/src/test/ui/feature-gate-used.stderr index 44c7c142c55a..d650b5ebb3b1 100644 --- a/src/test/ui/feature-gate-used.stderr +++ b/src/test/ui/feature-gate-used.stderr @@ -8,4 +8,4 @@ LL | #[used] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-wasm_custom_section.rs b/src/test/ui/feature-gate-wasm_custom_section.rs new file mode 100644 index 000000000000..c695ef4ff068 --- /dev/null +++ b/src/test/ui/feature-gate-wasm_custom_section.rs @@ -0,0 +1,14 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[wasm_custom_section = "foo"] //~ ERROR: attribute is currently unstable +const A: [u8; 2] = [1, 2]; + +fn main() {} diff --git a/src/test/ui/feature-gate-wasm_custom_section.stderr b/src/test/ui/feature-gate-wasm_custom_section.stderr new file mode 100644 index 000000000000..1b4415539f44 --- /dev/null +++ b/src/test/ui/feature-gate-wasm_custom_section.stderr @@ -0,0 +1,11 @@ +error[E0658]: attribute is currently unstable + --> $DIR/feature-gate-wasm_custom_section.rs:11:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: attribute is currently unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(wasm_custom_section)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate-wasm_import_module.rs b/src/test/ui/feature-gate-wasm_import_module.rs new file mode 100644 index 000000000000..c5898a9c1269 --- /dev/null +++ b/src/test/ui/feature-gate-wasm_import_module.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[wasm_import_module = "test"] //~ ERROR: experimental +extern { +} + +fn main() {} diff --git a/src/test/ui/feature-gate-wasm_import_module.stderr b/src/test/ui/feature-gate-wasm_import_module.stderr new file mode 100644 index 000000000000..bae5fa9d5956 --- /dev/null +++ b/src/test/ui/feature-gate-wasm_import_module.stderr @@ -0,0 +1,11 @@ +error[E0658]: experimental attribute + --> $DIR/feature-gate-wasm_import_module.rs:11:1 + | +LL | #[wasm_import_module = "test"] //~ ERROR: experimental + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(wasm_import_module)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs index a34f98f03559..6c2267993387 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: main function not found +// error-pattern: `main` function not found // At time of authorship, a crate-level #![bench] with no `--test` // will cause compilation to error unconditionally with "main function diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr index 1d33bc556113..503ef020d960 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr @@ -1,5 +1,7 @@ -error[E0601]: main function not found +error[E0601]: `main` function not found in crate `issue_43106_gating_of_bench` + | + = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-bench.rs` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 9c4fb79f6f1a..0beed6279871 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -1316,3 +1316,5 @@ LL | | println!("Hello World"); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr index 83f6e016370b..802c5d9384d7 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr @@ -6,3 +6,5 @@ LL | | println!("Hello World"); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs index 24e77bf60a8d..410f960e655f 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs @@ -35,3 +35,5 @@ mod inline { #[inline = "2100"] impl S { } //~^ ERROR attribute should be applied to function } + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr index 40a81171a898..d67d78e31a9d 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error[E0518]: attribute should be applied to function --> $DIR/issue-43106-gating-of-inline.rs:21:1 | @@ -39,7 +37,6 @@ error[E0518]: attribute should be applied to function LL | #[inline = "2100"] impl S { } | ^^^^^^^^^^^^^^^^^^ ---------- not a function -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -You've got a few errors: E0518, E0601 -If you want more information on an error, try using "rustc --explain E0518" +For more information about this error, try `rustc --explain E0518`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs index 3b2dbdefebad..ec3c97beab0f 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs @@ -13,5 +13,9 @@ // `#![macro_escape]` is incompatible with crate-level `#![macro_use]` // already present in issue-43106-gating-of-builtin-attrs. +// must-compile-successfully + #![macro_escape] //~^ WARN macro_escape is a deprecated synonym for macro_use + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr index 5e540f9139eb..d19720397e66 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr @@ -1,13 +1,8 @@ warning: macro_escape is a deprecated synonym for macro_use - --> $DIR/issue-43106-gating-of-macro_escape.rs:16:1 + --> $DIR/issue-43106-gating-of-macro_escape.rs:18:1 | LL | #![macro_escape] | ^^^^^^^^^^^^^^^^ | = help: consider an outer attribute, #[macro_use] mod ... -error[E0601]: main function not found - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0601" diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs index 133f70e0f3b1..5bb8bb024ed5 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs @@ -40,3 +40,5 @@ mod proc_macro_derive2 { #[proc_macro_derive = "2500"] impl S { } //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions } + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr index 5a184897a093..419efb6825a9 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr @@ -34,8 +34,5 @@ error: the `#[proc_macro_derive]` attribute may only be used on bare functions LL | #[proc_macro_derive = "2500"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0601]: main function not found +error: aborting due to 6 previous errors -error: aborting due to 7 previous errors - -If you want more information on this error, try using "rustc --explain E0601" diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs index 10c139863492..0c6cfb5da565 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs @@ -36,3 +36,4 @@ mod rustc_deprecated { //~^ ERROR stability attributes may not be used outside of the standard library } +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr index 1d4530852562..35c15cb6b1ea 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:17:1 | @@ -42,6 +40,5 @@ error: stability attributes may not be used outside of the standard library LL | #[rustc_deprecated = "1500"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0601" diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs index a6eaabf7a383..6415243d0873 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs @@ -35,3 +35,5 @@ mod stable { #[stable = "1300"] impl S { } //~^ ERROR stability attributes may not be used outside of the standard library } + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr index f7f426299dac..21543d1b20af 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-stable.rs:17:1 | @@ -42,6 +40,5 @@ error: stability attributes may not be used outside of the standard library LL | #[stable = "1300"] impl S { } | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0601" diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs index adcbfe77280b..06632396249a 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: main function not found +// error-pattern: `main` function not found // At time of authorship, crate-level #[test] attribute with no // `--test` signals unconditional error complaining of missing main diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr index 1d33bc556113..2ab35be43c57 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr @@ -1,5 +1,7 @@ -error[E0601]: main function not found +error[E0601]: `main` function not found in crate `issue_43106_gating_of_test` + | + = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-test.rs` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs index ff0600deb193..140474d82c88 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs @@ -35,3 +35,5 @@ mod unstable { #[unstable = "1200"] impl S { } //~^ ERROR stability attributes may not be used outside of the standard library } + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr index afa444217119..6124e16f4180 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error: stability attributes may not be used outside of the standard library --> $DIR/issue-43106-gating-of-unstable.rs:17:1 | @@ -42,6 +40,5 @@ error: stability attributes may not be used outside of the standard library LL | #[unstable = "1200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0601" diff --git a/src/test/ui/fmt/send-sync.rs b/src/test/ui/fmt/send-sync.rs index 3f13fd2e4913..424919a0eba6 100644 --- a/src/test/ui/fmt/send-sync.rs +++ b/src/test/ui/fmt/send-sync.rs @@ -15,6 +15,6 @@ fn main() { // `Cell` is not `Sync`, so `&Cell` is neither `Sync` nor `Send`, // `std::fmt::Arguments` used to forget this... let c = std::cell::Cell::new(42); - send(format_args!("{:?}", c)); //~ ERROR Sync` is not satisfied - sync(format_args!("{:?}", c)); //~ ERROR Sync` is not satisfied + send(format_args!("{:?}", c)); //~ ERROR E0277 + sync(format_args!("{:?}", c)); //~ ERROR E0277 } diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr index 0943b64c5c09..807b499155b8 100644 --- a/src/test/ui/fmt/send-sync.stderr +++ b/src/test/ui/fmt/send-sync.stderr @@ -1,7 +1,7 @@ -error[E0277]: the trait bound `*mut std::ops::Fn() + 'static: std::marker::Sync` is not satisfied in `[std::fmt::ArgumentV1<'_>]` +error[E0277]: `*mut std::ops::Fn() + 'static` cannot be shared between threads safely --> $DIR/send-sync.rs:18:5 | -LL | send(format_args!("{:?}", c)); //~ ERROR Sync` is not satisfied +LL | send(format_args!("{:?}", c)); //~ ERROR E0277 | ^^^^ `*mut std::ops::Fn() + 'static` cannot be shared between threads safely | = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut std::ops::Fn() + 'static` @@ -18,10 +18,10 @@ note: required by `send` LL | fn send(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `*mut std::ops::Fn() + 'static: std::marker::Sync` is not satisfied in `std::fmt::Arguments<'_>` +error[E0277]: `*mut std::ops::Fn() + 'static` cannot be shared between threads safely --> $DIR/send-sync.rs:19:5 | -LL | sync(format_args!("{:?}", c)); //~ ERROR Sync` is not satisfied +LL | sync(format_args!("{:?}", c)); //~ ERROR E0277 | ^^^^ `*mut std::ops::Fn() + 'static` cannot be shared between threads safely | = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut std::ops::Fn() + 'static` @@ -40,4 +40,4 @@ LL | fn sync(_: T) {} error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 8f78bb8fa884..dd78baf92750 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,15 +1,15 @@ -error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` +error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` --> $DIR/auto-trait-regions.rs:40:5 | LL | assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied - | ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No` + | ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No` | = help: the following implementations were found: = note: required because it appears within the type `OnlyFooIfStaticRef` = note: required because it appears within the type `&OnlyFooIfStaticRef` = note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}` - = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` + = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` note: required by `assert_foo` --> $DIR/auto-trait-regions.rs:30:1 | @@ -33,5 +33,5 @@ LL | fn assert_foo(f: T) {} error: aborting due to 2 previous errors -You've got a few errors: E0277, E0279 -If you want more information on an error, try using "rustc --explain E0277" +Some errors occurred: E0277, E0279. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs index de10bdef4aee..e56927d81823 100644 --- a/src/test/ui/generator/borrowing.rs +++ b/src/test/ui/generator/borrowing.rs @@ -15,7 +15,7 @@ use std::ops::Generator; fn main() { let _b = { let a = 3; - (|| yield &a).resume() + unsafe { (|| yield &a).resume() } //~^ ERROR: `a` does not live long enough }; diff --git a/src/test/ui/generator/borrowing.stderr b/src/test/ui/generator/borrowing.stderr index a27d950c0459..45d950b5aef6 100644 --- a/src/test/ui/generator/borrowing.stderr +++ b/src/test/ui/generator/borrowing.stderr @@ -1,10 +1,10 @@ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:18:20 + --> $DIR/borrowing.rs:18:29 | -LL | (|| yield &a).resume() - | -- ^ borrowed value does not live long enough - | | - | capture occurs here +LL | unsafe { (|| yield &a).resume() } + | -- ^ borrowed value does not live long enough + | | + | capture occurs here LL | //~^ ERROR: `a` does not live long enough LL | }; | - borrowed value only lives until here @@ -27,4 +27,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs index 0b143d7f5143..b2240fb225f5 100644 --- a/src/test/ui/generator/dropck.rs +++ b/src/test/ui/generator/dropck.rs @@ -23,6 +23,6 @@ fn main() { let _d = ref_.take(); //~ ERROR `ref_` does not live long enough yield; }; - gen.resume(); + unsafe { gen.resume(); } // drops the RefCell and then the Ref, leading to use-after-free } diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr index c4ae9051138b..4a22d299701b 100644 --- a/src/test/ui/generator/dropck.stderr +++ b/src/test/ui/generator/dropck.stderr @@ -14,4 +14,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/generator-with-nll.stderr b/src/test/ui/generator/generator-with-nll.stderr index 49542dd0ac35..7e39d3c54590 100644 --- a/src/test/ui/generator/generator-with-nll.stderr +++ b/src/test/ui/generator/generator-with-nll.stderr @@ -27,4 +27,4 @@ LL | yield (); error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0626" +For more information about this error, try `rustc --explain E0626`. diff --git a/src/test/ui/generator/issue-48048.stderr b/src/test/ui/generator/issue-48048.stderr index 759187667549..f0654685deba 100644 --- a/src/test/ui/generator/issue-48048.stderr +++ b/src/test/ui/generator/issue-48048.stderr @@ -8,4 +8,4 @@ LL | yield; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0626" +For more information about this error, try `rustc --explain E0626`. diff --git a/src/test/ui/generator/no-arguments-on-generators.stderr b/src/test/ui/generator/no-arguments-on-generators.stderr index 6091946f2fa7..6520f8b20231 100644 --- a/src/test/ui/generator/no-arguments-on-generators.stderr +++ b/src/test/ui/generator/no-arguments-on-generators.stderr @@ -6,4 +6,4 @@ LL | let gen = |start| { //~ ERROR generators cannot have explicit arguments error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0628" +For more information about this error, try `rustc --explain E0628`. diff --git a/src/test/ui/generator/not-send-sync.rs b/src/test/ui/generator/not-send-sync.rs index 0419758d8ea1..f0df05ebfdf8 100644 --- a/src/test/ui/generator/not-send-sync.rs +++ b/src/test/ui/generator/not-send-sync.rs @@ -17,14 +17,14 @@ fn main() { fn assert_send(_: T) {} assert_sync(|| { - //~^ ERROR: Sync` is not satisfied + //~^ ERROR: E0277 let a = Cell::new(2); yield; }); let a = Cell::new(2); assert_send(|| { - //~^ ERROR: Sync` is not satisfied + //~^ ERROR: E0277 drop(&a); yield; }); diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 6ca583bf16d6..edf7151f7c4b 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `std::cell::Cell: std::marker::Sync` is not satisfied +error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:26:5 | LL | assert_send(|| { @@ -13,7 +13,7 @@ note: required by `main::assert_send` LL | fn assert_send(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `std::cell::Cell: std::marker::Sync` is not satisfied in `[generator@$DIR/not-send-sync.rs:19:17: 23:6 {std::cell::Cell, ()}]` +error[E0277]: `std::cell::Cell` cannot be shared between threads safely --> $DIR/not-send-sync.rs:19:5 | LL | assert_sync(|| { @@ -30,4 +30,4 @@ LL | fn assert_sync(_: T) {} error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/pattern-borrow.stderr b/src/test/ui/generator/pattern-borrow.stderr index 6acfd96d8871..48f23486a317 100644 --- a/src/test/ui/generator/pattern-borrow.stderr +++ b/src/test/ui/generator/pattern-borrow.stderr @@ -8,4 +8,4 @@ LL | yield (); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0626" +For more information about this error, try `rustc --explain E0626`. diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr index 7cd07adf0b1c..65817e30c4de 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/sized-yield.rs b/src/test/ui/generator/sized-yield.rs index f38ebf8b9463..a1c8ca77e41e 100644 --- a/src/test/ui/generator/sized-yield.rs +++ b/src/test/ui/generator/sized-yield.rs @@ -17,5 +17,5 @@ fn main() { let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied yield s[..]; }; - gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied } diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index c10adad99ebc..957fac172c25 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -11,13 +11,13 @@ LL | | }; = note: the yield type of a generator must have a statically known size error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied - --> $DIR/sized-yield.rs:20:8 + --> $DIR/sized-yield.rs:20:17 | -LL | gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied - | ^^^^^^ `str` does not have a constant size known at compile-time +LL | unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + | ^^^^^^ `str` does not have a constant size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `str` error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/unsafe-immovable.stderr b/src/test/ui/generator/unsafe-immovable.stderr deleted file mode 100644 index a6755283bce0..000000000000 --- a/src/test/ui/generator/unsafe-immovable.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0133]: construction of immovable generator requires unsafe function or block - --> $DIR/unsafe-immovable.rs:14:5 - | -LL | / static || { //~ ERROR: construction of immovable generator requires unsafe -LL | | yield; -LL | | }; - | |_____^ construction of immovable generator - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0133" diff --git a/src/test/ui/generator/yield-in-args.stderr b/src/test/ui/generator/yield-in-args.stderr index 26152f73f5a9..3219939e89b2 100644 --- a/src/test/ui/generator/yield-in-args.stderr +++ b/src/test/ui/generator/yield-in-args.stderr @@ -6,4 +6,4 @@ LL | foo(&b, yield); //~ ERROR error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0626" +For more information about this error, try `rustc --explain E0626`. diff --git a/src/test/ui/generator/yield-in-const.rs b/src/test/ui/generator/yield-in-const.rs index e166d2651597..8636a66ae00a 100644 --- a/src/test/ui/generator/yield-in-const.rs +++ b/src/test/ui/generator/yield-in-const.rs @@ -12,3 +12,5 @@ const A: u8 = { yield 3u8; 3u8}; //~^ ERROR yield statement outside + +fn main() {} diff --git a/src/test/ui/generator/yield-in-const.stderr b/src/test/ui/generator/yield-in-const.stderr index 119f94695e72..874edce59316 100644 --- a/src/test/ui/generator/yield-in-const.stderr +++ b/src/test/ui/generator/yield-in-const.stderr @@ -1,12 +1,9 @@ -error[E0601]: main function not found - error[E0627]: yield statement outside of generator literal --> $DIR/yield-in-const.rs:13:17 | LL | const A: u8 = { yield 3u8; 3u8}; | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0601, E0627 -If you want more information on an error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0627`. diff --git a/src/test/ui/generator/yield-in-function.stderr b/src/test/ui/generator/yield-in-function.stderr index b1d76b41fa2b..35be1fcd28d1 100644 --- a/src/test/ui/generator/yield-in-function.stderr +++ b/src/test/ui/generator/yield-in-function.stderr @@ -6,4 +6,4 @@ LL | fn main() { yield; } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0627" +For more information about this error, try `rustc --explain E0627`. diff --git a/src/test/ui/generator/yield-in-static.rs b/src/test/ui/generator/yield-in-static.rs index 823a2aa425e2..21601f47f677 100644 --- a/src/test/ui/generator/yield-in-static.rs +++ b/src/test/ui/generator/yield-in-static.rs @@ -12,3 +12,5 @@ static B: u8 = { yield 3u8; 3u8}; //~^ ERROR yield statement outside + +fn main() {} diff --git a/src/test/ui/generator/yield-in-static.stderr b/src/test/ui/generator/yield-in-static.stderr index 0a2da21e6924..35d1ebaabdc1 100644 --- a/src/test/ui/generator/yield-in-static.stderr +++ b/src/test/ui/generator/yield-in-static.stderr @@ -1,12 +1,9 @@ -error[E0601]: main function not found - error[E0627]: yield statement outside of generator literal --> $DIR/yield-in-static.rs:13:18 | LL | static B: u8 = { yield 3u8; 3u8}; | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0601, E0627 -If you want more information on an error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0627`. diff --git a/src/test/ui/generator/yield-while-iterating.rs b/src/test/ui/generator/yield-while-iterating.rs index bc53448cb08e..b8a67a0e7b65 100644 --- a/src/test/ui/generator/yield-while-iterating.rs +++ b/src/test/ui/generator/yield-while-iterating.rs @@ -43,7 +43,7 @@ fn yield_during_iter_borrowed_slice_2() { println!("{:?}", x); } -fn yield_during_iter_borrowed_slice_3() { +unsafe fn yield_during_iter_borrowed_slice_3() { // OK to take a mutable ref to `x` and yield // up pointers from it: let mut x = vec![22_i32]; @@ -55,7 +55,7 @@ fn yield_during_iter_borrowed_slice_3() { b.resume(); } -fn yield_during_iter_borrowed_slice_4() { +unsafe fn yield_during_iter_borrowed_slice_4() { // ...but not OK to do that while reading // from `x` too let mut x = vec![22_i32]; @@ -68,7 +68,7 @@ fn yield_during_iter_borrowed_slice_4() { b.resume(); } -fn yield_during_range_iter() { +unsafe fn yield_during_range_iter() { // Should be OK. let mut b = || { let v = vec![1,2,3]; diff --git a/src/test/ui/generator/yield-while-iterating.stderr b/src/test/ui/generator/yield-while-iterating.stderr index c1a047f6c2a1..c20b1348e279 100644 --- a/src/test/ui/generator/yield-while-iterating.stderr +++ b/src/test/ui/generator/yield-while-iterating.stderr @@ -22,5 +22,5 @@ LL | } error: aborting due to 2 previous errors -You've got a few errors: E0502, E0626 -If you want more information on an error, try using "rustc --explain E0502" +Some errors occurred: E0502, E0626. +For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/generator/yield-while-local-borrowed.rs b/src/test/ui/generator/yield-while-local-borrowed.rs index 11bd4ed05cac..3dc2650a2ecb 100644 --- a/src/test/ui/generator/yield-while-local-borrowed.rs +++ b/src/test/ui/generator/yield-while-local-borrowed.rs @@ -15,7 +15,7 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; -fn borrow_local_inline() { +unsafe fn borrow_local_inline() { // Not OK to yield with a borrow of a temporary. // // (This error occurs because the region shows up in the type of @@ -30,7 +30,7 @@ fn borrow_local_inline() { b.resume(); } -fn borrow_local_inline_done() { +unsafe fn borrow_local_inline_done() { // No error here -- `a` is not in scope at the point of `yield`. let mut b = move || { { @@ -41,7 +41,7 @@ fn borrow_local_inline_done() { b.resume(); } -fn borrow_local() { +unsafe fn borrow_local() { // Not OK to yield with a borrow of a temporary. // // (This error occurs because the region shows up in the type of diff --git a/src/test/ui/generator/yield-while-local-borrowed.stderr b/src/test/ui/generator/yield-while-local-borrowed.stderr index 7417cdd9aa5f..a7f9862a726f 100644 --- a/src/test/ui/generator/yield-while-local-borrowed.stderr +++ b/src/test/ui/generator/yield-while-local-borrowed.stderr @@ -36,4 +36,4 @@ LL | yield(); error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0626" +For more information about this error, try `rustc --explain E0626`. diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.rs b/src/test/ui/generator/yield-while-ref-reborrowed.rs index b9c963ae7407..573dd4377bb2 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.rs +++ b/src/test/ui/generator/yield-while-ref-reborrowed.rs @@ -13,7 +13,7 @@ use std::ops::{GeneratorState, Generator}; use std::cell::Cell; -fn reborrow_shared_ref(x: &i32) { +unsafe fn reborrow_shared_ref(x: &i32) { // This is OK -- we have a borrow live over the yield, but it's of // data that outlives the generator. let mut b = move || { @@ -24,7 +24,7 @@ fn reborrow_shared_ref(x: &i32) { b.resume(); } -fn reborrow_mutable_ref(x: &mut i32) { +unsafe fn reborrow_mutable_ref(x: &mut i32) { // This is OK -- we have a borrow live over the yield, but it's of // data that outlives the generator. let mut b = move || { @@ -35,7 +35,7 @@ fn reborrow_mutable_ref(x: &mut i32) { b.resume(); } -fn reborrow_mutable_ref_2(x: &mut i32) { +unsafe fn reborrow_mutable_ref_2(x: &mut i32) { // ...but not OK to go on using `x`. let mut b = || { let a = &mut *x; diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.stderr index 57d688e78f69..8139814c7f2b 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.stderr @@ -14,4 +14,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0501" +For more information about this error, try `rustc --explain E0501`. diff --git a/src/test/ui/feature-gate-generic_param_attrs.rs b/src/test/ui/generic-param-attrs.rs similarity index 53% rename from src/test/ui/feature-gate-generic_param_attrs.rs rename to src/test/ui/generic-param-attrs.rs index 944802f450a6..37fabcd7e1e9 100644 --- a/src/test/ui/feature-gate-generic_param_attrs.rs +++ b/src/test/ui/generic-param-attrs.rs @@ -8,69 +8,47 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// This test ensures that attributes on formals in generic parameter -// lists are rejected if feature(generic_param_attrs) is not enabled. +// This test previously ensured that attributes on formals in generic parameter +// lists are rejected without a feature gate. // // (We are prefixing all tested features with `rustc_`, to ensure that // the attributes themselves won't be rejected by the compiler when // using `rustc_attrs` feature. There is a separate compile-fail/ test // ensuring that the attribute feature-gating works in this context.) +// must-compile-successfully + #![feature(rustc_attrs)] #![allow(dead_code)] struct StLt<#[rustc_lt_struct] 'a>(&'a u32); -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) struct StTy<#[rustc_ty_struct] I>(I); -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) enum EnTy<#[rustc_ty_enum] J> { A(J), B } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - type TyLt<#[rustc_lt_type] 'd> = &'d u32; -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) type TyTy<#[rustc_ty_type] L> = (L, ); -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) impl<#[rustc_lt_inherent] 'e> StLt<'e> { } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) impl<#[rustc_ty_inherent] M> StTy { } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> { - //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } } } impl<#[rustc_ty_impl_for] N> TrTy for StTy { - //~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) fn foo(&self, _: N) { } } fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) fn f_ty<#[rustc_ty_fn] O>(_: O) { } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) impl StTy { fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } - //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) fn m_ty<#[rustc_ty_meth] P>(_: P) { } - //~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) } fn hof_lt(_: Q) where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 - //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) -{ -} +{} -fn main() { - -} +fn main() {} diff --git a/src/test/ui/generic-type-less-params-with-defaults.stderr b/src/test/ui/generic-type-less-params-with-defaults.stderr index 327a36df80c5..28867eb2254e 100644 --- a/src/test/ui/generic-type-less-params-with-defaults.stderr +++ b/src/test/ui/generic-type-less-params-with-defaults.stderr @@ -6,4 +6,4 @@ LL | let _: Vec; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0243" +For more information about this error, try `rustc --explain E0243`. diff --git a/src/test/ui/generic-type-more-params-with-defaults.stderr b/src/test/ui/generic-type-more-params-with-defaults.stderr index 1f60d7997e32..684a22ce45c9 100644 --- a/src/test/ui/generic-type-more-params-with-defaults.stderr +++ b/src/test/ui/generic-type-more-params-with-defaults.stderr @@ -6,4 +6,4 @@ LL | let _: Vec; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0244" +For more information about this error, try `rustc --explain E0244`. diff --git a/src/test/ui/param-bounds-ignored.rs b/src/test/ui/higher-lifetime-bounds.rs similarity index 77% rename from src/test/ui/param-bounds-ignored.rs rename to src/test/ui/higher-lifetime-bounds.rs index 94bcdec94503..70b3b34fbd8f 100644 --- a/src/test/ui/param-bounds-ignored.rs +++ b/src/test/ui/higher-lifetime-bounds.rs @@ -10,31 +10,7 @@ #![allow(dead_code, non_camel_case_types)] -use std::rc::Rc; - -type SVec = Vec; -//~^ WARN bounds on generic parameters are ignored in type aliases -type VVec<'b, 'a: 'b+'b> = Vec<&'a i32>; -//~^ WARN bounds on generic parameters are ignored in type aliases -type WVec<'b, T: 'b+'b> = Vec; -//~^ WARN bounds on generic parameters are ignored in type aliases -type W2Vec<'b, T> where T: 'b, T: 'b = Vec; -//~^ WARN where clauses are ignored in type aliases - -fn foo<'a>(y: &'a i32) { - // If the bounds above would matter, the code below would be rejected. - let mut x : SVec<_> = Vec::new(); - x.push(Rc::new(42)); - - let mut x : VVec<'static, 'a> = Vec::new(); - x.push(y); - - let mut x : WVec<'static, & 'a i32> = Vec::new(); - x.push(y); - - let mut x : W2Vec<'static, & 'a i32> = Vec::new(); - x.push(y); -} +// Test that bounds on higher-kinded lifetime binders are rejected. fn bar1<'a, 'b>( x: &'a i32, diff --git a/src/test/ui/param-bounds-ignored.stderr b/src/test/ui/higher-lifetime-bounds.stderr similarity index 61% rename from src/test/ui/param-bounds-ignored.stderr rename to src/test/ui/higher-lifetime-bounds.stderr index 657fec54f960..82c007474360 100644 --- a/src/test/ui/param-bounds-ignored.stderr +++ b/src/test/ui/higher-lifetime-bounds.stderr @@ -1,94 +1,68 @@ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:42:22 + --> $DIR/higher-lifetime-bounds.rs:18:22 | LL | f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32) | ^^^ ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:50:34 + --> $DIR/higher-lifetime-bounds.rs:26:34 | LL | fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>( | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:65:28 + --> $DIR/higher-lifetime-bounds.rs:41:28 | LL | where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32 | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:77:25 + --> $DIR/higher-lifetime-bounds.rs:53:25 | LL | where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32 | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:85:28 + --> $DIR/higher-lifetime-bounds.rs:61:28 | LL | struct S1 Fn(&'xa i32, &'xb i32) -> &'xa i32>(F); | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:87:40 + --> $DIR/higher-lifetime-bounds.rs:63:40 | LL | struct S2(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32; | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:89:37 + --> $DIR/higher-lifetime-bounds.rs:65:37 | LL | struct S3(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32; | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:92:29 + --> $DIR/higher-lifetime-bounds.rs:68:29 | LL | struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32); | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:95:29 + --> $DIR/higher-lifetime-bounds.rs:71:29 | LL | type T1 = Box Fn(&'xa i32, &'xb i32) -> &'xa i32>; | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:99:34 + --> $DIR/higher-lifetime-bounds.rs:75:34 | LL | let _ : Option fn(&'xa i32, &'xb i32) -> &'xa i32> = None; | ^^^ error: lifetime bounds cannot be used in this context - --> $DIR/param-bounds-ignored.rs:101:38 + --> $DIR/higher-lifetime-bounds.rs:77:38 | LL | let _ : Option Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None; | ^^^ -warning: bounds on generic parameters are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:15:14 - | -LL | type SVec = Vec; - | ^^^^ ^^^^ - | - = note: #[warn(ignored_generic_bounds)] on by default - -warning: bounds on generic parameters are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:17:19 - | -LL | type VVec<'b, 'a: 'b+'b> = Vec<&'a i32>; - | ^^ ^^ - -warning: bounds on generic parameters are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:19:18 - | -LL | type WVec<'b, T: 'b+'b> = Vec; - | ^^ ^^ - -warning: where clauses are ignored in type aliases - --> $DIR/param-bounds-ignored.rs:21:25 - | -LL | type W2Vec<'b, T> where T: 'b, T: 'b = Vec; - | ^^^^^ ^^^^^ - error: aborting due to 11 previous errors diff --git a/src/test/ui/if-let-arm-types.stderr b/src/test/ui/if-let-arm-types.stderr index b20426103f44..2e6b71dadf13 100644 --- a/src/test/ui/if-let-arm-types.stderr +++ b/src/test/ui/if-let-arm-types.stderr @@ -23,4 +23,4 @@ LL | | }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr index dcbac5cfa0b1..99e1e56e3233 100644 --- a/src/test/ui/impl-duplicate-methods.stderr +++ b/src/test/ui/impl-duplicate-methods.stderr @@ -8,4 +8,4 @@ LL | fn orange(&self) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0201" +For more information about this error, try `rustc --explain E0201`. diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs index 5a6aac43ec77..99a7dd5e7852 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.rs +++ b/src/test/ui/impl-trait/auto-trait-leak.rs @@ -10,8 +10,6 @@ // ignore-tidy-linelength -#![feature(conservative_impl_trait)] - use std::cell::Cell; use std::rc::Rc; diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index bf7705881c91..ca639f1076d3 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -1,56 +1,56 @@ error[E0277]: the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>` - --> $DIR/auto-trait-leak.rs:27:5 + --> $DIR/auto-trait-leak.rs:25:5 | LL | send(before()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` - = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:21:5: 21:22 p:std::rc::Rc>]` + = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:19:5: 19:22 p:std::rc::Rc>]` = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` note: required by `send` - --> $DIR/auto-trait-leak.rs:24:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn send(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>` - --> $DIR/auto-trait-leak.rs:30:5 + --> $DIR/auto-trait-leak.rs:28:5 | LL | send(after()); | ^^^^ `std::rc::Rc>` cannot be sent between threads safely | = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` - = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:38:5: 38:22 p:std::rc::Rc>]` + = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:36:5: 36:22 p:std::rc::Rc>]` = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` note: required by `send` - --> $DIR/auto-trait-leak.rs:24:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn send(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^ error[E0391]: cyclic dependency detected - --> $DIR/auto-trait-leak.rs:44:1 + --> $DIR/auto-trait-leak.rs:42:1 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic reference | note: the cycle begins when processing `cycle1`... - --> $DIR/auto-trait-leak.rs:44:1 + --> $DIR/auto-trait-leak.rs:42:1 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which then requires processing `cycle2::{{impl-Trait}}`... - --> $DIR/auto-trait-leak.rs:52:16 + --> $DIR/auto-trait-leak.rs:50:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which then requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:52:1 + --> $DIR/auto-trait-leak.rs:50:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which then requires processing `cycle1::{{impl-Trait}}`... - --> $DIR/auto-trait-leak.rs:44:16 + --> $DIR/auto-trait-leak.rs:42:16 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ @@ -58,5 +58,5 @@ LL | fn cycle1() -> impl Clone { error: aborting due to 3 previous errors -You've got a few errors: E0277, E0391 -If you want more information on an error, try using "rustc --explain E0277" +Some errors occurred: E0277, E0391. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs index 9d9d4cef3119..b65e477f21f9 100644 --- a/src/test/ui/impl-trait/equality.rs +++ b/src/test/ui/impl-trait/equality.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, specialization)] +#![feature(specialization)] trait Foo: Copy + ToString {} diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 0c72468a2670..0f310df07142 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -53,5 +53,5 @@ LL | x.0); error: aborting due to 6 previous errors -You've got a few errors: E0277, E0308 -If you want more information on an error, try using "rustc --explain E0277" +Some errors occurred: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/impl-trait-plus-priority.stderr b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr index 1d4159aaa45e..2a9199b25bcf 100644 --- a/src/test/ui/impl-trait/impl-trait-plus-priority.stderr +++ b/src/test/ui/impl-trait/impl-trait-plus-priority.stderr @@ -66,4 +66,4 @@ LL | type A = &A + B; error: aborting due to 11 previous errors -If you want more information on this error, try using "rustc --explain E0178" +For more information about this error, try `rustc --explain E0178`. diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr index d80251200b29..89bc53884943 100644 --- a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr @@ -13,4 +13,4 @@ LL | f1.foo(1usize); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index b441ff518bdd..438d29f05353 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -15,4 +15,4 @@ LL | foo(|s| s.is_empty()); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index d5250b42cc21..bc4afb931098 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -255,4 +255,4 @@ LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).me error: aborting due to 24 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs new file mode 100644 index 000000000000..78ae922c7512 --- /dev/null +++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs @@ -0,0 +1,30 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// In contrast to `region-escape-via-bound-invariant`, in this case we +// *can* return a value of type `&'x u32`, even though `'x` does not +// appear in the bounds. This is because `&` is contravariant, and so +// we are *actually* returning a `&'y u32`. +// +// See https://github.com/rust-lang/rust/issues/46541 for more details. + +// run-pass + +#![allow(dead_code)] +#![feature(in_band_lifetimes)] +#![feature(nll)] + +fn foo(x: &'x u32) -> impl Fn() -> &'y u32 +where 'x: 'y +{ + move || x +} + +fn main() { } diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs new file mode 100644 index 000000000000..972461c2ffd9 --- /dev/null +++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs @@ -0,0 +1,34 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// In contrast to `region-escape-via-bound-invariant`, in this case we +// *can* return a value of type `&'x u32`, even though `'x` does not +// appear in the bounds. This is because `&` is contravariant, and so +// we are *actually* returning a `&'y u32`. +// +// See https://github.com/rust-lang/rust/issues/46541 for more details. + +// run-pass + +#![allow(dead_code)] +#![feature(in_band_lifetimes)] +#![feature(nll)] + +trait Trait<'a> { } + +impl Trait<'b> for &'a u32 { } + +fn foo(x: &'x u32) -> impl Trait<'y> +where 'x: 'y +{ + x +} + +fn main() { } diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs new file mode 100644 index 000000000000..e73f15606dc5 --- /dev/null +++ b/src/test/ui/impl-trait/region-escape-via-bound.rs @@ -0,0 +1,33 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do not allow the region `'x` to escape in the impl +// trait **even though** `'y` escapes, which outlives `'x`. +// +// See https://github.com/rust-lang/rust/issues/46541 for more details. + +#![allow(dead_code)] +#![feature(in_band_lifetimes)] +#![feature(nll)] + +use std::cell::Cell; + +trait Trait<'a> { } + +impl Trait<'b> for Cell<&'a u32> { } + +fn foo(x: Cell<&'x u32>) -> impl Trait<'y> + //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909] +where 'x: 'y +{ + x +} + +fn main() { } diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr new file mode 100644 index 000000000000..4281a4c10adf --- /dev/null +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -0,0 +1,20 @@ +error[E0909]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/region-escape-via-bound.rs:26:29 + | +LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y> + | ^^^^^^^^^^^^^^ + | +note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 26:1 + --> $DIR/region-escape-via-bound.rs:26:1 + | +LL | / fn foo(x: Cell<&'x u32>) -> impl Trait<'y> +LL | | //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909] +LL | | where 'x: 'y +LL | | { +LL | | x +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0909`. diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index 6c2fde03de37..c91ebb705dee 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -33,5 +33,5 @@ LL | impl std::fmt::Display for MyType4 {} error: aborting due to 4 previous errors -You've got a few errors: E0046, E0050, E0053, E0186 -If you want more information on an error, try using "rustc --explain E0046" +Some errors occurred: E0046, E0050, E0053, E0186. +For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/feature-gate-underscore-lifetimes.rs b/src/test/ui/impl-trait/universal-issue-48703.rs similarity index 75% rename from src/test/ui/feature-gate-underscore-lifetimes.rs rename to src/test/ui/impl-trait/universal-issue-48703.rs index 9da50c5c8771..e017b37b7b73 100644 --- a/src/test/ui/feature-gate-underscore-lifetimes.rs +++ b/src/test/ui/impl-trait/universal-issue-48703.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo<'a>(&'a u8); +#![feature(universal_impl_trait)] -fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable - Foo(x) -} +use std::fmt::Debug; + +fn foo(x: impl Debug) { } fn main() { - let x = 5; - let _ = foo(&x); + foo::('a'); //~ ERROR cannot provide explicit type parameters } diff --git a/src/test/ui/impl-trait/universal-issue-48703.stderr b/src/test/ui/impl-trait/universal-issue-48703.stderr new file mode 100644 index 000000000000..ea509684f9ef --- /dev/null +++ b/src/test/ui/impl-trait/universal-issue-48703.stderr @@ -0,0 +1,9 @@ +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/universal-issue-48703.rs:18:5 + | +LL | foo::('a'); //~ ERROR cannot provide explicit type parameters + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0632`. diff --git a/src/test/ui/impl-trait/universal-mismatched-type.rs b/src/test/ui/impl-trait/universal-mismatched-type.rs index 00fc22ff0d85..6a62eb36c303 100644 --- a/src/test/ui/impl-trait/universal-mismatched-type.rs +++ b/src/test/ui/impl-trait/universal-mismatched-type.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - use std::fmt::Debug; fn foo(x: impl Debug) -> String { diff --git a/src/test/ui/impl-trait/universal-mismatched-type.stderr b/src/test/ui/impl-trait/universal-mismatched-type.stderr index 67b3dacdaf56..031db511ff30 100644 --- a/src/test/ui/impl-trait/universal-mismatched-type.stderr +++ b/src/test/ui/impl-trait/universal-mismatched-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/universal-mismatched-type.rs:16:5 + --> $DIR/universal-mismatched-type.rs:14:5 | LL | fn foo(x: impl Debug) -> String { | ------ expected `std::string::String` because of return type @@ -11,4 +11,4 @@ LL | x //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.rs b/src/test/ui/impl-trait/universal-two-impl-traits.rs index 9a4847b56062..5ecef1fee65d 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.rs +++ b/src/test/ui/impl-trait/universal-two-impl-traits.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - use std::fmt::Debug; fn foo(x: impl Debug, y: impl Debug) -> String { diff --git a/src/test/ui/impl-trait/universal-two-impl-traits.stderr b/src/test/ui/impl-trait/universal-two-impl-traits.stderr index 4309c1a9bc9e..ed406895fc69 100644 --- a/src/test/ui/impl-trait/universal-two-impl-traits.stderr +++ b/src/test/ui/impl-trait/universal-two-impl-traits.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/universal-two-impl-traits.rs:17:9 + --> $DIR/universal-two-impl-traits.rs:15:9 | LL | a = y; //~ ERROR mismatched | ^ expected type parameter, found a different type parameter @@ -9,4 +9,4 @@ LL | a = y; //~ ERROR mismatched error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.rs b/src/test/ui/impl-trait/universal_wrong_bounds.rs index 36d9f615c5f5..a5e948223fb1 100644 --- a/src/test/ui/impl-trait/universal_wrong_bounds.rs +++ b/src/test/ui/impl-trait/universal_wrong_bounds.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] - use std::fmt::Display; fn foo(f: impl Display + Clone) -> String { diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.stderr b/src/test/ui/impl-trait/universal_wrong_bounds.stderr index 6cf0baa5fcce..02ac4707bc55 100644 --- a/src/test/ui/impl-trait/universal_wrong_bounds.stderr +++ b/src/test/ui/impl-trait/universal_wrong_bounds.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find function `wants_clone` in this scope - --> $DIR/universal_wrong_bounds.rs:18:5 + --> $DIR/universal_wrong_bounds.rs:16:5 | LL | wants_clone(f); //~ ERROR cannot find | ^^^^^^^^^^^ did you mean `wants_cone`? error[E0405]: cannot find trait `Debug` in this scope - --> $DIR/universal_wrong_bounds.rs:21:24 + --> $DIR/universal_wrong_bounds.rs:19:24 | LL | fn wants_debug(g: impl Debug) { } //~ ERROR cannot find | ^^^^^ not found in this scope @@ -15,7 +15,7 @@ LL | use std::fmt::Debug; | error[E0405]: cannot find trait `Debug` in this scope - --> $DIR/universal_wrong_bounds.rs:22:26 + --> $DIR/universal_wrong_bounds.rs:20:26 | LL | fn wants_display(g: impl Debug) { } //~ ERROR cannot find | ^^^^^ not found in this scope @@ -24,7 +24,7 @@ help: possible candidate is found in another module, you can import it into scop LL | use std::fmt::Debug; | -error: cannot continue compilation due to previous error +error: aborting due to 3 previous errors -You've got a few errors: E0405, E0425 -If you want more information on an error, try using "rustc --explain E0405" +Some errors occurred: E0405, E0425. +For more information about an error, try `rustc --explain E0405`. diff --git a/src/test/ui/impl-unused-rps-in-assoc-type.stderr b/src/test/ui/impl-unused-rps-in-assoc-type.stderr index fb3cf9a30c80..1f7f790b1e4a 100644 --- a/src/test/ui/impl-unused-rps-in-assoc-type.stderr +++ b/src/test/ui/impl-unused-rps-in-assoc-type.stderr @@ -6,4 +6,4 @@ LL | impl<'a> Fun for Holder { //~ ERROR E0207 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0207" +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index f69a78b1450f..6a7279422710 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -7,7 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(dyn_trait, conservative_impl_trait, universal_impl_trait)] +#![feature(dyn_trait)] use std::fmt::Debug; use std::option; diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr index f519f21215ef..9b38de614fc1 100644 --- a/src/test/ui/impl_trait_projections.stderr +++ b/src/test/ui/impl_trait_projections.stderr @@ -32,5 +32,5 @@ LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { error: aborting due to 5 previous errors -You've got a few errors: E0223, E0667 -If you want more information on an error, try using "rustc --explain E0223" +Some errors occurred: E0223, E0667. +For more information about an error, try `rustc --explain E0223`. diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index 0715674077a7..452e3e1e2008 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -86,5 +86,5 @@ LL | use self::m2::*; error: aborting due to 5 previous errors -You've got a few errors: E0252, E0659 -If you want more information on an error, try using "rustc --explain E0252" +Some errors occurred: E0252, E0659. +For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/macro-paths.rs b/src/test/ui/imports/macro-paths.rs index 88a6e1c0d92e..e709eeee14a8 100644 --- a/src/test/ui/imports/macro-paths.rs +++ b/src/test/ui/imports/macro-paths.rs @@ -36,3 +36,5 @@ fn g() { mod baz { pub use two_macros::m; } } } + +fn main() {} diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr index 815694919c76..799e7f972464 100644 --- a/src/test/ui/imports/macro-paths.stderr +++ b/src/test/ui/imports/macro-paths.stderr @@ -36,9 +36,6 @@ LL | | } | |_^ = note: macro-expanded items do not shadow when used in a macro invocation path -error[E0601]: main function not found +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -You've got a few errors: E0601, E0659 -If you want more information on an error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/macros.rs b/src/test/ui/imports/macros.rs index 98577d73ee0f..5d6a11913849 100644 --- a/src/test/ui/imports/macros.rs +++ b/src/test/ui/imports/macros.rs @@ -49,3 +49,5 @@ mod m4 { use two_macros::m; m!(); //~ ERROR ambiguous } + +fn main() {} diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr index c32fb56cd5d8..f91987cd9f34 100644 --- a/src/test/ui/imports/macros.stderr +++ b/src/test/ui/imports/macros.stderr @@ -51,9 +51,6 @@ LL | use two_macros::m; | ^^^^^^^^^^^^^ = note: macro-expanded macro imports do not shadow -error[E0601]: main function not found +error: aborting due to 3 previous errors -error: aborting due to 4 previous errors - -You've got a few errors: E0601, E0659 -If you want more information on an error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index 8c72d27d6aae..c9d80ada4725 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -57,4 +57,4 @@ LL | #[macro_use(n)] error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0659" +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/impossible_range.rs b/src/test/ui/impossible_range.rs index 5c72c506e6bf..073ed867bdb8 100644 --- a/src/test/ui/impossible_range.rs +++ b/src/test/ui/impossible_range.rs @@ -10,8 +10,6 @@ // Make sure that invalid ranges generate an error during HIR lowering, not an ICE -#![feature(inclusive_range_syntax)] - pub fn main() { ..; 0..; diff --git a/src/test/ui/impossible_range.stderr b/src/test/ui/impossible_range.stderr index 0754dbc796b4..cfeaa53a6bb1 100644 --- a/src/test/ui/impossible_range.stderr +++ b/src/test/ui/impossible_range.stderr @@ -1,5 +1,5 @@ error[E0586]: inclusive range with no end - --> $DIR/impossible_range.rs:20:8 + --> $DIR/impossible_range.rs:18:8 | LL | ..=; //~ERROR inclusive range with no end | ^ @@ -7,7 +7,7 @@ LL | ..=; //~ERROR inclusive range with no end = help: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error[E0586]: inclusive range with no end - --> $DIR/impossible_range.rs:27:9 + --> $DIR/impossible_range.rs:25:9 | LL | 0..=; //~ERROR inclusive range with no end | ^ @@ -16,4 +16,4 @@ LL | 0..=; //~ERROR inclusive range with no end error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0586" +For more information about this error, try `rustc --explain E0586`. diff --git a/src/test/ui/in-band-lifetimes/E0687.stderr b/src/test/ui/in-band-lifetimes/E0687.stderr index e1fa4164cc4c..441494d738a7 100644 --- a/src/test/ui/in-band-lifetimes/E0687.stderr +++ b/src/test/ui/in-band-lifetimes/E0687.stderr @@ -24,4 +24,4 @@ LL | fn bar(&self, x: fn(&'a u32)) {} //~ ERROR must be explicitly error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0687" +For more information about this error, try `rustc --explain E0687`. diff --git a/src/test/ui/in-band-lifetimes/E0687_where.rs b/src/test/ui/in-band-lifetimes/E0687_where.rs index ac6755877200..c1b268eac701 100644 --- a/src/test/ui/in-band-lifetimes/E0687_where.rs +++ b/src/test/ui/in-band-lifetimes/E0687_where.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(warnings)] -#![feature(in_band_lifetimes, universal_impl_trait)] +#![feature(in_band_lifetimes)] fn bar(x: &F) where F: Fn(&'a u32) {} //~ ERROR must be explicitly diff --git a/src/test/ui/in-band-lifetimes/E0687_where.stderr b/src/test/ui/in-band-lifetimes/E0687_where.stderr index 74da124c9c70..a2ad5cf0f83b 100644 --- a/src/test/ui/in-band-lifetimes/E0687_where.stderr +++ b/src/test/ui/in-band-lifetimes/E0687_where.stderr @@ -12,4 +12,4 @@ LL | fn baz(x: &impl Fn(&'a u32)) {} //~ ERROR must be explicitly error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0687" +For more information about this error, try `rustc --explain E0687`. diff --git a/src/test/ui/in-band-lifetimes/E0688.stderr b/src/test/ui/in-band-lifetimes/E0688.stderr index 3521e370dc57..66dca227941a 100644 --- a/src/test/ui/in-band-lifetimes/E0688.stderr +++ b/src/test/ui/in-band-lifetimes/E0688.stderr @@ -24,4 +24,4 @@ LL | impl<'b> Foo<'a> { //~ ERROR cannot mix error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0688" +For more information about this error, try `rustc --explain E0688`. diff --git a/src/test/ui/in-band-lifetimes/impl/assoc-type.rs b/src/test/ui/in-band-lifetimes/impl/assoc-type.rs new file mode 100644 index 000000000000..ab35331b279b --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/assoc-type.rs @@ -0,0 +1,37 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do not yet support elision in associated types, even +// when there is just one name we could take from the impl header. + +#![allow(warnings)] + +#![feature(in_band_lifetimes)] + +trait MyTrait { + type Output; +} + +impl MyTrait for &i32 { + type Output = &i32; + //~^ ERROR missing lifetime specifier +} + +impl MyTrait for &u32 { + type Output = &'_ i32; + //~^ ERROR missing lifetime specifier +} + +// This is what you have to do: +impl MyTrait for &'a f32 { + type Output = &'a f32; +} + +fn main() { } diff --git a/src/test/ui/in-band-lifetimes/impl/assoc-type.stderr b/src/test/ui/in-band-lifetimes/impl/assoc-type.stderr new file mode 100644 index 000000000000..59b2cfd2226d --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/assoc-type.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/assoc-type.rs:23:19 + | +LL | type Output = &i32; + | ^ expected lifetime parameter + +error[E0106]: missing lifetime specifier + --> $DIR/assoc-type.rs:28:20 + | +LL | type Output = &'_ i32; + | ^^ expected lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs new file mode 100644 index 000000000000..a504bae2e600 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs @@ -0,0 +1,44 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a, +// 'b> MyTrait<'a> for &'b i32`. + +#![allow(warnings)] + +#![feature(dyn_trait)] +#![feature(in_band_lifetimes)] + +use std::fmt::Debug; + +// Equivalent to `Box`: +trait StaticTrait { } +impl StaticTrait for Box { } + +// Equivalent to `Box`: +trait NotStaticTrait { } +impl NotStaticTrait for Box { } + +fn static_val(_: T) { +} + +fn with_dyn_debug_static<'a>(x: Box) { + static_val(x); //~ ERROR cannot infer +} + +fn not_static_val(_: T) { +} + +fn with_dyn_debug_not_static<'a>(x: Box) { + not_static_val(x); // OK +} + +fn main() { +} diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr new file mode 100644 index 000000000000..9d6a318c0751 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr @@ -0,0 +1,22 @@ +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/dyn-trait.rs:33:16 + | +LL | static_val(x); //~ ERROR cannot infer + | ^ + | +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 32:1... + --> $DIR/dyn-trait.rs:32:1 + | +LL | fn with_dyn_debug_static<'a>(x: Box) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the expression is assignable: + expected std::boxed::Box + found std::boxed::Box + = note: but, the lifetime must be valid for the static lifetime... + = note: ...so that the types are compatible: + expected StaticTrait + found StaticTrait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/impl/path-elided.rs b/src/test/ui/in-band-lifetimes/impl/path-elided.rs new file mode 100644 index 000000000000..8a758b124ba5 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/path-elided.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(warnings)] + +#![feature(in_band_lifetimes)] + +trait MyTrait { } + +struct Foo<'a> { x: &'a u32 } + +impl MyTrait for Foo { + //~^ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/src/test/ui/in-band-lifetimes/impl/path-elided.stderr b/src/test/ui/in-band-lifetimes/impl/path-elided.stderr new file mode 100644 index 000000000000..6c1d72411bf5 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/path-elided.stderr @@ -0,0 +1,9 @@ +error[E0106]: missing lifetime specifier + --> $DIR/path-elided.rs:18:18 + | +LL | impl MyTrait for Foo { + | ^^^ expected lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/in-band-lifetimes/impl/path-underscore.rs b/src/test/ui/in-band-lifetimes/impl/path-underscore.rs new file mode 100644 index 000000000000..756991d97a53 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/path-underscore.rs @@ -0,0 +1,46 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `impl MyTrait for Foo<'_>` works. + +// run-pass + +#![allow(warnings)] + +#![feature(in_band_lifetimes)] + +trait MyTrait { } + +struct Foo<'a> { x: &'a u32 } + +impl MyTrait for Foo<'_> { +} + +fn impls_my_trait() { } + +fn impls_my_trait_val(_: T) { + impls_my_trait::(); +} + +fn random_where_clause() +where for<'a> Foo<'a>: MyTrait { } + +fn main() { + let x = 22; + let f = Foo { x: &x }; + + // This type is `Foo<'x>` for a local lifetime `'x`; so the impl + // must apply to any lifetime to apply to this. + impls_my_trait_val(f); + + impls_my_trait::>(); + + random_where_clause(); +} diff --git a/src/test/ui/in-band-lifetimes/impl/ref-underscore.rs b/src/test/ui/in-band-lifetimes/impl/ref-underscore.rs new file mode 100644 index 000000000000..99708afff351 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/ref-underscore.rs @@ -0,0 +1,42 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `impl MyTrait for &i32` works and is equivalent to any lifetime. + +// run-pass + +#![allow(warnings)] + +#![feature(in_band_lifetimes)] + +trait MyTrait { } + +impl MyTrait for &i32 { +} + +fn impls_my_trait() { } + +fn impls_my_trait_val(_: T) { + impls_my_trait::(); +} + +fn random_where_clause() +where for<'a> &'a i32: MyTrait { } + +fn main() { + let x = 22; + let f = &x; + + impls_my_trait_val(f); + + impls_my_trait::<&'static i32>(); + + random_where_clause(); +} diff --git a/src/test/ui/in-band-lifetimes/impl/trait-elided.rs b/src/test/ui/in-band-lifetimes/impl/trait-elided.rs new file mode 100644 index 000000000000..e0709ab6dd07 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/trait-elided.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(warnings)] + +#![feature(in_band_lifetimes)] + +trait MyTrait<'a> { } + +impl MyTrait for u32 { + //~^ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/src/test/ui/in-band-lifetimes/impl/trait-elided.stderr b/src/test/ui/in-band-lifetimes/impl/trait-elided.stderr new file mode 100644 index 000000000000..fe3ded8e04c3 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/trait-elided.stderr @@ -0,0 +1,9 @@ +error[E0106]: missing lifetime specifier + --> $DIR/trait-elided.rs:16:6 + | +LL | impl MyTrait for u32 { + | ^^^^^^^ expected lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/in-band-lifetimes/impl/trait-underscore.rs b/src/test/ui/in-band-lifetimes/impl/trait-underscore.rs new file mode 100644 index 000000000000..971fd1fe759b --- /dev/null +++ b/src/test/ui/in-band-lifetimes/impl/trait-underscore.rs @@ -0,0 +1,47 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a, +// 'b> MyTrait<'a> for &'b i32`. +// +// run-pass + +#![allow(warnings)] + +#![feature(in_band_lifetimes)] + +trait MyTrait<'a> { } + +// This is equivalent to `MyTrait<'a> for &'b i32`, which is proven by +// the code below. +impl MyTrait<'_> for &i32 { +} + +// When called, T will be `&'x i32` for some `'x`, so since we can +// prove that `&'x i32: for<'a> MyTrait<'a>, then we know that the +// lifetime parameter above is disconnected. +fn impls_my_trait MyTrait<'a>>() { } + +fn impls_my_trait_val MyTrait<'a>>(_: T) { + impls_my_trait::(); +} + +fn random_where_clause() +where for<'a, 'b> &'a i32: MyTrait<'b> { } + +fn main() { + let x = 22; + let f = &x; + impls_my_trait_val(f); + + impls_my_trait::<&'static i32>(); + + random_where_clause(); +} diff --git a/src/test/ui/in-band-lifetimes/mismatched.stderr b/src/test/ui/in-band-lifetimes/mismatched.stderr index 9485c9652a97..d2748b2da4b6 100644 --- a/src/test/ui/in-band-lifetimes/mismatched.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched.stderr @@ -16,5 +16,5 @@ LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatc error: aborting due to 2 previous errors -You've got a few errors: E0621, E0623 -If you want more information on an error, try using "rustc --explain E0621" +Some errors occurred: E0621, E0623. +For more information about an error, try `rustc --explain E0621`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait.stderr index 5007701afdbd..71b46f6d4d60 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait.stderr @@ -8,4 +8,4 @@ LL | y //~ ERROR explicit lifetime required error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs index f845762cefd8..ff04cfe99c0b 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -20,3 +20,5 @@ impl Deref for Struct { } } //~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter + +fn main() {} diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index bc55b1c56cf2..37b586e1e3bd 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements --> $DIR/mismatched_trait_impl-2.rs:18:5 | @@ -18,7 +16,6 @@ LL | | } expected fn(&Struct) -> &Trait + 'static found fn(&Struct) -> &Trait -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0495, E0601 -If you want more information on an error, try using "rustc --explain E0495" +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 41b0c77ea148..675ae1695b55 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -22,4 +22,4 @@ LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0495" +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr b/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr index 258b369f257e..1498eb7ac1da 100644 --- a/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr +++ b/src/test/ui/in-band-lifetimes/mut_while_borrow.stderr @@ -8,4 +8,4 @@ LL | p += 1; //~ ERROR cannot assign to `p` because it is borrowed error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr index 7cba013c96b7..da46cb7f22e3 100644 --- a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr +++ b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr @@ -12,4 +12,4 @@ LL | Baz(&'test u32), //~ ERROR undeclared lifetime error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0261" +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr index 7b1d0509bbdc..d53b71907a42 100644 --- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr +++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr @@ -12,4 +12,4 @@ LL | let y: fn(&'test u32) = foo2; //~ ERROR use of undeclared lifetime error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0261" +For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/in-band-lifetimes/shadow.stderr b/src/test/ui/in-band-lifetimes/shadow.stderr index b22b18aa9294..0ee228fca312 100644 --- a/src/test/ui/in-band-lifetimes/shadow.stderr +++ b/src/test/ui/in-band-lifetimes/shadow.stderr @@ -17,4 +17,4 @@ LL | fn baz(x: for<'s> fn(&'s u32)) {} //~ ERROR shadows a lifetime name error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0496" +For more information about this error, try `rustc --explain E0496`. diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index ae3cd529ac42..669c0837fdab 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr @@ -9,4 +9,4 @@ LL | x[0i32]; //~ ERROR E0277 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/inference-variable-behind-raw-pointer.stderr b/src/test/ui/inference-variable-behind-raw-pointer.stderr index eb40151615da..fe6dc0b07482 100644 --- a/src/test/ui/inference-variable-behind-raw-pointer.stderr +++ b/src/test/ui/inference-variable-behind-raw-pointer.stderr @@ -5,6 +5,6 @@ LL | if data.is_null() {} | ^^^^^^^ | = note: #[warn(tyvar_behind_raw_pointer)] on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 epoch! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! = note: for more information, see issue #46906 diff --git a/src/test/ui/inference_unstable.rs b/src/test/ui/inference_unstable.rs new file mode 100644 index 000000000000..816c443a06c2 --- /dev/null +++ b/src/test/ui/inference_unstable.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Ensures #[unstable] functions without opting in the corresponding #![feature] +// will not break inference. + +// aux-build:inference_unstable_iterator.rs +// aux-build:inference_unstable_itertools.rs +// run-pass + +extern crate inference_unstable_iterator; +extern crate inference_unstable_itertools; + +#[allow(unused_imports)] +use inference_unstable_iterator::IpuIterator; +use inference_unstable_itertools::IpuItertools; + +fn main() { + assert_eq!('x'.ipu_flatten(), 1); + //~^ WARN a method with this name may be added to the standard library in the future + //~^^ WARN once this method is added to the standard library, there will be ambiguity here +} diff --git a/src/test/ui/inference_unstable.stderr b/src/test/ui/inference_unstable.stderr new file mode 100644 index 000000000000..9c614d659d36 --- /dev/null +++ b/src/test/ui/inference_unstable.stderr @@ -0,0 +1,12 @@ +warning: a method with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:26:20 + | +LL | assert_eq!('x'.ipu_flatten(), 1); + | ^^^^^^^^^^^ + | + = note: #[warn(unstable_name_collision)] on by default + = warning: once this method is added to the standard library, there will be ambiguity here, which will cause a hard error! + = note: for more information, see issue #48919 + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method + = note: add #![feature(ipu_flatten)] to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten` + diff --git a/src/test/ui/inference_unstable_featured.rs b/src/test/ui/inference_unstable_featured.rs new file mode 100644 index 000000000000..f5c49bedc711 --- /dev/null +++ b/src/test/ui/inference_unstable_featured.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// There should be E0034 "multiple applicable items in scope" if we opt-in for +// the feature. + +// aux-build:inference_unstable_iterator.rs +// aux-build:inference_unstable_itertools.rs + +#![feature(ipu_flatten)] + +extern crate inference_unstable_iterator; +extern crate inference_unstable_itertools; + +use inference_unstable_iterator::IpuIterator; +use inference_unstable_itertools::IpuItertools; + +fn main() { + assert_eq!('x'.ipu_flatten(), 0); //~ ERROR E0034 +} diff --git a/src/test/ui/inference_unstable_featured.stderr b/src/test/ui/inference_unstable_featured.stderr new file mode 100644 index 000000000000..cb5f3623291b --- /dev/null +++ b/src/test/ui/inference_unstable_featured.stderr @@ -0,0 +1,12 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/inference_unstable_featured.rs:26:20 + | +LL | assert_eq!('x'.ipu_flatten(), 0); //~ ERROR E0034 + | ^^^^^^^^^^^ multiple `ipu_flatten` found + | + = note: candidate #1 is defined in an impl of the trait `inference_unstable_iterator::IpuIterator` for the type `char` + = note: candidate #2 is defined in an impl of the trait `inference_unstable_itertools::IpuItertools` for the type `char` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/src/test/compile-fail/placement-expr-unsafe.rs b/src/test/ui/inference_unstable_forced.rs similarity index 53% rename from src/test/compile-fail/placement-expr-unsafe.rs rename to src/test/ui/inference_unstable_forced.rs index bf6f4c52f1f9..82ce4034ce26 100644 --- a/src/test/compile-fail/placement-expr-unsafe.rs +++ b/src/test/ui/inference_unstable_forced.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,17 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that placement in respects unsafe code checks. +// If the unstable API is the only possible solution, +// still emit E0658 "use of unstable library feature". -#![feature(box_heap)] -#![feature(placement_in_syntax)] +// aux-build:inference_unstable_iterator.rs + +extern crate inference_unstable_iterator; + +use inference_unstable_iterator::IpuIterator; fn main() { - use std::boxed::HEAP; - - let p: *const i32 = &42; - let _ = HEAP <- *p; //~ ERROR requires unsafe - - let p: *const _ = &HEAP; - let _ = *p <- 42; //~ ERROR requires unsafe + assert_eq!('x'.ipu_flatten(), 0); //~ ERROR E0658 } diff --git a/src/test/ui/inference_unstable_forced.stderr b/src/test/ui/inference_unstable_forced.stderr new file mode 100644 index 000000000000..00eb81cd9a23 --- /dev/null +++ b/src/test/ui/inference_unstable_forced.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'ipu_flatten' (see issue #99999) + --> $DIR/inference_unstable_forced.rs:21:20 + | +LL | assert_eq!('x'.ipu_flatten(), 0); //~ ERROR E0658 + | ^^^^^^^^^^^ + | + = help: add #![feature(ipu_flatten)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/infinite-recursion-const-fn.stderr b/src/test/ui/infinite-recursion-const-fn.stderr index bc062ecce258..81717fe1f092 100644 --- a/src/test/ui/infinite-recursion-const-fn.stderr +++ b/src/test/ui/infinite-recursion-const-fn.stderr @@ -69,4 +69,4 @@ LL | const ARR: [i32; a()] = [5; 6]; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0080" +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index e27353eda099..4c489c5964ba 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -12,4 +12,4 @@ LL | catch_unwind(|| { x.set(23); }); //~ ERROR the trait bound error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index 2dac52d6f81e..2dd62ec05007 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -8,4 +8,4 @@ LL | pub mod baz; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0583" +For more information about this error, try `rustc --explain E0583`. diff --git a/src/test/ui/invalid-path-in-const.stderr b/src/test/ui/invalid-path-in-const.stderr index 06eb6005d71d..9214800b93a5 100644 --- a/src/test/ui/invalid-path-in-const.stderr +++ b/src/test/ui/invalid-path-in-const.stderr @@ -6,4 +6,4 @@ LL | fn f(a: [u8; u32::DOESNOTEXIST]) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-10969.stderr b/src/test/ui/issue-10969.stderr index b4d365dcc004..edc4ecbab525 100644 --- a/src/test/ui/issue-10969.stderr +++ b/src/test/ui/issue-10969.stderr @@ -16,4 +16,4 @@ LL | i(); //~ERROR expected function, found `i32` error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0618" +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/issue-11004.stderr b/src/test/ui/issue-11004.stderr index 4cfc7d23bd0b..215120c9c25e 100644 --- a/src/test/ui/issue-11004.stderr +++ b/src/test/ui/issue-11004.stderr @@ -2,18 +2,14 @@ error[E0609]: no field `x` on type `*mut A` --> $DIR/issue-11004.rs:17:21 | LL | let x : i32 = n.x; //~ no field `x` on type `*mut A` - | ^ - | - = note: `n` is a native pointer; perhaps you need to deref with `(*n).x` + | ^ help: `n` is a native pointer; try dereferencing it: `(*n).x` error[E0609]: no field `y` on type `*mut A` --> $DIR/issue-11004.rs:18:21 | LL | let y : f64 = n.y; //~ no field `y` on type `*mut A` - | ^ - | - = note: `n` is a native pointer; perhaps you need to deref with `(*n).y` + | ^ help: `n` is a native pointer; try dereferencing it: `(*n).y` error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0609" +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/issue-11319.stderr b/src/test/ui/issue-11319.stderr index b94f8001ccf5..8189cf5ea170 100644 --- a/src/test/ui/issue-11319.stderr +++ b/src/test/ui/issue-11319.stderr @@ -17,4 +17,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-12187-1.stderr b/src/test/ui/issue-12187-1.stderr index 29b1e985183d..7d4df2901fe3 100644 --- a/src/test/ui/issue-12187-1.stderr +++ b/src/test/ui/issue-12187-1.stderr @@ -9,4 +9,4 @@ LL | let &v = new(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issue-12187-2.stderr b/src/test/ui/issue-12187-2.stderr index 327105bee162..f7ecbd447729 100644 --- a/src/test/ui/issue-12187-2.stderr +++ b/src/test/ui/issue-12187-2.stderr @@ -9,4 +9,4 @@ LL | let &v = new(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issue-12511.stderr b/src/test/ui/issue-12511.stderr index 3f0c0e7ee13d..c1612b8cb678 100644 --- a/src/test/ui/issue-12511.stderr +++ b/src/test/ui/issue-12511.stderr @@ -18,4 +18,4 @@ LL | trait t1 : t2 { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issue-13058.stderr b/src/test/ui/issue-13058.stderr index 30936d4c90d8..cef5f5ae475b 100644 --- a/src/test/ui/issue-13058.stderr +++ b/src/test/ui/issue-13058.stderr @@ -21,5 +21,5 @@ LL | check((3, 5)); error: aborting due to 2 previous errors -You've got a few errors: E0308, E0621 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0621. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-14092.stderr b/src/test/ui/issue-14092.stderr index 209ca27a20be..f90ea4776ab7 100644 --- a/src/test/ui/issue-14092.stderr +++ b/src/test/ui/issue-14092.stderr @@ -6,4 +6,4 @@ LL | fn fn1(0: Box) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0243" +For more information about this error, try `rustc --explain E0243`. diff --git a/src/test/ui/issue-15260.stderr b/src/test/ui/issue-15260.stderr index 1b0a39d02f5b..10cb79e0fc54 100644 --- a/src/test/ui/issue-15260.stderr +++ b/src/test/ui/issue-15260.stderr @@ -33,4 +33,4 @@ LL | a: x error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0025" +For more information about this error, try `rustc --explain E0025`. diff --git a/src/test/ui/issue-15524.stderr b/src/test/ui/issue-15524.stderr index e26766eca373..a116e621a95d 100644 --- a/src/test/ui/issue-15524.stderr +++ b/src/test/ui/issue-15524.stderr @@ -26,4 +26,4 @@ LL | E = N, error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0081" +For more information about this error, try `rustc --explain E0081`. diff --git a/src/test/ui/issue-17263.stderr b/src/test/ui/issue-17263.stderr index e321a9f45626..4767fbbcfbbd 100644 --- a/src/test/ui/issue-17263.stderr +++ b/src/test/ui/issue-17263.stderr @@ -22,5 +22,5 @@ LL | } error: aborting due to 2 previous errors -You've got a few errors: E0499, E0502 -If you want more information on an error, try using "rustc --explain E0499" +Some errors occurred: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/issue-17441.stderr b/src/test/ui/issue-17441.stderr index ec0f33caffc7..80ba49cce1a0 100644 --- a/src/test/ui/issue-17441.stderr +++ b/src/test/ui/issue-17441.stderr @@ -44,4 +44,4 @@ LL | let _quux = [1_usize, 2] as [usize]; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0620" +For more information about this error, try `rustc --explain E0620`. diff --git a/src/test/ui/issue-18183.stderr b/src/test/ui/issue-18183.stderr index 93cd351cbc58..169a3019d521 100644 --- a/src/test/ui/issue-18183.stderr +++ b/src/test/ui/issue-18183.stderr @@ -6,4 +6,4 @@ LL | pub struct Foo(Bar); //~ ERROR E0128 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0128" +For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/issue-18819.stderr b/src/test/ui/issue-18819.stderr index e714707c2c3d..86926863598b 100644 --- a/src/test/ui/issue-18819.stderr +++ b/src/test/ui/issue-18819.stderr @@ -9,4 +9,4 @@ LL | print_x(X); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/issue-19498.stderr b/src/test/ui/issue-19498.stderr index b2793dff2bf8..839ab778061c 100644 --- a/src/test/ui/issue-19498.stderr +++ b/src/test/ui/issue-19498.stderr @@ -44,4 +44,4 @@ LL | use C::D as OtherD; error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0255" +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/issue-19707.stderr b/src/test/ui/issue-19707.stderr index 22a892c9252b..56088d38aaf9 100644 --- a/src/test/ui/issue-19707.stderr +++ b/src/test/ui/issue-19707.stderr @@ -16,4 +16,4 @@ LL | fn bar &u8>(f: &F) {} //~ ERROR missing lifetime specifi error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0106" +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/issue-19922.stderr b/src/test/ui/issue-19922.stderr index ac64cb12ef0b..a5bc579e1924 100644 --- a/src/test/ui/issue-19922.stderr +++ b/src/test/ui/issue-19922.stderr @@ -8,4 +8,4 @@ LL | let homura = Homura::Akemi { kaname: () }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0559" +For more information about this error, try `rustc --explain E0559`. diff --git a/src/test/ui/issue-20692.stderr b/src/test/ui/issue-20692.stderr index 1c23f42f3cc4..1316773f6b78 100644 --- a/src/test/ui/issue-20692.stderr +++ b/src/test/ui/issue-20692.stderr @@ -17,4 +17,4 @@ LL | let _ = x error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/issue-21546.stderr b/src/test/ui/issue-21546.stderr index 6f8000f24924..bff79e52aa18 100644 --- a/src/test/ui/issue-21546.stderr +++ b/src/test/ui/issue-21546.stderr @@ -66,4 +66,4 @@ LL | mod Corge { } error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0428" +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/issue-21600.stderr b/src/test/ui/issue-21600.stderr index b1dcf1cd7300..873dc7448be2 100644 --- a/src/test/ui/issue-21600.stderr +++ b/src/test/ui/issue-21600.stderr @@ -29,4 +29,4 @@ LL | call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0387" +For more information about this error, try `rustc --explain E0387`. diff --git a/src/test/ui/issue-21950.stderr b/src/test/ui/issue-21950.stderr index 9d33e1fd0ab0..a2f74a29aab7 100644 --- a/src/test/ui/issue-21950.stderr +++ b/src/test/ui/issue-21950.stderr @@ -14,5 +14,5 @@ LL | &Add; error: aborting due to 2 previous errors -You've got a few errors: E0191, E0393 -If you want more information on an error, try using "rustc --explain E0191" +Some errors occurred: E0191, E0393. +For more information about an error, try `rustc --explain E0191`. diff --git a/src/test/ui/issue-22370.stderr b/src/test/ui/issue-22370.stderr index 79362ce7aa3a..b3691503fc19 100644 --- a/src/test/ui/issue-22370.stderr +++ b/src/test/ui/issue-22370.stderr @@ -8,4 +8,4 @@ LL | fn f(a: &A) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0393" +For more information about this error, try `rustc --explain E0393`. diff --git a/src/test/ui/issue-22560.stderr b/src/test/ui/issue-22560.stderr index 907b0d8822dc..b5524036fae9 100644 --- a/src/test/ui/issue-22560.stderr +++ b/src/test/ui/issue-22560.stderr @@ -32,5 +32,5 @@ LL | | Sub; error: aborting due to 4 previous errors -You've got a few errors: E0191, E0225, E0393 -If you want more information on an error, try using "rustc --explain E0191" +Some errors occurred: E0191, E0225, E0393. +For more information about an error, try `rustc --explain E0191`. diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 257b9bd235d7..aeb465b2ab23 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -89,3 +89,5 @@ error: expected type, found `4` LL | println!("{}", a: &mut 4); //~ ERROR expected type, found `4` | ^ expecting a type here because of type ascription +error: aborting due to 9 previous errors + diff --git a/src/test/ui/issue-22886.stderr b/src/test/ui/issue-22886.stderr index 4a69e6bc4c25..0e05cbfa7eed 100644 --- a/src/test/ui/issue-22886.stderr +++ b/src/test/ui/issue-22886.stderr @@ -6,4 +6,4 @@ LL | impl<'a> Iterator for Newtype { //~ ERROR E0207 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0207" +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/issue-22933-2.stderr b/src/test/ui/issue-22933-2.stderr index 41324fd8b753..435a89b716f9 100644 --- a/src/test/ui/issue-22933-2.stderr +++ b/src/test/ui/issue-22933-2.stderr @@ -9,4 +9,4 @@ LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-23041.stderr b/src/test/ui/issue-23041.stderr index cf4e677ed0c4..f89bce09c7ed 100644 --- a/src/test/ui/issue-23041.stderr +++ b/src/test/ui/issue-23041.stderr @@ -6,4 +6,4 @@ LL | b.downcast_ref::_>(); //~ ERROR E0282 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issue-23173.stderr b/src/test/ui/issue-23173.stderr index bf2c67f93f88..d58a4d2b8f8a 100644 --- a/src/test/ui/issue-23173.stderr +++ b/src/test/ui/issue-23173.stderr @@ -36,4 +36,4 @@ LL | Struct::Assoc; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-23217.stderr b/src/test/ui/issue-23217.stderr index 7abe4bd7b213..d542a10e9b60 100644 --- a/src/test/ui/issue-23217.stderr +++ b/src/test/ui/issue-23217.stderr @@ -5,7 +5,9 @@ LL | pub enum SomeEnum { | ----------------- variant `A` not found here LL | B = SomeEnum::A, | ^^^^^^^^^^^ variant not found in `SomeEnum` + | + = note: did you mean `variant::B`? error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-23302-1.stderr b/src/test/ui/issue-23302-1.stderr index 087eae43a299..c587c00279bd 100644 --- a/src/test/ui/issue-23302-1.stderr +++ b/src/test/ui/issue-23302-1.stderr @@ -18,4 +18,4 @@ LL | A = X::A as isize, //~ ERROR E0391 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issue-23302-2.stderr b/src/test/ui/issue-23302-2.stderr index 66ba5c325821..553ddaa1a810 100644 --- a/src/test/ui/issue-23302-2.stderr +++ b/src/test/ui/issue-23302-2.stderr @@ -18,4 +18,4 @@ LL | A = Y::B as isize, //~ ERROR E0391 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issue-23302-3.stderr b/src/test/ui/issue-23302-3.stderr index 31168579394d..8cf296bc6db6 100644 --- a/src/test/ui/issue-23302-3.stderr +++ b/src/test/ui/issue-23302-3.stderr @@ -28,4 +28,4 @@ LL | const B: i32 = A; //~ ERROR cyclic dependency detected error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issue-23543.stderr b/src/test/ui/issue-23543.stderr index c62af8f0635b..ea443f1cbbba 100644 --- a/src/test/ui/issue-23543.stderr +++ b/src/test/ui/issue-23543.stderr @@ -6,4 +6,4 @@ LL | where T: A; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0229" +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/issue-23544.stderr b/src/test/ui/issue-23544.stderr index 882703cdb5ae..147e2a212edd 100644 --- a/src/test/ui/issue-23544.stderr +++ b/src/test/ui/issue-23544.stderr @@ -6,4 +6,4 @@ LL | where T: A; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0229" +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/issue-23716.stderr b/src/test/ui/issue-23716.stderr index 739c8d66e713..fd268c1b5a19 100644 --- a/src/test/ui/issue-23716.stderr +++ b/src/test/ui/issue-23716.stderr @@ -18,4 +18,4 @@ LL | fn question(answer: i32) {} error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0530" +For more information about this error, try `rustc --explain E0530`. diff --git a/src/test/ui/issue-24036.stderr b/src/test/ui/issue-24036.stderr index bbf64d8305de..24995be773e7 100644 --- a/src/test/ui/issue-24036.stderr +++ b/src/test/ui/issue-24036.stderr @@ -29,4 +29,4 @@ LL | | }; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-24081.stderr b/src/test/ui/issue-24081.stderr index 257e32f91980..17cd3ec0aa6d 100644 --- a/src/test/ui/issue-24081.stderr +++ b/src/test/ui/issue-24081.stderr @@ -75,4 +75,4 @@ LL | use std::ops::Rem as OtherRem; error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0255" +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/issue-24424.stderr b/src/test/ui/issue-24424.stderr index c3d5211cddc9..7bcf67a50480 100644 --- a/src/test/ui/issue-24424.stderr +++ b/src/test/ui/issue-24424.stderr @@ -12,4 +12,4 @@ LL | trait Trait0<'l0> {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0283" +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/issue-25385.stderr b/src/test/ui/issue-25385.stderr index 88e30d7fae05..f12388d4b458 100644 --- a/src/test/ui/issue-25385.stderr +++ b/src/test/ui/issue-25385.stderr @@ -15,4 +15,4 @@ LL | foo!(1i32.foo()); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-25793.stderr b/src/test/ui/issue-25793.stderr index 2d8b5d6f4995..926a744f69e8 100644 --- a/src/test/ui/issue-25793.stderr +++ b/src/test/ui/issue-25793.stderr @@ -11,4 +11,4 @@ LL | self.get_size(width!(self)) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0503" +For more information about this error, try `rustc --explain E0503`. diff --git a/src/test/ui/issue-25826.stderr b/src/test/ui/issue-25826.stderr index 94cbcf53f430..fed9e8efa848 100644 --- a/src/test/ui/issue-25826.stderr +++ b/src/test/ui/issue-25826.stderr @@ -6,4 +6,4 @@ LL | const A: bool = id:: as *const () < id:: as *const (); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0395" +For more information about this error, try `rustc --explain E0395`. diff --git a/src/test/ui/issue-26056.stderr b/src/test/ui/issue-26056.stderr index c806308562ce..51a48af81a16 100644 --- a/src/test/ui/issue-26056.stderr +++ b/src/test/ui/issue-26056.stderr @@ -8,4 +8,4 @@ LL | as &Map; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/issue-26093.stderr b/src/test/ui/issue-26093.stderr index 29ffd9635c64..1abe313bbf66 100644 --- a/src/test/ui/issue-26093.stderr +++ b/src/test/ui/issue-26093.stderr @@ -9,4 +9,4 @@ LL | not_a_place!(99); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0070" +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/issue-26472.stderr b/src/test/ui/issue-26472.stderr index 345008b45787..26f54f61a7ee 100644 --- a/src/test/ui/issue-26472.stderr +++ b/src/test/ui/issue-26472.stderr @@ -8,4 +8,4 @@ LL | let v = s.len; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0616" +For more information about this error, try `rustc --explain E0616`. diff --git a/src/test/ui/issue-26638.stderr b/src/test/ui/issue-26638.stderr index a5fc3ba26d66..cf6fcd9f01cc 100644 --- a/src/test/ui/issue-26638.stderr +++ b/src/test/ui/issue-26638.stderr @@ -26,4 +26,4 @@ LL | fn parse_type_3() -> &str { unimplemented!() } error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0106" +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/issue-26886.stderr b/src/test/ui/issue-26886.stderr index dc812d1bae3b..759426239410 100644 --- a/src/test/ui/issue-26886.stderr +++ b/src/test/ui/issue-26886.stderr @@ -29,4 +29,4 @@ LL | use std::sync as other_sync; //~ ERROR the name `sync` is defined multiple error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0252" +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/issue-27842.stderr b/src/test/ui/issue-27842.stderr index 98f2b18dc77b..026594811e47 100644 --- a/src/test/ui/issue-27842.stderr +++ b/src/test/ui/issue-27842.stderr @@ -14,4 +14,4 @@ LL | let _ = tup[i]; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0608" +For more information about this error, try `rustc --explain E0608`. diff --git a/src/test/ui/issue-27942.stderr b/src/test/ui/issue-27942.stderr index 19654a647c57..879eda0f8564 100644 --- a/src/test/ui/issue-27942.stderr +++ b/src/test/ui/issue-27942.stderr @@ -38,4 +38,4 @@ LL | fn select(&self) -> BufferViewHandle; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-2848.stderr b/src/test/ui/issue-2848.stderr index 6ab018b0014b..8f7ebbf95dd9 100644 --- a/src/test/ui/issue-2848.stderr +++ b/src/test/ui/issue-2848.stderr @@ -8,4 +8,4 @@ LL | alpha | beta => {} //~ ERROR variable `beta` is not bound in all pat error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0408" +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/issue-28568.stderr b/src/test/ui/issue-28568.stderr index fecc5a41b3b9..3208074642f0 100644 --- a/src/test/ui/issue-28568.stderr +++ b/src/test/ui/issue-28568.stderr @@ -9,4 +9,4 @@ LL | impl Drop for MyStruct { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/issue-28776.stderr b/src/test/ui/issue-28776.stderr index e426f05ddf6d..3b468a882054 100644 --- a/src/test/ui/issue-28776.stderr +++ b/src/test/ui/issue-28776.stderr @@ -6,4 +6,4 @@ LL | (&ptr::write)(1 as *mut _, 42); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0133" +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/issue-28837.stderr b/src/test/ui/issue-28837.stderr index 62fc0ebec32f..88994eaeb937 100644 --- a/src/test/ui/issue-28837.stderr +++ b/src/test/ui/issue-28837.stderr @@ -120,4 +120,4 @@ LL | a >= a; //~ ERROR binary operation `>=` cannot be applied to type `A` error: aborting due to 15 previous errors -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/issue-28971.stderr b/src/test/ui/issue-28971.stderr index ebd759a9c3cc..df114351ff57 100644 --- a/src/test/ui/issue-28971.stderr +++ b/src/test/ui/issue-28971.stderr @@ -6,7 +6,9 @@ LL | enum Foo { ... LL | Foo::Baz(..) => (), | ^^^^^^^^^^^^ variant not found in `Foo` + | + = note: did you mean `variant::Bar`? error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-29124.stderr b/src/test/ui/issue-29124.stderr index 091671b23097..bd00772dfd28 100644 --- a/src/test/ui/issue-29124.stderr +++ b/src/test/ui/issue-29124.stderr @@ -16,4 +16,4 @@ LL | func.x(); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issue-29723.stderr b/src/test/ui/issue-29723.stderr index 1b4c750471fa..48e50b9dea9c 100644 --- a/src/test/ui/issue-29723.stderr +++ b/src/test/ui/issue-29723.stderr @@ -11,4 +11,4 @@ LL | s error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/issue-3008-1.stderr b/src/test/ui/issue-3008-1.stderr index 282181d51cde..05c1f2aae814 100644 --- a/src/test/ui/issue-3008-1.stderr +++ b/src/test/ui/issue-3008-1.stderr @@ -11,4 +11,4 @@ LL | BarSome(Bar) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/issue-3008-2.stderr b/src/test/ui/issue-3008-2.stderr index a015e6d621db..d02fb45be496 100644 --- a/src/test/ui/issue-3008-2.stderr +++ b/src/test/ui/issue-3008-2.stderr @@ -10,4 +10,4 @@ LL | struct bar { x: bar } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/issue-30255.stderr b/src/test/ui/issue-30255.stderr index 6a55025d7b1d..9556f6d9e230 100644 --- a/src/test/ui/issue-30255.stderr +++ b/src/test/ui/issue-30255.stderr @@ -24,4 +24,4 @@ LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0106" +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/issue-30302.stderr b/src/test/ui/issue-30302.stderr index 6528058428a4..42dfdadf9c46 100644 --- a/src/test/ui/issue-30302.stderr +++ b/src/test/ui/issue-30302.stderr @@ -23,3 +23,4 @@ LL | #![deny(unreachable_patterns)] error: aborting due to previous error +For more information about this error, try `rustc --explain E0170`. diff --git a/src/test/ui/issue-3044.stderr b/src/test/ui/issue-3044.stderr index 00f9b302ffbf..cdca9be48ac6 100644 --- a/src/test/ui/issue-3044.stderr +++ b/src/test/ui/issue-3044.stderr @@ -6,4 +6,4 @@ LL | needlesArr.iter().fold(|x, y| { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/issue-32326.stderr b/src/test/ui/issue-32326.stderr index 290c491b489a..1aa99c402ed8 100644 --- a/src/test/ui/issue-32326.stderr +++ b/src/test/ui/issue-32326.stderr @@ -12,4 +12,4 @@ LL | Plus(Expr, Expr), error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/issue-33525.stderr b/src/test/ui/issue-33525.stderr index ad308b87b376..2b365e1cc98b 100644 --- a/src/test/ui/issue-33525.stderr +++ b/src/test/ui/issue-33525.stderr @@ -18,5 +18,5 @@ LL | "".ipsum; //~ ERROR no field error: aborting due to 3 previous errors -You've got a few errors: E0425, E0609 -If you want more information on an error, try using "rustc --explain E0425" +Some errors occurred: E0425, E0609. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/issue-33941.stderr b/src/test/ui/issue-33941.stderr index ef76158682b7..f20b87fa371f 100644 --- a/src/test/ui/issue-33941.stderr +++ b/src/test/ui/issue-33941.stderr @@ -19,4 +19,4 @@ LL | for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0271" +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/issue-34047.stderr b/src/test/ui/issue-34047.stderr index efd6222db20e..10804cc6fff4 100644 --- a/src/test/ui/issue-34047.stderr +++ b/src/test/ui/issue-34047.stderr @@ -9,4 +9,4 @@ LL | mut C => {} //~ ERROR match bindings cannot shadow constants error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0530" +For more information about this error, try `rustc --explain E0530`. diff --git a/src/test/ui/issue-34209.stderr b/src/test/ui/issue-34209.stderr index faf3f3856fd6..5c31acea5b60 100644 --- a/src/test/ui/issue-34209.stderr +++ b/src/test/ui/issue-34209.stderr @@ -8,4 +8,4 @@ LL | S::B{ } => { }, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0223" +For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/issue-35139.stderr b/src/test/ui/issue-35139.stderr index 79b0ecff94ed..7ec1459dd169 100644 --- a/src/test/ui/issue-35139.stderr +++ b/src/test/ui/issue-35139.stderr @@ -6,4 +6,4 @@ LL | impl<'a> MethodType for MTFn { //~ ERROR E0207 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0207" +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/issue-35241.stderr b/src/test/ui/issue-35241.stderr index be0b21f94601..42bf0aae5b12 100644 --- a/src/test/ui/issue-35241.stderr +++ b/src/test/ui/issue-35241.stderr @@ -13,4 +13,4 @@ LL | fn test() -> Foo { Foo } //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-35675.stderr b/src/test/ui/issue-35675.stderr index 84054b532de8..fef8de3a28d9 100644 --- a/src/test/ui/issue-35675.stderr +++ b/src/test/ui/issue-35675.stderr @@ -65,5 +65,5 @@ LL | fn qux() -> Some { error: aborting due to 7 previous errors -You've got a few errors: E0412, E0425, E0573 -If you want more information on an error, try using "rustc --explain E0412" +Some errors occurred: E0412, E0425, E0573. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/issue-35869.rs b/src/test/ui/issue-35869.rs index 17ee62aed1b8..7bab22edcf68 100644 --- a/src/test/ui/issue-35869.rs +++ b/src/test/ui/issue-35869.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait)] - trait Foo { fn foo(_: fn(u8) -> ()); fn bar(_: Option); diff --git a/src/test/ui/issue-35869.stderr b/src/test/ui/issue-35869.stderr index e90906ee8416..1930dd5bbcb8 100644 --- a/src/test/ui/issue-35869.stderr +++ b/src/test/ui/issue-35869.stderr @@ -1,5 +1,5 @@ error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/issue-35869.rs:23:15 + --> $DIR/issue-35869.rs:21:15 | LL | fn foo(_: fn(u8) -> ()); | ------------ type in trait @@ -11,7 +11,7 @@ LL | fn foo(_: fn(u16) -> ()) {} found type `fn(fn(u16))` error[E0053]: method `bar` has an incompatible type for trait - --> $DIR/issue-35869.rs:25:15 + --> $DIR/issue-35869.rs:23:15 | LL | fn bar(_: Option); | ---------- type in trait @@ -23,7 +23,7 @@ LL | fn bar(_: Option) {} found type `fn(std::option::Option)` error[E0053]: method `baz` has an incompatible type for trait - --> $DIR/issue-35869.rs:27:15 + --> $DIR/issue-35869.rs:25:15 | LL | fn baz(_: (u8, u16)); | --------- type in trait @@ -35,7 +35,7 @@ LL | fn baz(_: (u16, u16)) {} found type `fn((u16, u16))` error[E0053]: method `qux` has an incompatible type for trait - --> $DIR/issue-35869.rs:29:17 + --> $DIR/issue-35869.rs:27:17 | LL | fn qux() -> u8; | -- type in trait @@ -48,4 +48,4 @@ LL | fn qux() -> u16 { 5u16 } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0053" +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/issue-36163.stderr b/src/test/ui/issue-36163.stderr index 4323eb4858f4..7ab4bd46ebf4 100644 --- a/src/test/ui/issue-36163.stderr +++ b/src/test/ui/issue-36163.stderr @@ -28,4 +28,4 @@ LL | const A: isize = Foo::B as isize; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/issue-36400.stderr b/src/test/ui/issue-36400.stderr index 4a632356b4e1..dbd6999b4f29 100644 --- a/src/test/ui/issue-36400.stderr +++ b/src/test/ui/issue-36400.stderr @@ -8,4 +8,4 @@ LL | f(&mut *x); //~ ERROR cannot borrow immutable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/issue-36708.stderr b/src/test/ui/issue-36708.stderr index d2aa5b6c0ec3..4e28a769f506 100644 --- a/src/test/ui/issue-36708.stderr +++ b/src/test/ui/issue-36708.stderr @@ -6,4 +6,4 @@ LL | fn foo() {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0049" +For more information about this error, try `rustc --explain E0049`. diff --git a/src/test/ui/issue-3779.stderr b/src/test/ui/issue-3779.stderr index 6dcbabbe39a5..f5e89638f161 100644 --- a/src/test/ui/issue-3779.stderr +++ b/src/test/ui/issue-3779.stderr @@ -11,4 +11,4 @@ LL | element: Option error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/issue-37884.stderr b/src/test/ui/issue-37884.stderr index d1f6cb7d9226..73fbb2d32038 100644 --- a/src/test/ui/issue-37884.stderr +++ b/src/test/ui/issue-37884.stderr @@ -29,4 +29,4 @@ LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr index 999583dcd311..70be30e4f71d 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr @@ -9,4 +9,4 @@ LL | let e = f.v[0]; //~ ERROR cannot move out of indexed content error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0507" +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr index 3703d32be064..4ed28963b5b9 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr @@ -9,4 +9,4 @@ LL | let (a, b) = x[0]; //~ ERROR cannot move out of indexed content error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0507" +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index df7b8a6525f8..3f76b25692cf 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -10,4 +10,4 @@ LL | 3_i32.f() error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0689" +For more information about this error, try `rustc --explain E0689`. diff --git a/src/test/ui/issue-42106.stderr b/src/test/ui/issue-42106.stderr index c9629cc6e61d..b8944bb24239 100644 --- a/src/test/ui/issue-42106.stderr +++ b/src/test/ui/issue-42106.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0502" +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/issue-4335.stderr b/src/test/ui/issue-4335.stderr index 90b94a597a5d..80f5b445bb64 100644 --- a/src/test/ui/issue-4335.stderr +++ b/src/test/ui/issue-4335.stderr @@ -18,5 +18,5 @@ LL | id(Box::new(|| *v)) error: aborting due to 2 previous errors -You've got a few errors: E0373, E0507 -If you want more information on an error, try using "rustc --explain E0373" +Some errors occurred: E0373, E0507. +For more information about an error, try `rustc --explain E0373`. diff --git a/src/test/ui/issue-44023.stderr b/src/test/ui/issue-44023.stderr index a3dde7321c26..3baf7ec0277b 100644 --- a/src/test/ui/issue-44023.stderr +++ b/src/test/ui/issue-44023.stderr @@ -11,4 +11,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr index 443b28cf0996..de7c11732e4a 100644 --- a/src/test/ui/issue-44406.stderr +++ b/src/test/ui/issue-44406.stderr @@ -13,3 +13,5 @@ LL | bar(baz: $rest) LL | foo!(true); //~ ERROR expected type, found keyword | ^^^^ expecting a type here because of type ascription +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issue-45157.rs b/src/test/ui/issue-45157.rs index cff338f76c50..a906d193d995 100644 --- a/src/test/ui/issue-45157.rs +++ b/src/test/ui/issue-45157.rs @@ -37,7 +37,6 @@ fn main() { let nref = &u.z.c; //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502] println!("{} {}", mref, nref) - //~^ ERROR cannot borrow `u.s.a` as mutable because it is also borrowed as immutable [E0502] } } diff --git a/src/test/ui/issue-45157.stderr b/src/test/ui/issue-45157.stderr index bec91f7f70de..e528a84ebd1a 100644 --- a/src/test/ui/issue-45157.stderr +++ b/src/test/ui/issue-45157.stderr @@ -10,17 +10,6 @@ LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also bo LL | println!("{} {}", mref, nref) | ---- borrow later used here -error[E0502]: cannot borrow `u.s.a` as mutable because it is also borrowed as immutable - --> $DIR/issue-45157.rs:39:27 - | -LL | let nref = &u.z.c; - | ------ immutable borrow occurs here -LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502] -LL | println!("{} {}", mref, nref) - | ^^^^ ---- borrow later used here - | | - | mutable borrow occurs here +error: aborting due to previous error -error: aborting due to 2 previous errors - -If you want more information on this error, try using "rustc --explain E0502" +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/issue-45697-1.stderr b/src/test/ui/issue-45697-1.stderr index 2a6d219267d2..aa899c5aee9e 100644 --- a/src/test/ui/issue-45697-1.stderr +++ b/src/test/ui/issue-45697-1.stderr @@ -16,5 +16,5 @@ LL | *y.pointer += 1; error: aborting due to 2 previous errors -You've got a few errors: E0503, E0506 -If you want more information on an error, try using "rustc --explain E0503" +Some errors occurred: E0503, E0506. +For more information about an error, try `rustc --explain E0503`. diff --git a/src/test/ui/issue-45697.stderr b/src/test/ui/issue-45697.stderr index 30baded7dad9..babfc33b9458 100644 --- a/src/test/ui/issue-45697.stderr +++ b/src/test/ui/issue-45697.stderr @@ -16,5 +16,5 @@ LL | *y.pointer += 1; error: aborting due to 2 previous errors -You've got a few errors: E0503, E0506 -If you want more information on an error, try using "rustc --explain E0503" +Some errors occurred: E0503, E0506. +For more information about an error, try `rustc --explain E0503`. diff --git a/src/test/ui/issue-45730.stderr b/src/test/ui/issue-45730.stderr index b10c69f26c5c..aa5773e3dbff 100644 --- a/src/test/ui/issue-45730.stderr +++ b/src/test/ui/issue-45730.stderr @@ -30,4 +30,4 @@ LL | let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0641" +For more information about this error, try `rustc --explain E0641`. diff --git a/src/test/ui/issue-46112.stderr b/src/test/ui/issue-46112.stderr index 7c6796841650..796187b93aa9 100644 --- a/src/test/ui/issue-46112.stderr +++ b/src/test/ui/issue-46112.stderr @@ -12,4 +12,4 @@ LL | fn main() { test(Ok(())); } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-46332.stderr b/src/test/ui/issue-46332.stderr index c3b17884676b..06553767cc97 100644 --- a/src/test/ui/issue-46332.stderr +++ b/src/test/ui/issue-46332.stderr @@ -6,4 +6,4 @@ LL | TyUInt {}; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0422" +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/issue-46471-1.stderr b/src/test/ui/issue-46471-1.stderr index b46bcbd69112..bfd5bfa9f727 100644 --- a/src/test/ui/issue-46471-1.stderr +++ b/src/test/ui/issue-46471-1.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-46471.stderr b/src/test/ui/issue-46471.stderr index ce2b2c310259..ac974afa13a1 100644 --- a/src/test/ui/issue-46471.stderr +++ b/src/test/ui/issue-46471.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-46472.stderr b/src/test/ui/issue-46472.stderr index a0d41c961a44..9b55b78b43d5 100644 --- a/src/test/ui/issue-46472.stderr +++ b/src/test/ui/issue-46472.stderr @@ -30,4 +30,4 @@ LL | fn bar<'a>() -> &'a mut u32 { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-46983.stderr b/src/test/ui/issue-46983.stderr index 67c8fa8261f7..31aeebd5a721 100644 --- a/src/test/ui/issue-46983.stderr +++ b/src/test/ui/issue-46983.stderr @@ -8,4 +8,4 @@ LL | &*x error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/issue-47184.rs b/src/test/ui/issue-47184.rs new file mode 100644 index 000000000000..0831b7e0af8e --- /dev/null +++ b/src/test/ui/issue-47184.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +fn main() { + let _vec: Vec<&'static String> = vec![&String::new()]; + //~^ ERROR borrowed value does not live long enough [E0597] +} diff --git a/src/test/ui/issue-47184.stderr b/src/test/ui/issue-47184.stderr new file mode 100644 index 000000000000..a9eb33f01e3e --- /dev/null +++ b/src/test/ui/issue-47184.stderr @@ -0,0 +1,14 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/issue-47184.rs:14:44 + | +LL | let _vec: Vec<&'static String> = vec![&String::new()]; + | ^^^^^^^^^^^^^ temporary value does not live long enough +LL | //~^ ERROR borrowed value does not live long enough [E0597] +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-47377.stderr b/src/test/ui/issue-47377.stderr index 2de117489c39..66c4a1277a0f 100644 --- a/src/test/ui/issue-47377.stderr +++ b/src/test/ui/issue-47377.stderr @@ -10,4 +10,4 @@ LL | let _a = b.to_owned() + ", World!"; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/issue-47380.stderr b/src/test/ui/issue-47380.stderr index 968dc614ad68..585a2ec64d06 100644 --- a/src/test/ui/issue-47380.stderr +++ b/src/test/ui/issue-47380.stderr @@ -10,4 +10,4 @@ LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/issue-47511.stderr b/src/test/ui/issue-47511.stderr index 2b8ba8794fb7..6ee71fc6c73d 100644 --- a/src/test/ui/issue-47511.stderr +++ b/src/test/ui/issue-47511.stderr @@ -14,4 +14,4 @@ LL | fn g<'a>(_: X<'a>) -> X<'a> { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0581" +For more information about this error, try `rustc --explain E0581`. diff --git a/src/test/ui/issue-47623.stderr b/src/test/ui/issue-47623.stderr index fd15ce784208..8cbed1c293e1 100644 --- a/src/test/ui/issue-47623.stderr +++ b/src/test/ui/issue-47623.stderr @@ -6,4 +6,4 @@ LL | use self; //~ERROR `self` imports are only allowed within a { } list error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0429" +For more information about this error, try `rustc --explain E0429`. diff --git a/src/test/ui/issue-47706-trait.rs b/src/test/ui/issue-47706-trait.rs index 86a9da49a054..4ce653547da0 100644 --- a/src/test/ui/issue-47706-trait.rs +++ b/src/test/ui/issue-47706-trait.rs @@ -14,3 +14,5 @@ trait T { } //~^^ ERROR function is expected to take a single 0-tuple as argument } + +fn main() {} diff --git a/src/test/ui/issue-47706-trait.stderr b/src/test/ui/issue-47706-trait.stderr index a6a270b057a4..717b3eb0b562 100644 --- a/src/test/ui/issue-47706-trait.stderr +++ b/src/test/ui/issue-47706-trait.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error[E0593]: function is expected to take a single 0-tuple as argument, but it takes 2 distinct arguments --> $DIR/issue-47706-trait.rs:13:20 | @@ -8,7 +6,6 @@ LL | fn f(&self, _: ()) { LL | None::<()>.map(Self::f); | ^^^ expected function that takes a single 0-tuple as argument -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0593, E0601 -If you want more information on an error, try using "rustc --explain E0593" +For more information about this error, try `rustc --explain E0593`. diff --git a/src/test/ui/issue-47706.stderr b/src/test/ui/issue-47706.stderr index ef48d4d7aaef..0a5c8beccd13 100644 --- a/src/test/ui/issue-47706.stderr +++ b/src/test/ui/issue-47706.stderr @@ -28,4 +28,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0593" +For more information about this error, try `rustc --explain E0593`. diff --git a/src/test/ui/issue-48132.rs b/src/test/ui/issue-48132.rs new file mode 100644 index 000000000000..87fee986de76 --- /dev/null +++ b/src/test/ui/issue-48132.rs @@ -0,0 +1,42 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #48132. This was failing due to problems around +// the projection caching and dropck type enumeration. + +// run-pass + +#![feature(nll)] +#![allow(warnings)] + +struct Inner { + iterator: I, + item: V, +} + +struct Outer { + inner: Inner, +} + +fn outer(iterator: I) -> Outer +where I: Iterator, + I::Item: Default, +{ + Outer { + inner: Inner { + iterator: iterator, + item: Default::default(), + } + } +} + +fn main() { + outer(std::iter::once(&1).cloned()); +} diff --git a/src/test/ui/issue-48179.rs b/src/test/ui/issue-48179.rs new file mode 100644 index 000000000000..745b59e0658f --- /dev/null +++ b/src/test/ui/issue-48179.rs @@ -0,0 +1,51 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #48132. This was failing due to problems around +// the projection caching and dropck type enumeration. + +// run-pass + +#![feature(nll)] +#![allow(warnings)] + +pub struct Container { + value: Option, +} + +impl Container { + pub fn new(iter: T) -> Self { + panic!() + } +} + +pub struct Wrapper<'a> { + content: &'a Content, +} + +impl<'a, 'de> Wrapper<'a> { + pub fn new(content: &'a Content) -> Self { + Wrapper { + content: content, + } + } +} + +pub struct Content; + +fn crash_it(content: Content) { + let items = vec![content]; + let map = items.iter().map(|ref o| Wrapper::new(o)); + + let mut map_visitor = Container::new(map); + +} + +fn main() {} diff --git a/src/test/ui/issue-48276.rs b/src/test/ui/issue-48276.rs new file mode 100644 index 000000000000..30d11a2e37f1 --- /dev/null +++ b/src/test/ui/issue-48276.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for issue #48276 - ICE when self type does not match what is +// required by a trait and regions are involved. + +trait MyFrom { + fn from(a: A) -> Self; +} + +struct A; + +impl<'a, 'b> MyFrom for &'a str { + fn from(self: &'a Self) -> &'b str { + //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait + "asdf" + } +} + +struct B; + +impl From for B { + fn from(&self) -> B { + //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait + B + } +} + +impl From for &'static str { + fn from(&self) -> &'static str { + //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait + "" + } +} + +fn main(){} diff --git a/src/test/ui/issue-48276.stderr b/src/test/ui/issue-48276.stderr new file mode 100644 index 000000000000..db4894aa6916 --- /dev/null +++ b/src/test/ui/issue-48276.stderr @@ -0,0 +1,28 @@ +error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait + --> $DIR/issue-48276.rs:21:5 + | +LL | fn from(a: A) -> Self; + | ---------------------- trait method declared without `&self` +... +LL | fn from(self: &'a Self) -> &'b str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl + +error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait + --> $DIR/issue-48276.rs:30:5 + | +LL | fn from(&self) -> B { + | ^^^^^^^^^^^^^^^^^^^ `&self` used in impl + | + = note: `from` from trait: `fn(T) -> Self` + +error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait + --> $DIR/issue-48276.rs:37:5 + | +LL | fn from(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl + | + = note: `from` from trait: `fn(T) -> Self` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0185`. diff --git a/src/test/ui/issue-49040.rs b/src/test/ui/issue-49040.rs new file mode 100644 index 000000000000..866ecd9e1d95 --- /dev/null +++ b/src/test/ui/issue-49040.rs @@ -0,0 +1,12 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused_variables)]; //~ ERROR expected item, found `;` +fn main() {} diff --git a/src/test/ui/issue-49040.stderr b/src/test/ui/issue-49040.stderr new file mode 100644 index 000000000000..b6f624dac7db --- /dev/null +++ b/src/test/ui/issue-49040.stderr @@ -0,0 +1,8 @@ +error: expected item, found `;` + --> $DIR/issue-49040.rs:11:28 + | +LL | #![allow(unused_variables)]; //~ ERROR expected item, found `;` + | ^ help: consider removing this semicolon + +error: aborting due to previous error + diff --git a/src/test/ui/issue-49074.rs b/src/test/ui/issue-49074.rs new file mode 100644 index 000000000000..2e7e11844109 --- /dev/null +++ b/src/test/ui/issue-49074.rs @@ -0,0 +1,24 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that unknown attribute error is shown even if there are unresolved macros. + +#[marco_use] // typo +//~^ ERROR The attribute `marco_use` is currently unknown to the compiler +mod foo { + macro_rules! bar { + () => (); + } +} + +fn main() { + bar!(); + //~^ ERROR cannot find macro `bar!` +} diff --git a/src/test/ui/issue-49074.stderr b/src/test/ui/issue-49074.stderr new file mode 100644 index 000000000000..c9984ea2e9a8 --- /dev/null +++ b/src/test/ui/issue-49074.stderr @@ -0,0 +1,19 @@ +error: cannot find macro `bar!` in this scope + --> $DIR/issue-49074.rs:22:4 + | +LL | bar!(); + | ^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/issue-49074.rs:13:1 + | +LL | #[marco_use] // typo + | ^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issue-49257.rs b/src/test/ui/issue-49257.rs new file mode 100644 index 000000000000..a31984922374 --- /dev/null +++ b/src/test/ui/issue-49257.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test for #49257: +// emits good diagnostics for `..` pattern fragments not in the last position. + +#![allow(unused)] + +struct Point { x: u8, y: u8 } + +fn main() { + let p = Point { x: 0, y: 0 }; + let Point { .., y } = p; //~ ERROR expected `}`, found `,` + //~| ERROR pattern does not mention fields `x`, `y` +} diff --git a/src/test/ui/issue-49257.stderr b/src/test/ui/issue-49257.stderr new file mode 100644 index 000000000000..fec990764bb1 --- /dev/null +++ b/src/test/ui/issue-49257.stderr @@ -0,0 +1,15 @@ +error: expected `}`, found `,` + --> $DIR/issue-49257.rs:20:19 + | +LL | let Point { .., y } = p; //~ ERROR expected `}`, found `,` + | ^ `..` must be in the last position, and cannot have a trailing comma + +error[E0027]: pattern does not mention fields `x`, `y` + --> $DIR/issue-49257.rs:20:9 + | +LL | let Point { .., y } = p; //~ ERROR expected `}`, found `,` + | ^^^^^^^^^^^^^^^ missing fields `x`, `y` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/issue-4935.stderr b/src/test/ui/issue-4935.stderr index fb5a2261c1f6..25efd54443ae 100644 --- a/src/test/ui/issue-4935.stderr +++ b/src/test/ui/issue-4935.stderr @@ -9,4 +9,4 @@ LL | fn main() { foo(5, 6) } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/issue-5239-1.stderr b/src/test/ui/issue-5239-1.stderr index 6a6405726232..2f9204e72d3f 100644 --- a/src/test/ui/issue-5239-1.stderr +++ b/src/test/ui/issue-5239-1.stderr @@ -8,4 +8,4 @@ LL | let x = |ref x: isize| { x += 1; }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0368" +For more information about this error, try `rustc --explain E0368`. diff --git a/src/test/ui/issue-6458-3.stderr b/src/test/ui/issue-6458-3.stderr index 8eb864a878a1..c09b2643dfa2 100644 --- a/src/test/ui/issue-6458-3.stderr +++ b/src/test/ui/issue-6458-3.stderr @@ -6,4 +6,4 @@ LL | mem::transmute(0); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issue-6458-4.stderr b/src/test/ui/issue-6458-4.stderr index 2615085a930d..13b0ace64652 100644 --- a/src/test/ui/issue-6458-4.stderr +++ b/src/test/ui/issue-6458-4.stderr @@ -13,4 +13,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-6458.stderr b/src/test/ui/issue-6458.stderr index 058a6ea5c7d7..701795c748dc 100644 --- a/src/test/ui/issue-6458.stderr +++ b/src/test/ui/issue-6458.stderr @@ -6,4 +6,4 @@ LL | foo(TypeWithState(marker::PhantomData)); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issue-7813.stderr b/src/test/ui/issue-7813.stderr index b4291684db4b..34837e90e4f7 100644 --- a/src/test/ui/issue-7813.stderr +++ b/src/test/ui/issue-7813.stderr @@ -8,4 +8,4 @@ LL | let v = &[]; //~ ERROR type annotations needed error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetime-elision-return-type-requires-explicit-lifetime.stderr index b8145a893aac..30cff86ed1d4 100644 --- a/src/test/ui/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -52,4 +52,4 @@ LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0106" +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr index 4cf0ad0888b2..87cb17489135 100644 --- a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr +++ b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.stderr @@ -9,4 +9,4 @@ LL | &*x //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr index 5b65dffdb38b..29163361e23f 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr @@ -9,4 +9,4 @@ LL | other //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr index b11b96595dfa..e18156179a20 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -8,4 +8,4 @@ LL | if x > y { x } else { y } //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr index a334f97b3cc4..f208fb57f5b7 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -8,4 +8,4 @@ LL | if x > y { x } else { y } //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr index d61292330b89..7604b9a9017e 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -8,4 +8,4 @@ LL | if x > y { x } else { y } //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 9efdb33f7e58..83c6ff19867d 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -9,4 +9,4 @@ LL | if true { &self.field } else { x } //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr index f27d869a4d4a..0eb8afbb26b6 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -11,4 +11,4 @@ LL | if x > y { x } else { y } //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index d098df514e1a..9893eee77e8c 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -8,4 +8,4 @@ LL | if x > y { x } else { y } //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr index c72d25fe2a9f..b6dfdff60be2 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -11,4 +11,4 @@ LL | x //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr index 4d9e26c06326..6c32adc11ce0 100644 --- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -11,4 +11,4 @@ LL | if true { x } else { self } //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr index 90f210148522..4710ebfa9679 100644 --- a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -8,4 +8,4 @@ LL | fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0106" +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr index 5d3316276916..5c9b7666de65 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -8,4 +8,4 @@ LL | y.push(x); //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr index d840467835ba..4cfb76f85f2a 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr @@ -9,4 +9,4 @@ LL | x.push(y); //~ ERROR explicit lifetime required error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index a5433ec08340..ede76bca2ba0 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR explicit lifetime error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index dd220a7e661d..9884c0f35116 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr index bba52f408b0c..114024c2fb02 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -9,4 +9,4 @@ LL | x.push(z); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr index 673aee256b4f..32fc8b42f42e 100644 --- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -8,4 +8,4 @@ LL | let a: &mut Vec> = x; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr index cbe48abbb993..f62848ffa8c1 100644 --- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -8,4 +8,4 @@ LL | let a: &mut Vec> = x; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr index eb7985a565ff..f3716c307035 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -8,4 +8,4 @@ LL | v = x; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr index e9c156149d41..5a584296d3ba 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -16,4 +16,4 @@ LL | z.push((x,y)); //~ ERROR lifetime mismatch error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr deleted file mode 100644 index 19339800a7a9..000000000000 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-4.rs:12:13 - | -11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | --- --- these references are declared with different lifetimes... -12 | z.push((x,y)); - | ^ ...but data flows into `z` here - -error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-4.rs:12:15 - | -11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | --- --- these references are declared with different lifetimes... -12 | z.push((x,y)); - | ^ ...but data flows into `z` here - -error: aborting due to 2 previous errors - -If you want more information on this error, try using "rustc --explain E0623" diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr index 19cd661505ad..158f40f2969a 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr @@ -8,4 +8,4 @@ LL | x.b = y.b; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr index 52a319fad610..546789eedcb9 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr @@ -10,4 +10,4 @@ LL | x.a = x.b; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr index 121afa47bc1b..ccc5e02ab704 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr @@ -10,4 +10,4 @@ LL | x.a = x.b; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr index 7348b366e801..f69bcb642978 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr @@ -9,4 +9,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr index 5478abfdbc00..f9530c436a0a 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr index 1cde0d83feb1..243103e2d180 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr index ca6c4337b9b8..c4dd28234317 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr index 8bcc7d4a92bf..52293e453061 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr @@ -10,4 +10,4 @@ LL | y = x.b; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr index 80639d9359e2..b5d10e573c4e 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr @@ -8,4 +8,4 @@ LL | y.b = x; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr index c0ceefdea171..089132995206 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr @@ -8,4 +8,4 @@ LL | y.b = x; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr index 28af2905e4ae..133611ae4894 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr @@ -8,4 +8,4 @@ LL | x.b = y; //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr index ff2492b94360..01ea885b63ea 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr @@ -10,4 +10,4 @@ LL | x //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr index b6bd1c5c9221..aa5ab5402959 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr @@ -10,4 +10,4 @@ LL | if true { x } else { self } //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index 5a5abf3f98b8..8a9ee9a05b81 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -8,4 +8,4 @@ LL | y.push(z); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr index b09877ede38a..65c9ea4e757f 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index 9e18c2e11bf7..43ca5cd603f1 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -8,4 +8,4 @@ LL | y.push(z); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr index d73af970e56e..57187a47239c 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr @@ -8,4 +8,4 @@ LL | x.push(y); //~ ERROR lifetime mismatch error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr b/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr index 8a69514932af..437431189665 100644 --- a/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr +++ b/src/test/ui/lifetime-errors/liveness-assign-imm-local-notes.stderr @@ -62,4 +62,4 @@ LL | x = 2; //~ ERROR (Ast) [E0384] error: aborting due to 8 previous errors -If you want more information on this error, try using "rustc --explain E0384" +For more information about this error, try `rustc --explain E0384`. diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index aaa01a86d60a..c78b09a86a49 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -13,4 +13,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index b58cbfd7b2ea..ea79990bbb1f 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -111,5 +111,5 @@ LL | | } error: aborting due to 7 previous errors -You've got a few errors: E0309, E0310 -If you want more information on an error, try using "rustc --explain E0309" +Some errors occurred: E0309, E0310. +For more information about an error, try `rustc --explain E0309`. diff --git a/src/test/ui/lint-ctypes.rs b/src/test/ui/lint-ctypes.rs index 77cb1ef0f513..85957831653e 100644 --- a/src/test/ui/lint-ctypes.rs +++ b/src/test/ui/lint-ctypes.rs @@ -9,7 +9,7 @@ // except according to those terms. #![deny(improper_ctypes)] -#![feature(libc, i128_type, repr_transparent)] +#![feature(libc, repr_transparent)] extern crate libc; diff --git a/src/test/ui/lint-forbid-attr.stderr b/src/test/ui/lint-forbid-attr.stderr index 73a40a46c110..aa0c0c1f5c2b 100644 --- a/src/test/ui/lint-forbid-attr.stderr +++ b/src/test/ui/lint-forbid-attr.stderr @@ -9,4 +9,4 @@ LL | #[allow(deprecated)] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0453" +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint-output-format-2.stderr b/src/test/ui/lint-output-format-2.stderr index b2d1e1ac0582..d484061ef966 100644 --- a/src/test/ui/lint-output-format-2.stderr +++ b/src/test/ui/lint-output-format-2.stderr @@ -22,3 +22,5 @@ LL | | let _y = bar(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr index 62bec0fe7b33..e49dcd4a2d19 100644 --- a/src/test/ui/lint/outer-forbid.stderr +++ b/src/test/ui/lint/outer-forbid.stderr @@ -27,4 +27,4 @@ LL | #[allow(bad_style)] //~ ERROR overruled error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0453" +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/type-overflow.rs b/src/test/ui/lint/type-overflow.rs index 495989587e58..30e6fb2883b8 100644 --- a/src/test/ui/lint/type-overflow.rs +++ b/src/test/ui/lint/type-overflow.rs @@ -10,8 +10,6 @@ // must-compile-successfully -#![feature(i128_type)] - fn main() { let error = 255i8; //~WARNING literal out of range for i8 diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index d3fcb1335e20..6f5d3d07aea2 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -1,5 +1,5 @@ warning: literal out of range for i8 - --> $DIR/type-overflow.rs:16:17 + --> $DIR/type-overflow.rs:14:17 | LL | let error = 255i8; //~WARNING literal out of range for i8 | ^^^^^ @@ -7,7 +7,7 @@ LL | let error = 255i8; //~WARNING literal out of range for i8 = note: #[warn(overflowing_literals)] on by default warning: literal out of range for i8 - --> $DIR/type-overflow.rs:21:16 + --> $DIR/type-overflow.rs:19:16 | LL | let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 | ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8` @@ -15,7 +15,7 @@ LL | let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8` warning: literal out of range for i64 - --> $DIR/type-overflow.rs:23:16 + --> $DIR/type-overflow.rs:21:16 | LL | let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64 | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64` @@ -23,7 +23,7 @@ LL | let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range fo = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64` warning: literal out of range for u32 - --> $DIR/type-overflow.rs:25:16 + --> $DIR/type-overflow.rs:23:16 | LL | let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 | ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64` @@ -31,7 +31,7 @@ LL | let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32` warning: literal out of range for i128 - --> $DIR/type-overflow.rs:27:22 + --> $DIR/type-overflow.rs:25:22 | LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; = help: consider using `u128` instead warning: literal out of range for i32 - --> $DIR/type-overflow.rs:30:16 + --> $DIR/type-overflow.rs:28:16 | LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 | ^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i = help: consider using `i128` instead warning: literal out of range for i8 - --> $DIR/type-overflow.rs:32:17 + --> $DIR/type-overflow.rs:30:17 | LL | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 | ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index 00624f7e5ca4..b90c5aa3a4ba 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -384,7 +384,6 @@ LL | use std::collections::hash_map::Iter; | and 8 other candidates -If you want more information on this error, try using /"rustc --explain E0412/" " } { @@ -397,3 +396,12 @@ If you want more information on this error, try using /"rustc --explain E0412/" " } +{ + "message": "For more information about this error, try `rustc --explain E0412`.", + "code": null, + "level": "", + "spans": [], + "children": [], + "rendered": "For more information about this error, try `rustc --explain E0412`. +" +} diff --git a/src/test/ui/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness-return-last-stmt-semi.stderr index faf098296e8b..1fa001879a0a 100644 --- a/src/test/ui/liveness-return-last-stmt-semi.stderr +++ b/src/test/ui/liveness-return-last-stmt-semi.stderr @@ -49,4 +49,4 @@ LL | | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr index 0f04847df4cd..4421f557e420 100644 --- a/src/test/ui/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loop-break-value-no-repeat.stderr @@ -10,4 +10,4 @@ LL | break //~ ERROR `break` with value from a `for` loop error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0571" +For more information about this error, try `rustc --explain E0571`. diff --git a/src/test/ui/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops-reject-duplicate-labels-2.stderr index d35ed4ff88a6..830270a99d11 100644 --- a/src/test/ui/loops-reject-duplicate-labels-2.stderr +++ b/src/test/ui/loops-reject-duplicate-labels-2.stderr @@ -70,3 +70,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-duplicate-labels.stderr b/src/test/ui/loops-reject-duplicate-labels.stderr index d1b874ea9972..a71f98b812a8 100644 --- a/src/test/ui/loops-reject-duplicate-labels.stderr +++ b/src/test/ui/loops-reject-duplicate-labels.stderr @@ -73,3 +73,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr b/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr index 0cdd58fdbd75..af524d5b0176 100644 --- a/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr +++ b/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr @@ -108,3 +108,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/loops-reject-lifetime-shadowing-label.stderr b/src/test/ui/loops-reject-lifetime-shadowing-label.stderr index a050aec50c72..999cfb9cc3c6 100644 --- a/src/test/ui/loops-reject-lifetime-shadowing-label.stderr +++ b/src/test/ui/loops-reject-lifetime-shadowing-label.stderr @@ -14,3 +14,5 @@ LL | | foo(); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr index 0fa6fdae4812..9b40062bd57b 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-hr.stderr @@ -16,4 +16,4 @@ LL | | }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 49fb063a9c68..6a69e7cc7172 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -16,4 +16,4 @@ LL | | }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/macro-context.stderr b/src/test/ui/macro-context.stderr index 4dc6bbe4d656..b3e67fb2607c 100644 --- a/src/test/ui/macro-context.stderr +++ b/src/test/ui/macro-context.stderr @@ -43,3 +43,5 @@ LL | () => ( i ; typeof ); //~ ERROR expected expression, found reserved k LL | m!(); | ----- in this macro invocation +error: aborting due to 4 previous errors + diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 58fc3c3a65b0..eab6cd23748c 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -80,5 +80,5 @@ LL | 2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous n error: aborting due to 8 previous errors -You've got a few errors: E0599, E0609, E0610, E0689 -If you want more information on an error, try using "rustc --explain E0599" +Some errors occurred: E0599, E0609, E0610, E0689. +For more information about an error, try `rustc --explain E0599`. diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr index a0ed467b5af5..a4fe702c0d93 100644 --- a/src/test/ui/macros/macro-backtrace-nested.stderr +++ b/src/test/ui/macros/macro-backtrace-nested.stderr @@ -18,4 +18,4 @@ LL | call_nested_expr_sum!(); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr index d573523a5a0d..0f9f0607c5bf 100644 --- a/src/test/ui/macros/macro_path_as_generic_bound.stderr +++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve. Use of undeclared type or module `m` LL | foo!(m::m2::A); //~ ERROR failed to resolve | ^ Use of undeclared type or module `m` -error: cannot continue compilation due to previous error +error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0433" +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr index 3343c210d24d..c67095d9ee75 100644 --- a/src/test/ui/macros/span-covering-argument-1.stderr +++ b/src/test/ui/macros/span-covering-argument-1.stderr @@ -11,4 +11,4 @@ LL | bad!(foo whatever); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index 9fb5b17a3114..a9ffef8ef809 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -45,3 +45,5 @@ LL | my_recursive_macro!(); = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro ! ( ) ;` +error: aborting due to 2 previous errors + diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr index 0f775dba536e..a5ef92f14bbc 100644 --- a/src/test/ui/main-wrong-location.stderr +++ b/src/test/ui/main-wrong-location.stderr @@ -1,4 +1,4 @@ -error[E0601]: main function not found +error[E0601]: `main` function not found in crate `main_wrong_location` | = note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior. note: here is a function named 'main' @@ -9,4 +9,4 @@ LL | fn main() { } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0601" +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/method-call-err-msg.stderr b/src/test/ui/method-call-err-msg.stderr index 05d5bde18cf5..3e5bbdfa8f84 100644 --- a/src/test/ui/method-call-err-msg.stderr +++ b/src/test/ui/method-call-err-msg.stderr @@ -43,5 +43,5 @@ LL | .take() //~ ERROR no method named `take` found for type `Foo` in th error: aborting due to 4 previous errors -You've got a few errors: E0061, E0599 -If you want more information on an error, try using "rustc --explain E0061" +Some errors occurred: E0061, E0599. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/method-missing-call.stderr b/src/test/ui/method-missing-call.stderr index a5715d4a7ad9..82d04cb06dd4 100644 --- a/src/test/ui/method-missing-call.stderr +++ b/src/test/ui/method-missing-call.stderr @@ -16,4 +16,4 @@ LL | .filter_map; //~ ERROR attempted to take value of method `fil error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0615" +For more information about this error, try `rustc --explain E0615`. diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr index 8256c9328d90..1b16694bf2c4 100644 --- a/src/test/ui/mismatched_types/E0053.stderr +++ b/src/test/ui/mismatched_types/E0053.stderr @@ -24,4 +24,4 @@ LL | fn bar(&mut self) { } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0053" +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index 93cea816824e..a1bfcafe0539 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -17,5 +17,5 @@ LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 error: aborting due to 2 previous errors -You've got a few errors: E0308, E0409 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr index 4560771f21e8..647e0a215aa5 100644 --- a/src/test/ui/mismatched_types/E0631.stderr +++ b/src/test/ui/mismatched_types/E0631.stderr @@ -58,4 +58,4 @@ LL | fn bar>(_: F) {} error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0631" +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 423b460e31dd..1b2ea514f3e9 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -68,4 +68,4 @@ LL | x //~ ERROR mismatched types error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 75950c0f6d33..9d23b256fd33 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -48,4 +48,4 @@ LL | 6 == Ok(1); //~ ERROR is not satisfied error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index a4e5a897e492..7931e7ff07f4 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -248,5 +248,5 @@ LL | vec![0.0].iter().map(|s| s as f32).collect::>(); //~ ERROR is error: aborting due to 34 previous errors -You've got a few errors: E0054, E0277, E0604, E0605, E0606, E0607, E0609 -If you want more information on an error, try using "rustc --explain E0054" +Some errors occurred: E0054, E0277, E0604, E0605, E0606, E0607, E0609. +For more information about an error, try `rustc --explain E0054`. diff --git a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr index 46cb027c9072..262c4aa1a7c7 100644 --- a/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr @@ -12,4 +12,4 @@ LL | m.iter().map( |(_, b)| { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0593" +For more information about this error, try `rustc --explain E0593`. diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 0370c2596cc4..6451c0d06fa2 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -118,4 +118,4 @@ LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); error: aborting due to 12 previous errors -If you want more information on this error, try using "rustc --explain E0593" +For more information about this error, try `rustc --explain E0593`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index b37779dd0938..62e646c8d394 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -51,5 +51,5 @@ LL | fn baz(_: F) {} error: aborting due to 5 previous errors -You've got a few errors: E0271, E0631 -If you want more information on an error, try using "rustc --explain E0271" +Some errors occurred: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 3950242e27bd..cb03d0ea4cca 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -28,5 +28,5 @@ LL | fn baz(_: T) {} error: aborting due to 2 previous errors -You've got a few errors: E0271, E0631 -If you want more information on an error, try using "rustc --explain E0271" +Some errors occurred: E0271, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr index 453f1d9e6143..ba248e076d4b 100644 --- a/src/test/ui/mismatched_types/const-fn-in-trait.stderr +++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr @@ -12,4 +12,4 @@ LL | const fn f() -> u32 { 22 } //~ ERROR cannot be declared const error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0379" +For more information about this error, try `rustc --explain E0379`. diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index d62026f75204..221ee79bd67e 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -30,4 +30,4 @@ LL | fn apply(t: T, f: F) where F: FnOnce(T) { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0631" +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr index e28e3f12bf74..1fed52883973 100644 --- a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -9,4 +9,4 @@ LL | x //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index c52048919b31..c838c617ae45 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -11,4 +11,4 @@ LL | t as *mut Trait error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index f07cb2f73143..ff047a28adcf 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -20,5 +20,5 @@ LL | cast!(2); error: aborting due to 2 previous errors -You've got a few errors: E0308, E0605 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0605. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr index df573df67d4c..062bda4468a3 100644 --- a/src/test/ui/mismatched_types/issue-35030.stderr +++ b/src/test/ui/mismatched_types/issue-35030.stderr @@ -9,4 +9,4 @@ LL | Some(true) //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index bd1a930baa93..86a92a70287e 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -18,5 +18,5 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); error: aborting due to 2 previous errors -You've got a few errors: E0599, E0631 -If you want more information on an error, try using "rustc --explain E0599" +Some errors occurred: E0599, E0631. +For more information about an error, try `rustc --explain E0599`. diff --git a/src/test/ui/mismatched_types/issue-38371.rs b/src/test/ui/mismatched_types/issue-38371.rs index b9b6b05996b6..8e613d4edba1 100644 --- a/src/test/ui/mismatched_types/issue-38371.rs +++ b/src/test/ui/mismatched_types/issue-38371.rs @@ -7,8 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(slice_patterns)] - struct Foo { } diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index bba216b1e8cc..dd5da7690751 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-38371.rs:16:8 + --> $DIR/issue-38371.rs:14:8 | LL | fn foo(&foo: Foo) { //~ ERROR mismatched types | ^^^^ expected struct `Foo`, found reference @@ -9,7 +9,7 @@ LL | fn foo(&foo: Foo) { //~ ERROR mismatched types = help: did you mean `foo: &Foo`? error[E0308]: mismatched types - --> $DIR/issue-38371.rs:30:9 + --> $DIR/issue-38371.rs:28:9 | LL | fn agh(&&bar: &u32) { //~ ERROR mismatched types | ^^^^ expected u32, found reference @@ -19,7 +19,7 @@ LL | fn agh(&&bar: &u32) { //~ ERROR mismatched types = help: did you mean `bar: &u32`? error[E0308]: mismatched types - --> $DIR/issue-38371.rs:33:8 + --> $DIR/issue-38371.rs:31:8 | LL | fn bgh(&&bar: u32) { //~ ERROR mismatched types | ^^^^^ expected u32, found reference @@ -28,12 +28,12 @@ LL | fn bgh(&&bar: u32) { //~ ERROR mismatched types found type `&_` error[E0529]: expected an array or slice, found `u32` - --> $DIR/issue-38371.rs:36:9 + --> $DIR/issue-38371.rs:34:9 | LL | fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice | ^^^^^ pattern cannot match with input type `u32` error: aborting due to 4 previous errors -You've got a few errors: E0308, E0529 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0529. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr index 7793a38b38eb..ce6f2ee6e052 100644 --- a/src/test/ui/mismatched_types/main.stderr +++ b/src/test/ui/mismatched_types/main.stderr @@ -11,4 +11,4 @@ LL | | ); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index d84b8474ded6..471c15f6d72d 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -9,4 +9,4 @@ LL | a.unwrap(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr index 830eec48d118..d841a340431a 100644 --- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr @@ -21,5 +21,5 @@ LL | let ans = s("burma", "shave"); error: aborting due to 3 previous errors -You've got a few errors: E0057, E0308 -If you want more information on an error, try using "rustc --explain E0057" +Some errors occurred: E0057, E0308. +For more information about an error, try `rustc --explain E0057`. diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr index e922b203adf3..bbe9053430a1 100644 --- a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr +++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr @@ -9,4 +9,4 @@ LL | a(x); //~ ERROR mismatched types [E0308] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 0460ec3194a7..28b16641e4dd 100644 --- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -24,4 +24,4 @@ LL | fn bar(&mut self, bar: &Bar) { } //~ ERROR incompatible type error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0053" +For more information about this error, try `rustc --explain E0053`. diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index cac85e7fbac1..762f0744d80c 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -15,4 +15,4 @@ LL | fn call_itisize>(y: isize, mut f: F) -> isize { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0631" +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/missing-fields-in-struct-pattern.rs b/src/test/ui/missing-fields-in-struct-pattern.rs new file mode 100644 index 000000000000..dfde37994998 --- /dev/null +++ b/src/test/ui/missing-fields-in-struct-pattern.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S(usize, usize, usize, usize); + +fn main() { + if let S { a, b, c, d } = S(1, 2, 3, 4) { + //~^ ERROR struct `S` does not have fields named `a`, `b`, `c`, `d` [E0026] + //~| ERROR pattern does not mention fields `0`, `1`, `2`, `3` [E0027] + println!("hi"); + } +} diff --git a/src/test/ui/missing-fields-in-struct-pattern.stderr b/src/test/ui/missing-fields-in-struct-pattern.stderr new file mode 100644 index 000000000000..d1c3260f11e3 --- /dev/null +++ b/src/test/ui/missing-fields-in-struct-pattern.stderr @@ -0,0 +1,18 @@ +error[E0026]: struct `S` does not have fields named `a`, `b`, `c`, `d` + --> $DIR/missing-fields-in-struct-pattern.rs:14:16 + | +LL | if let S { a, b, c, d } = S(1, 2, 3, 4) { + | ^ ^ ^ ^ struct `S` does not have these fields + +error[E0027]: pattern does not mention fields `0`, `1`, `2`, `3` + --> $DIR/missing-fields-in-struct-pattern.rs:14:12 + | +LL | if let S { a, b, c, d } = S(1, 2, 3, 4) { + | ^^^^^^^^^^^^^^^^ missing fields `0`, `1`, `2`, `3` + | + = note: trying to match a tuple variant with a struct variant pattern + +error: aborting due to 2 previous errors + +Some errors occurred: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/missing-items/issue-40221.stderr b/src/test/ui/missing-items/issue-40221.stderr index cb30805ce2f1..81c9f40f6cfb 100644 --- a/src/test/ui/missing-items/issue-40221.stderr +++ b/src/test/ui/missing-items/issue-40221.stderr @@ -6,4 +6,4 @@ LL | match proto { //~ ERROR non-exhaustive patterns error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0004" +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/missing-items/m2.rs b/src/test/ui/missing-items/m2.rs index 9f1954526916..f655047f6f5a 100644 --- a/src/test/ui/missing-items/m2.rs +++ b/src/test/ui/missing-items/m2.rs @@ -18,3 +18,5 @@ struct X { impl m1::X for X { //~ ERROR not all trait items implemented } + +fn main() {} diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr index aebe25ab4926..3f7a4039eb76 100644 --- a/src/test/ui/missing-items/m2.stderr +++ b/src/test/ui/missing-items/m2.stderr @@ -1,5 +1,3 @@ -error[E0601]: main function not found - error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method` --> $DIR/m2.rs:19:1 | @@ -10,7 +8,6 @@ LL | impl m1::X for X { //~ ERROR not all trait items implemented = note: `Type` from trait: `type Type;` = note: `method` from trait: `fn(&Self, std::string::String) -> ::Type` -error: aborting due to 2 previous errors +error: aborting due to previous error -You've got a few errors: E0046, E0601 -If you want more information on an error, try using "rustc --explain E0046" +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr index c2798af66f21..a27e8aac28f2 100644 --- a/src/test/ui/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing-items/missing-type-parameter.stderr @@ -6,4 +6,4 @@ LL | foo(); //~ ERROR type annotations needed error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index 1df422730ecf..f494af0ff3ec 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -8,4 +8,4 @@ LL | mod missing; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0583" +For more information about this error, try `rustc --explain E0583`. diff --git a/src/test/ui/moves-based-on-type-block-bad.stderr b/src/test/ui/moves-based-on-type-block-bad.stderr index fd83309274d8..f1b882924109 100644 --- a/src/test/ui/moves-based-on-type-block-bad.stderr +++ b/src/test/ui/moves-based-on-type-block-bad.stderr @@ -9,4 +9,4 @@ LL | box E::Bar(x) => println!("{}", x.to_string()), error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0507" +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/moves-based-on-type-match-bindings.stderr b/src/test/ui/moves-based-on-type-match-bindings.stderr index 1c33004d8f69..62e16df583f8 100644 --- a/src/test/ui/moves-based-on-type-match-bindings.stderr +++ b/src/test/ui/moves-based-on-type-match-bindings.stderr @@ -11,4 +11,4 @@ LL | touch(&x); //~ ERROR use of partially moved value: `x` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves-based-on-type-tuple.stderr b/src/test/ui/moves-based-on-type-tuple.stderr index a614b33c63e9..b0a3b6bf1fd6 100644 --- a/src/test/ui/moves-based-on-type-tuple.stderr +++ b/src/test/ui/moves-based-on-type-tuple.stderr @@ -20,4 +20,4 @@ LL | box (x, x) error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0382" +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nested_impl_trait.rs b/src/test/ui/nested_impl_trait.rs index f6302c0f3b3e..be0454472dd0 100644 --- a/src/test/ui/nested_impl_trait.rs +++ b/src/test/ui/nested_impl_trait.rs @@ -7,8 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, universal_impl_trait)] - use std::fmt::Debug; fn fine(x: impl Into) -> impl Into { x } diff --git a/src/test/ui/nested_impl_trait.stderr b/src/test/ui/nested_impl_trait.stderr index b3e61e74bbb7..ee53194e2b48 100644 --- a/src/test/ui/nested_impl_trait.stderr +++ b/src/test/ui/nested_impl_trait.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:16:56 + --> $DIR/nested_impl_trait.rs:14:56 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:19:42 + --> $DIR/nested_impl_trait.rs:17:42 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ----------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:23:37 + --> $DIR/nested_impl_trait.rs:21:37 | LL | fn bad_in_arg_position(_: impl Into) { } | ----------^^^^^^^^^^- @@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into) { } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/nested_impl_trait.rs:28:44 + --> $DIR/nested_impl_trait.rs:26:44 | LL | fn bad(x: impl Into) -> impl Into { x } | ----------^^^^^^^^^^- @@ -35,18 +35,18 @@ LL | fn bad(x: impl Into) -> impl Into { x } | outer `impl Trait` error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/nested_impl_trait.rs:19:32 + --> $DIR/nested_impl_trait.rs:17:32 | LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} | ^^^^^^^^^^^^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/nested_impl_trait.rs:36:42 + --> $DIR/nested_impl_trait.rs:34:42 | LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into { | ^^^^^^^^^^^^^^ error: aborting due to 6 previous errors -You've got a few errors: E0562, E0666 -If you want more information on an error, try using "rustc --explain E0562" +Some errors occurred: E0562, E0666. +For more information about an error, try `rustc --explain E0562`. diff --git a/src/test/ui/nll/borrowed-local-error.stderr b/src/test/ui/nll/borrowed-local-error.stderr index 24964f651f79..901b1ca271a5 100644 --- a/src/test/ui/nll/borrowed-local-error.stderr +++ b/src/test/ui/nll/borrowed-local-error.stderr @@ -14,4 +14,4 @@ LL | | }); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/borrowed-match-issue-45045.stderr b/src/test/ui/nll/borrowed-match-issue-45045.stderr index a80bc686e34a..7904e6015799 100644 --- a/src/test/ui/nll/borrowed-match-issue-45045.stderr +++ b/src/test/ui/nll/borrowed-match-issue-45045.stderr @@ -27,4 +27,4 @@ LL | *g = Xyz::B; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0503" +For more information about this error, try `rustc --explain E0503`. diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.stderr b/src/test/ui/nll/borrowed-referent-issue-38899.stderr index 675f85ecb4dd..5c5a66e7e21d 100644 --- a/src/test/ui/nll/borrowed-referent-issue-38899.stderr +++ b/src/test/ui/nll/borrowed-referent-issue-38899.stderr @@ -12,4 +12,4 @@ LL | drop(x); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0502" +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/nll/borrowed-temporary-error.stderr b/src/test/ui/nll/borrowed-temporary-error.stderr index 575d9b5a62d7..37746a173eb7 100644 --- a/src/test/ui/nll/borrowed-temporary-error.stderr +++ b/src/test/ui/nll/borrowed-temporary-error.stderr @@ -11,4 +11,4 @@ LL | println!("{:?}", x); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/borrowed-universal-error-2.stderr b/src/test/ui/nll/borrowed-universal-error-2.stderr index 2e4d7cc8f818..467b02d207dd 100644 --- a/src/test/ui/nll/borrowed-universal-error-2.stderr +++ b/src/test/ui/nll/borrowed-universal-error-2.stderr @@ -15,4 +15,4 @@ LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/borrowed-universal-error.stderr b/src/test/ui/nll/borrowed-universal-error.stderr index 3e9a3ceb1dba..94d9bb36fa42 100644 --- a/src/test/ui/nll/borrowed-universal-error.stderr +++ b/src/test/ui/nll/borrowed-universal-error.stderr @@ -15,4 +15,4 @@ LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr index 0fb718075849..81946de612af 100644 --- a/src/test/ui/nll/capture-ref-in-struct.stderr +++ b/src/test/ui/nll/capture-ref-in-struct.stderr @@ -12,4 +12,4 @@ LL | deref(p); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index 18ffdc583497..a9a52aba8421 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -37,4 +37,4 @@ LL | deref(p); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index 7b2b2f748726..a7fb9d90a218 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -64,4 +64,4 @@ LL | deref(p); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index 0a45603a42cd..fd6b7a2e68d3 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -41,4 +41,4 @@ LL | deref(p); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 798f222c136e..947b95b1c532 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -49,4 +49,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 86653138a185..d39cdc34471a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -83,4 +83,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr deleted file mode 100644 index 502b344c89e4..000000000000 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-to-empty.stderr +++ /dev/null @@ -1,45 +0,0 @@ -warning: not reporting region error due to -Znll - --> $DIR/propagate-approximated-to-empty.rs:41:9 - | -41 | demand_y(x, y, x.get()) - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: free region `'_#6r` does not outlive free region `'_#4r` - --> $DIR/propagate-approximated-to-empty.rs:41:18 - | -41 | demand_y(x, y, x.get()) - | ^ - -note: No external requirements - --> $DIR/propagate-approximated-to-empty.rs:39:47 - | -39 | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | _______________________________________________^ -40 | | // Only works if 'x: 'y: -41 | | demand_y(x, y, x.get()) -42 | | //~^ WARN not reporting region error due to -Znll -43 | | //~| ERROR free region `'_#6r` does not outlive free region `'_#4r` -44 | | }); - | |_____^ - | - = note: defining type: DefId(0/1:18 ~ propagate_approximated_to_empty[317d]::supply[0]::{{closure}}[0]) with closure substs [ - i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>)) - ] - -note: No external requirements - --> $DIR/propagate-approximated-to-empty.rs:38:1 - | -38 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { -39 | | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { -40 | | // Only works if 'x: 'y: -41 | | demand_y(x, y, x.get()) -... | -44 | | }); -45 | | } - | |_^ - | - = note: defining type: DefId(0/0:6 ~ propagate_approximated_to_empty[317d]::supply[0]) with substs [] - -error: aborting due to previous error - diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 6eb0926b1c83..475fdd947817 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -49,4 +49,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index dfe4e5f844e1..5bdfc7e935fe 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -60,4 +60,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr index a162d754defa..1e93ae1ee07c 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -14,4 +14,4 @@ LL | &*x error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr index f8bf188e789e..3af6d7d21f75 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr @@ -16,4 +16,4 @@ LL | &*x error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0623" +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/nll/decl-macro-illegal-copy.rs b/src/test/ui/nll/decl-macro-illegal-copy.rs new file mode 100644 index 000000000000..1525791c8811 --- /dev/null +++ b/src/test/ui/nll/decl-macro-illegal-copy.rs @@ -0,0 +1,39 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #46314 + +#![feature(nll)] +#![feature(decl_macro)] + +struct NonCopy(String); + +struct Wrapper { + inner: NonCopy, +} + +macro inner_copy($wrapper:ident) { + $wrapper.inner +} + +fn main() { + let wrapper = Wrapper { + inner: NonCopy("foo".into()), + }; + assert_two_non_copy( + inner_copy!(wrapper), + wrapper.inner, + //~^ ERROR use of moved value: `wrapper.inner` [E0382] + ); +} + +fn assert_two_non_copy(a: NonCopy, b: NonCopy) { + assert_eq!(a.0, b.0); +} diff --git a/src/test/ui/nll/decl-macro-illegal-copy.stderr b/src/test/ui/nll/decl-macro-illegal-copy.stderr new file mode 100644 index 000000000000..8bc25c23e017 --- /dev/null +++ b/src/test/ui/nll/decl-macro-illegal-copy.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `wrapper.inner` + --> $DIR/decl-macro-illegal-copy.rs:32:9 + | +LL | $wrapper.inner + | -------------- value moved here +... +LL | wrapper.inner, + | ^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `wrapper.inner` has type `NonCopy`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/drop-may-dangle.rs b/src/test/ui/nll/drop-may-dangle.rs index 2780b3474637..55c9f5de3020 100644 --- a/src/test/ui/nll/drop-may-dangle.rs +++ b/src/test/ui/nll/drop-may-dangle.rs @@ -17,7 +17,6 @@ #![allow(warnings)] #![feature(dropck_eyepatch)] -#![feature(generic_param_attrs)] fn use_x(_: usize) -> bool { true } diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index 3d9a5456cbb3..e5478e39fecc 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -17,7 +17,6 @@ #![allow(warnings)] #![feature(dropck_eyepatch)] -#![feature(generic_param_attrs)] fn use_x(_: usize) -> bool { true } diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr index bbb9c0051bc9..a35271bdcfef 100644 --- a/src/test/ui/nll/drop-no-may-dangle.stderr +++ b/src/test/ui/nll/drop-no-may-dangle.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `v[..]` because it is borrowed - --> $DIR/drop-no-may-dangle.rs:31:9 + --> $DIR/drop-no-may-dangle.rs:30:9 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; | ----- borrow of `v[..]` occurs here @@ -11,7 +11,7 @@ LL | } | - borrow later used here, when `p` is dropped error[E0506]: cannot assign to `v[..]` because it is borrowed - --> $DIR/drop-no-may-dangle.rs:34:5 + --> $DIR/drop-no-may-dangle.rs:33:5 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; | ----- borrow of `v[..]` occurs here @@ -23,4 +23,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/get_default.stderr b/src/test/ui/nll/get_default.stderr index 37c9a10cf927..064fd38b8725 100644 --- a/src/test/ui/nll/get_default.stderr +++ b/src/test/ui/nll/get_default.stderr @@ -48,4 +48,4 @@ LL | return v; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0502" +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/nll/guarantor-issue-46974.stderr b/src/test/ui/nll/guarantor-issue-46974.stderr index 82c5e8dafdce..3cb20cc975f4 100644 --- a/src/test/ui/nll/guarantor-issue-46974.stderr +++ b/src/test/ui/nll/guarantor-issue-46974.stderr @@ -20,5 +20,5 @@ LL | &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621] error: aborting due to 2 previous errors -You've got a few errors: E0506, E0621 -If you want more information on an error, try using "rustc --explain E0506" +Some errors occurred: E0506, E0621. +For more information about an error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/issue-31567.rs b/src/test/ui/nll/issue-31567.rs new file mode 100644 index 000000000000..a0d1faf1f0e8 --- /dev/null +++ b/src/test/ui/nll/issue-31567.rs @@ -0,0 +1,37 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #31567: cached results of projections were +// causing region relations not to be enforced at all the places where +// they have to be enforced. + +#![feature(nll)] + +struct VecWrapper<'a>(&'a mut S); + +struct S(Box); + +fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 { + let s_inner: &'a S = &*v.0; //~ ERROR `*v.0` does not live long enough + &s_inner.0 +} + +impl<'a> Drop for VecWrapper<'a> { + fn drop(&mut self) { + *self.0 = S(Box::new(0)); + } +} + +fn main() { + let mut s = S(Box::new(11)); + let vw = VecWrapper(&mut s); + let dangling = get_dangling(vw); + println!("{}", dangling); +} diff --git a/src/test/ui/nll/issue-31567.stderr b/src/test/ui/nll/issue-31567.stderr new file mode 100644 index 000000000000..579dc7eba8c8 --- /dev/null +++ b/src/test/ui/nll/issue-31567.stderr @@ -0,0 +1,18 @@ +error[E0597]: `*v.0` does not live long enough + --> $DIR/issue-31567.rs:22:26 + | +LL | let s_inner: &'a S = &*v.0; //~ ERROR `*v.0` does not live long enough + | ^^^^^ borrowed value does not live long enough +LL | &s_inner.0 +LL | } + | - borrowed value only lives until here + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 21:1... + --> $DIR/issue-31567.rs:21:1 + | +LL | fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-43058.rs b/src/test/ui/nll/issue-43058.rs new file mode 100644 index 000000000000..91ac7e400426 --- /dev/null +++ b/src/test/ui/nll/issue-43058.rs @@ -0,0 +1,38 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// must-compile-successfully + +#![feature(nll)] + +use std::borrow::Cow; + +#[derive(Clone, Debug)] +struct S<'a> { + name: Cow<'a, str> +} + +#[derive(Clone, Debug)] +struct T<'a> { + s: Cow<'a, [S<'a>]> +} + +fn main() { + let s1 = [S { name: Cow::Borrowed("Test1") }, S { name: Cow::Borrowed("Test2") }]; + let b1 = T { s: Cow::Borrowed(&s1) }; + let s2 = [S { name: Cow::Borrowed("Test3") }, S { name: Cow::Borrowed("Test4") }]; + let b2 = T { s: Cow::Borrowed(&s2) }; + + let mut v = Vec::new(); + v.push(b1); + v.push(b2); + + println!("{:?}", v); +} diff --git a/src/test/ui/nll/issue-47470.rs b/src/test/ui/nll/issue-47470.rs new file mode 100644 index 000000000000..c962f193cd5b --- /dev/null +++ b/src/test/ui/nll/issue-47470.rs @@ -0,0 +1,34 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #47470: cached results of projections were +// causing region relations not to be enforced at all the places where +// they have to be enforced. + +#![feature(nll)] + +struct Foo<'a>(&'a ()); +trait Bar { + type Assoc; + fn get(self) -> Self::Assoc; +} + +impl<'a> Bar for Foo<'a> { + type Assoc = &'a u32; + fn get(self) -> Self::Assoc { + let local = 42; + &local //~ ERROR `local` does not live long enough + } +} + +fn main() { + let f = Foo(&()).get(); + println!("{}", f); +} diff --git a/src/test/ui/nll/issue-47470.stderr b/src/test/ui/nll/issue-47470.stderr new file mode 100644 index 000000000000..f84a68d85b95 --- /dev/null +++ b/src/test/ui/nll/issue-47470.stderr @@ -0,0 +1,17 @@ +error[E0597]: `local` does not live long enough + --> $DIR/issue-47470.rs:27:9 + | +LL | &local //~ ERROR `local` does not live long enough + | ^^^^^^ borrowed value does not live long enough +LL | } + | - borrowed value only lives until here + | +note: borrowed value must be valid for the lifetime 'a as defined on the impl at 23:1... + --> $DIR/issue-47470.rs:23:1 + | +LL | impl<'a> Bar for Foo<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-48070.rs b/src/test/ui/nll/issue-48070.rs new file mode 100644 index 000000000000..71d92c3702e6 --- /dev/null +++ b/src/test/ui/nll/issue-48070.rs @@ -0,0 +1,35 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-pass +// revisions: lxl nll + +#![cfg_attr(nll, feature(nll))] + +struct Foo { + x: u32 +} + +impl Foo { + fn twiddle(&mut self) -> &mut Self { self } + fn twaddle(&mut self) -> &mut Self { self } + fn emit(&mut self) { + self.x += 1; + } +} + +fn main() { + let mut foo = Foo { x: 0 }; + match 22 { + 22 => &mut foo, + 44 => foo.twiddle(), + _ => foo.twaddle(), + }.emit(); +} diff --git a/src/test/ui/nll/issue-48238.rs b/src/test/ui/nll/issue-48238.rs new file mode 100644 index 000000000000..6f7644da3d34 --- /dev/null +++ b/src/test/ui/nll/issue-48238.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for issue #48238 + +#![feature(nll)] + +fn use_val<'a>(val: &'a u8) -> &'a u8 { + val +} + +fn main() { + let orig: u8 = 5; + move || use_val(&orig); //~ ERROR free region `` does not outlive free region `'_#1r` +} diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr new file mode 100644 index 000000000000..29385d9b2430 --- /dev/null +++ b/src/test/ui/nll/issue-48238.stderr @@ -0,0 +1,8 @@ +error: free region `` does not outlive free region `'_#1r` + --> $DIR/issue-48238.rs:21:21 + | +LL | move || use_val(&orig); //~ ERROR free region `` does not outlive free region `'_#1r` + | ^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr index d34b8184e6d8..327454ee60e5 100644 --- a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr +++ b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr @@ -12,4 +12,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr b/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr index ed81aa6006a2..54be12f28954 100644 --- a/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr +++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr index 96eb2afd5b16..ee926e427931 100644 --- a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr +++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr @@ -12,4 +12,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/maybe-initialized-drop.stderr b/src/test/ui/nll/maybe-initialized-drop.stderr index 1e4851d10da5..cc842c29ccb1 100644 --- a/src/test/ui/nll/maybe-initialized-drop.stderr +++ b/src/test/ui/nll/maybe-initialized-drop.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0506" +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.stderr index 2184beac99b6..f40e38c63f5a 100644 --- a/src/test/ui/nll/return-ref-mut-issue-46557.stderr +++ b/src/test/ui/nll/return-ref-mut-issue-46557.stderr @@ -14,4 +14,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index 990b5faf3471..2c3fd091f9a0 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -38,4 +38,4 @@ LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs index 850cd1e7336d..571bd9fd76e8 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -11,7 +11,6 @@ // compile-flags:-Znll -Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(conservative_impl_trait)] trait Foo<'a> { } diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 3b75b8d7027e..92e4f72da3a1 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,11 +1,11 @@ warning: not reporting region error due to -Znll - --> $DIR/impl-trait-captures.rs:22:5 + --> $DIR/impl-trait-captures.rs:21:5 | LL | x | ^ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/impl-trait-captures.rs:22:5 + --> $DIR/impl-trait-captures.rs:21:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | - consider changing the type of `x` to `&ReEarlyBound(0, 'a) T` @@ -14,4 +14,4 @@ LL | x error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0621" +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs index 135805a73394..2e0671f1a51e 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -11,7 +11,6 @@ // compile-flags:-Znll -Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(conservative_impl_trait)] use std::fmt::Debug; diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 33abfb5c3a1f..2b90d53774e6 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -1,17 +1,17 @@ warning: not reporting region error due to -Znll - --> $DIR/impl-trait-outlives.rs:18:35 + --> $DIR/impl-trait-outlives.rs:17:35 | LL | fn no_region<'a, T>(x: Box) -> impl Debug + 'a | ^^^^^^^^^^^^^^^ warning: not reporting region error due to -Znll - --> $DIR/impl-trait-outlives.rs:34:42 + --> $DIR/impl-trait-outlives.rs:33:42 | LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a | ^^^^^^^^^^^^^^^ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:23:5 + --> $DIR/impl-trait-outlives.rs:22:5 | LL | x | ^ @@ -19,7 +19,7 @@ LL | x = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:39:5 + --> $DIR/impl-trait-outlives.rs:38:5 | LL | x | ^ @@ -28,4 +28,4 @@ LL | x error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr index 2ad715e0c5b1..fa53967ed3ac 100644 --- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -14,4 +14,4 @@ LL | twice(value, |value_ref, item| invoke2(value_ref, item)); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0310" +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index a580502f1757..bcdf984f65a8 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -159,4 +159,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr index 05385c16bdc4..95851e7edc70 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr @@ -28,4 +28,4 @@ LL | Box::new(x.next()) error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index f557b448cec3..aa45cf187010 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -198,4 +198,4 @@ LL | | } error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 4fc0dffa6757..c7cbdaec3395 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -330,4 +330,4 @@ LL | | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index ab3c40064596..997cc57cfa28 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -85,4 +85,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 76ccb13e53e0..ba08bc1ff7b4 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -60,4 +60,4 @@ LL | x error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 83d2b959c801..fcdb0b0a4a9f 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -193,4 +193,4 @@ LL | | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr index bdbde6c4ac01..1510ca61e5c7 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr @@ -8,4 +8,4 @@ LL | outlives(cell, t) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr index 21ca9e38103b..34ed709a2730 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -14,4 +14,4 @@ LL | outlives(cell, t) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr index 9fe074a299d0..98ccfc52029f 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr @@ -28,4 +28,4 @@ LL | x error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0309" +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/no-patterns-in-args.stderr b/src/test/ui/no-patterns-in-args.stderr index e0e5ed07ef28..8ac1cced28fb 100644 --- a/src/test/ui/no-patterns-in-args.stderr +++ b/src/test/ui/no-patterns-in-args.stderr @@ -30,5 +30,5 @@ LL | type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function point error: aborting due to 5 previous errors -You've got a few errors: E0130, E0561 -If you want more information on an error, try using "rustc --explain E0130" +Some errors occurred: E0130, E0561. +For more information about an error, try `rustc --explain E0130`. diff --git a/src/test/ui/non-constant-expr-for-arr-len.stderr b/src/test/ui/non-constant-expr-for-arr-len.stderr index 6e9bafa5a4cc..9504c84b10ed 100644 --- a/src/test/ui/non-constant-expr-for-arr-len.stderr +++ b/src/test/ui/non-constant-expr-for-arr-len.stderr @@ -6,4 +6,4 @@ LL | let _x = [0; n]; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0435" +For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/non-exhaustive-pattern-witness.rs b/src/test/ui/non-exhaustive-pattern-witness.rs index 0b12a9acbcb9..dd14a10a2bce 100644 --- a/src/test/ui/non-exhaustive-pattern-witness.rs +++ b/src/test/ui/non-exhaustive-pattern-witness.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] struct Foo { diff --git a/src/test/ui/non-exhaustive-pattern-witness.stderr b/src/test/ui/non-exhaustive-pattern-witness.stderr index 74bf0e256e3b..e364e822ea87 100644 --- a/src/test/ui/non-exhaustive-pattern-witness.stderr +++ b/src/test/ui/non-exhaustive-pattern-witness.stderr @@ -1,45 +1,45 @@ error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:20:11 + --> $DIR/non-exhaustive-pattern-witness.rs:19:11 | LL | match (Foo { first: true, second: None }) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered error[E0004]: non-exhaustive patterns: `Red` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:36:11 + --> $DIR/non-exhaustive-pattern-witness.rs:35:11 | LL | match Color::Red { | ^^^^^^^^^^ pattern `Red` not covered error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:48:11 + --> $DIR/non-exhaustive-pattern-witness.rs:47:11 | LL | match Direction::North { | ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered - --> $DIR/non-exhaustive-pattern-witness.rs:59:11 + --> $DIR/non-exhaustive-pattern-witness.rs:58:11 | LL | match ExcessiveEnum::First { | ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:67:11 + --> $DIR/non-exhaustive-pattern-witness.rs:66:11 | LL | match Color::Red { | ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:83:11 + --> $DIR/non-exhaustive-pattern-witness.rs:82:11 | LL | match *x { | ^^ pattern `[Second(true), Second(false)]` not covered error[E0004]: non-exhaustive patterns: `((), false)` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:96:11 + --> $DIR/non-exhaustive-pattern-witness.rs:95:11 | LL | match ((), false) { | ^^^^^^^^^^^ pattern `((), false)` not covered error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0004" +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/non_modrs_mods/non_modrs_mods.stderr b/src/test/ui/non_modrs_mods/non_modrs_mods.stderr index d4ca6f53feb2..c45ab734fd57 100644 --- a/src/test/ui/non_modrs_mods/non_modrs_mods.stderr +++ b/src/test/ui/non_modrs_mods/non_modrs_mods.stderr @@ -36,4 +36,4 @@ LL | pub mod innest; error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/not-enough-arguments.stderr b/src/test/ui/not-enough-arguments.stderr index a39070cef1f5..6a869cc5d552 100644 --- a/src/test/ui/not-enough-arguments.stderr +++ b/src/test/ui/not-enough-arguments.stderr @@ -9,4 +9,4 @@ LL | foo(1, 2, 3); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/numeric-fields.stderr b/src/test/ui/numeric-fields.stderr index bed94e8f09a9..68a87da8ded3 100644 --- a/src/test/ui/numeric-fields.stderr +++ b/src/test/ui/numeric-fields.stderr @@ -10,9 +10,9 @@ error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:17:17 | LL | S{0: a, 0x1: b, ..} => {} - | ^^^^^^ struct `S` does not have field `0x1` + | ^^^^^^ struct `S` does not have this field error: aborting due to 2 previous errors -You've got a few errors: E0026, E0560 -If you want more information on an error, try using "rustc --explain E0026" +Some errors occurred: E0026, E0560. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/object-safety-associated-consts.stderr b/src/test/ui/object-safety-associated-consts.stderr index 71a2a4992677..39ec5a64e933 100644 --- a/src/test/ui/object-safety-associated-consts.stderr +++ b/src/test/ui/object-safety-associated-consts.stderr @@ -8,4 +8,4 @@ LL | fn make_bar(t: &T) -> &Bar { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety-generics.stderr b/src/test/ui/object-safety-generics.stderr index e10a2c6b1249..e5dfa6666303 100644 --- a/src/test/ui/object-safety-generics.stderr +++ b/src/test/ui/object-safety-generics.stderr @@ -16,4 +16,4 @@ LL | fn make_bar_explicit(t: &T) -> &Bar { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety-mentions-Self.stderr b/src/test/ui/object-safety-mentions-Self.stderr index a1690d60ff28..b181be95a540 100644 --- a/src/test/ui/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety-mentions-Self.stderr @@ -16,4 +16,4 @@ LL | fn make_baz(t: &T) -> &Baz { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety-sized.stderr b/src/test/ui/object-safety-sized.stderr index 994dd943c76e..a6dd16666c68 100644 --- a/src/test/ui/object-safety-sized.stderr +++ b/src/test/ui/object-safety-sized.stderr @@ -8,4 +8,4 @@ LL | fn make_bar(t: &T) -> &Bar { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety-supertrait-mentions-Self.stderr b/src/test/ui/object-safety-supertrait-mentions-Self.stderr index d2ca35ced9d9..f562bc6c54f9 100644 --- a/src/test/ui/object-safety-supertrait-mentions-Self.stderr +++ b/src/test/ui/object-safety-supertrait-mentions-Self.stderr @@ -8,4 +8,4 @@ LL | fn make_baz(t: &T) -> &Baz { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr index ce4dcfb906d3..c37383757384 100644 --- a/src/test/ui/on-unimplemented/bad-annotation.stderr +++ b/src/test/ui/on-unimplemented/bad-annotation.stderr @@ -74,5 +74,5 @@ LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message error: aborting due to 10 previous errors -You've got a few errors: E0230, E0231, E0232 -If you want more information on an error, try using "rustc --explain E0230" +Some errors occurred: E0230, E0231, E0232. +For more information about an error, try `rustc --explain E0230`. diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index ca0723875884..23635a3c415d 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -63,4 +63,4 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr index dfb7b576c5a3..5d8f80e57b07 100644 --- a/src/test/ui/on-unimplemented/no-debug.stderr +++ b/src/test/ui/on-unimplemented/no-debug.stderr @@ -36,4 +36,4 @@ LL | println!("{} {}", Foo, Bar); error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 6f9868d4cdaf..2b286ad0be7f 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -21,4 +21,4 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr index 8708f1461863..8bd910403b47 100644 --- a/src/test/ui/on-unimplemented/on-trait.stderr +++ b/src/test/ui/on-unimplemented/on-trait.stderr @@ -26,4 +26,4 @@ LL | fn foobar>() -> T { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index 5e507b3aa9c5..6a4756eb1c98 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -18,4 +18,4 @@ LL | x[..1i32]; //~ ERROR E0277 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/partialeq_help.stderr b/src/test/ui/partialeq_help.stderr index ff03c7efa509..c813b64d40b5 100644 --- a/src/test/ui/partialeq_help.stderr +++ b/src/test/ui/partialeq_help.stderr @@ -9,4 +9,4 @@ LL | a == b; //~ ERROR E0277 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/pat-slice-old-style.stderr b/src/test/ui/pat-slice-old-style.stderr deleted file mode 100644 index 0fbd9b8e2095..000000000000 --- a/src/test/ui/pat-slice-old-style.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: non-reference pattern used to match a reference (see issue #42640) - --> $DIR/pat-slice-old-style.rs:19:9 - | -LL | [a, b..] => {}, - | ^^^^^^^^ help: consider using a reference: `&[a, b..]` - | - = help: add #![feature(match_default_bindings)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs index 7f234e243e92..875883a2cca7 100644 --- a/src/test/ui/print_type_sizes/niche-filling.rs +++ b/src/test/ui/print_type_sizes/niche-filling.rs @@ -14,7 +14,7 @@ // This file illustrates how niche-filling enums are handled, // modelled after cases like `Option<&u32>`, `Option` and such. // -// It uses NonZero directly, rather than `&_` or `Unique<_>`, because +// It uses NonZeroU32 rather than `&_` or `Unique<_>`, because // the test is not set up to deal with target-dependent pointer width. // // It avoids using u64/i64 because on some targets that is only 4-byte @@ -25,8 +25,7 @@ #![feature(nonzero)] #![allow(dead_code)] -extern crate core; -use core::nonzero::{NonZero, Zeroable}; +use std::num::NonZeroU32; pub enum MyOption { None, Some(T) } @@ -36,7 +35,7 @@ impl Default for MyOption { pub enum EmbeddedDiscr { None, - Record { pre: u8, val: NonZero, post: u16 }, + Record { pre: u8, val: NonZeroU32, post: u16 }, } impl Default for EmbeddedDiscr { @@ -44,32 +43,24 @@ impl Default for EmbeddedDiscr { } #[derive(Default)] -pub struct IndirectNonZero { +pub struct IndirectNonZero { pre: u8, - nested: NestedNonZero, + nested: NestedNonZero, post: u16, } -pub struct NestedNonZero { +pub struct NestedNonZero { pre: u8, - val: NonZero, + val: NonZeroU32, post: u16, } -impl Default for NestedNonZero { +impl Default for NestedNonZero { fn default() -> Self { - NestedNonZero { pre: 0, val: NonZero::new(T::one()).unwrap(), post: 0 } + NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 } } } -pub trait One { - fn one() -> Self; -} - -impl One for u32 { - fn one() -> Self { 1 } -} - pub enum Enum4 { One(A), Two(B), @@ -79,9 +70,9 @@ pub enum Enum4 { #[start] fn start(_: isize, _: *const *const u8) -> isize { - let _x: MyOption> = Default::default(); + let _x: MyOption = Default::default(); let _y: EmbeddedDiscr = Default::default(); - let _z: MyOption> = Default::default(); + let _z: MyOption = Default::default(); let _a: MyOption = Default::default(); let _b: MyOption = Default::default(); let _c: MyOption = Default::default(); diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout index 0f53e7722dd5..79f9ef5a231d 100644 --- a/src/test/ui/print_type_sizes/niche-filling.stdout +++ b/src/test/ui/print_type_sizes/niche-filling.stdout @@ -1,9 +1,9 @@ -print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes +print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes print-type-size field `.nested`: 8 bytes print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes print-type-size end padding: 1 bytes -print-type-size type: `MyOption>`: 12 bytes, alignment: 4 bytes +print-type-size type: `MyOption`: 12 bytes, alignment: 4 bytes print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 12 bytes print-type-size field `.0`: 12 bytes @@ -14,7 +14,7 @@ print-type-size field `.val`: 4 bytes print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes print-type-size end padding: 1 bytes -print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes +print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes print-type-size field `.val`: 4 bytes print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes @@ -32,12 +32,14 @@ print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes -print-type-size type: `MyOption>`: 4 bytes, alignment: 4 bytes +print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes print-type-size variant `None`: 0 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `core::nonzero::NonZero`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes +print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes +print-type-size field `.0`: 4 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes print-type-size variant `One`: 0 bytes print-type-size field `.0`: 0 bytes diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs index 4d0396903e55..7e8eff02c20a 100644 --- a/src/test/ui/print_type_sizes/uninhabited.rs +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -11,7 +11,6 @@ // compile-flags: -Z print-type-sizes // must-compile-successfully -#![feature(never_type)] #![feature(start)] #[start] diff --git a/src/test/ui/qualified-path-params-2.stderr b/src/test/ui/qualified-path-params-2.stderr index 471e6f4fa5db..8b618cbf7ba9 100644 --- a/src/test/ui/qualified-path-params-2.stderr +++ b/src/test/ui/qualified-path-params-2.stderr @@ -14,5 +14,5 @@ LL | type A = ::A::f; error: aborting due to 2 previous errors -You've got a few errors: E0109, E0223 -If you want more information on an error, try using "rustc --explain E0109" +Some errors occurred: E0109, E0223. +For more information about an error, try `rustc --explain E0109`. diff --git a/src/test/ui/range-inclusive-pattern-precedence.rs b/src/test/ui/range-inclusive-pattern-precedence.rs new file mode 100644 index 000000000000..67a0f79ca6b8 --- /dev/null +++ b/src/test/ui/range-inclusive-pattern-precedence.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// In expression, `&a..=b` is treated as `(&a)..=(b)` and `box a..=b` is +// `(box a)..=(b)`. In a pattern, however, `&a..=b` means `&(a..=b)`. This may +// lead to confusion. +// +// We are going to disallow `&a..=b` and `box a..=b` in a pattern. However, the +// older ... syntax is still allowed as a stability guarantee. + +#![feature(box_patterns)] + +pub fn main() { + match &12 { + &0...9 => {} + &10..=15 => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~^^ HELP add parentheses to clarify the precedence + &(16..=20) => {} + _ => {} + } + + match Box::new(12) { + box 0...9 => {} + box 10..=15 => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~^^ HELP add parentheses to clarify the precedence + box (16..=20) => {} + _ => {} + } +} diff --git a/src/test/ui/range-inclusive-pattern-precedence.stderr b/src/test/ui/range-inclusive-pattern-precedence.stderr new file mode 100644 index 000000000000..99e0d739036b --- /dev/null +++ b/src/test/ui/range-inclusive-pattern-precedence.stderr @@ -0,0 +1,14 @@ +error: the range pattern here has ambiguous interpretation + --> $DIR/range-inclusive-pattern-precedence.rs:23:10 + | +LL | &10..=15 => {} + | ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)` + +error: the range pattern here has ambiguous interpretation + --> $DIR/range-inclusive-pattern-precedence.rs:32:13 + | +LL | box 10..=15 => {} + | ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/raw-literal-keywords.rs b/src/test/ui/raw-literal-keywords.rs new file mode 100644 index 000000000000..9b28aa0b1511 --- /dev/null +++ b/src/test/ui/raw-literal-keywords.rs @@ -0,0 +1,26 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +#![feature(dyn_trait)] +#![feature(raw_identifiers)] + +fn test_if() { + r#if true { } //~ ERROR found `true` +} + +fn test_struct() { + r#struct Test; //~ ERROR found `Test` +} + +fn test_union() { + r#union Test; //~ ERROR found `Test` +} diff --git a/src/test/ui/raw-literal-keywords.stderr b/src/test/ui/raw-literal-keywords.stderr new file mode 100644 index 000000000000..3758568323cc --- /dev/null +++ b/src/test/ui/raw-literal-keywords.stderr @@ -0,0 +1,20 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true` + --> $DIR/raw-literal-keywords.rs:17:10 + | +LL | r#if true { } //~ ERROR found `true` + | ^^^^ expected one of 8 possible tokens here + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` + --> $DIR/raw-literal-keywords.rs:21:14 + | +LL | r#struct Test; //~ ERROR found `Test` + | ^^^^ expected one of 8 possible tokens here + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` + --> $DIR/raw-literal-keywords.rs:25:13 + | +LL | r#union Test; //~ ERROR found `Test` + | ^^^^ expected one of 8 possible tokens here + +error: aborting due to 3 previous errors + diff --git a/src/test/run-pass/diverging-fn-tail-35849.rs b/src/test/ui/raw-literal-self.rs similarity index 66% rename from src/test/run-pass/diverging-fn-tail-35849.rs rename to src/test/ui/raw-literal-self.rs index dfd99bcc9fb4..f88d6cf9a67b 100644 --- a/src/test/run-pass/diverging-fn-tail-35849.rs +++ b/src/test/ui/raw-literal-self.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[allow(coerce_never)] -fn assert_sizeof() -> ! { - unsafe { - ::std::mem::transmute::(panic!()) - } -} +// compile-flags: -Z parse-only -fn main() { } +#![feature(raw_identifiers)] + +fn self_test(r#self: u32) { + //~^ ERROR `r#self` is not currently supported. +} diff --git a/src/test/ui/raw-literal-self.stderr b/src/test/ui/raw-literal-self.stderr new file mode 100644 index 000000000000..e3345847aa89 --- /dev/null +++ b/src/test/ui/raw-literal-self.stderr @@ -0,0 +1,8 @@ +error: `r#self` is not currently supported. + --> $DIR/raw-literal-self.rs:15:14 + | +LL | fn self_test(r#self: u32) { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/raw-literal-underscore.rs b/src/test/ui/raw-literal-underscore.rs new file mode 100644 index 000000000000..ec33e4861958 --- /dev/null +++ b/src/test/ui/raw-literal-underscore.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn underscore_test(r#_: u32) { + //~^ ERROR `r#_` is not currently supported. +} diff --git a/src/test/ui/raw-literal-underscore.stderr b/src/test/ui/raw-literal-underscore.stderr new file mode 100644 index 000000000000..8072eee4f060 --- /dev/null +++ b/src/test/ui/raw-literal-underscore.stderr @@ -0,0 +1,8 @@ +error: `r#_` is not currently supported. + --> $DIR/raw-literal-underscore.rs:13:20 + | +LL | fn underscore_test(r#_: u32) { + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/raw_string.stderr b/src/test/ui/raw_string.stderr index b8aa596ef953..ddf1cfe406f7 100644 --- a/src/test/ui/raw_string.stderr +++ b/src/test/ui/raw_string.stderr @@ -6,3 +6,5 @@ LL | let x = r##"lol"#; | = note: this raw string should be terminated with `"##` +error: aborting due to previous error + diff --git a/src/test/ui/reachable/expr_add.rs b/src/test/ui/reachable/expr_add.rs index dd43c58de6df..3e39b75d8c0f 100644 --- a/src/test/ui/reachable/expr_add.rs +++ b/src/test/ui/reachable/expr_add.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(never_type)] #![allow(unused_variables)] #![deny(unreachable_code)] diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr index d3e1da0e7189..f49a781ce336 100644 --- a/src/test/ui/reachable/expr_add.stderr +++ b/src/test/ui/reachable/expr_add.stderr @@ -1,11 +1,11 @@ error: unreachable expression - --> $DIR/expr_add.rs:27:13 + --> $DIR/expr_add.rs:26:13 | LL | let x = Foo + return; //~ ERROR unreachable | ^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/expr_add.rs:13:9 + --> $DIR/expr_add.rs:12:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_array.rs b/src/test/ui/reachable/expr_array.rs index 31229668796e..323a5752e220 100644 --- a/src/test/ui/reachable/expr_array.rs +++ b/src/test/ui/reachable/expr_array.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] fn a() { @@ -21,7 +20,7 @@ fn a() { } fn b() { - // the `array is unreachable: + // the array is unreachable: let x: [usize; 2] = [22, return]; //~ ERROR unreachable } diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr index 3257514ea500..78ac76a6137f 100644 --- a/src/test/ui/reachable/expr_array.stderr +++ b/src/test/ui/reachable/expr_array.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_array.rs:20:34 + --> $DIR/expr_array.rs:19:34 | LL | let x: [usize; 2] = [return, 22]; //~ ERROR unreachable | ^^ @@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_array.rs:25:25 + --> $DIR/expr_array.rs:24:25 | LL | let x: [usize; 2] = [22, return]; //~ ERROR unreachable | ^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_assign.rs b/src/test/ui/reachable/expr_assign.rs index e6fb46a5bac0..73083af34d97 100644 --- a/src/test/ui/reachable/expr_assign.rs +++ b/src/test/ui/reachable/expr_assign.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn foo() { // No error here. diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr index 15dcf2c2401d..628bfbf62171 100644 --- a/src/test/ui/reachable/expr_assign.stderr +++ b/src/test/ui/reachable/expr_assign.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_assign.rs:20:5 + --> $DIR/expr_assign.rs:19:5 | LL | x = return; //~ ERROR unreachable | ^^^^^^^^^^ @@ -11,13 +11,13 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_assign.rs:30:14 + --> $DIR/expr_assign.rs:29:14 | LL | *p = return; //~ ERROR unreachable | ^^^^^^ error: unreachable expression - --> $DIR/expr_assign.rs:36:15 + --> $DIR/expr_assign.rs:35:15 | LL | *{return; &mut i} = 22; //~ ERROR unreachable | ^^^^^^ diff --git a/src/test/ui/reachable/expr_block.rs b/src/test/ui/reachable/expr_block.rs index 57b5d3cabce6..93bce43f76d9 100644 --- a/src/test/ui/reachable/expr_block.rs +++ b/src/test/ui/reachable/expr_block.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn a() { // Here the tail expression is considered unreachable: diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index a0cef6449f7d..5f5696aadb37 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_block.rs:21:9 + --> $DIR/expr_block.rs:20:9 | LL | 22 //~ ERROR unreachable | ^^ @@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable statement - --> $DIR/expr_block.rs:36:9 + --> $DIR/expr_block.rs:35:9 | LL | println!("foo"); | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_call.rs b/src/test/ui/reachable/expr_call.rs index 86b95aad9c25..2772dd429d18 100644 --- a/src/test/ui/reachable/expr_call.rs +++ b/src/test/ui/reachable/expr_call.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn foo(x: !, y: usize) { } diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index 455e5ab3653d..414d29ec2a73 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_call.rs:23:17 + --> $DIR/expr_call.rs:22:17 | LL | foo(return, 22); //~ ERROR unreachable | ^^ @@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_call.rs:28:5 + --> $DIR/expr_call.rs:27:5 | LL | bar(return); //~ ERROR unreachable | ^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_cast.rs b/src/test/ui/reachable/expr_cast.rs index 76b00c00ad98..88846b638416 100644 --- a/src/test/ui/reachable/expr_cast.rs +++ b/src/test/ui/reachable/expr_cast.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] fn a() { diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index 8c37759aa469..458334e2af96 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_cast.rs:20:13 + --> $DIR/expr_cast.rs:19:13 | LL | let x = {return} as !; //~ ERROR unreachable | ^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_if.rs b/src/test/ui/reachable/expr_if.rs index 2a265e772f35..d2fb1044e48b 100644 --- a/src/test/ui/reachable/expr_if.rs +++ b/src/test/ui/reachable/expr_if.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn foo() { if {return} { diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index c14cdbfc2bc7..6e8afd1c5be8 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/expr_if.rs:38:5 + --> $DIR/expr_if.rs:37:5 | LL | println!("But I am."); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_loop.rs b/src/test/ui/reachable/expr_loop.rs index 3ed4b2dcf0cf..533cdac0968b 100644 --- a/src/test/ui/reachable/expr_loop.rs +++ b/src/test/ui/reachable/expr_loop.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn a() { loop { return; } diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index 7f834567de36..a51ef293acf1 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/expr_loop.rs:19:5 + --> $DIR/expr_loop.rs:18:5 | LL | println!("I am dead."); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(unreachable_code)] = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement - --> $DIR/expr_loop.rs:31:5 + --> $DIR/expr_loop.rs:30:5 | LL | println!("I am dead."); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | println!("I am dead."); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement - --> $DIR/expr_loop.rs:41:5 + --> $DIR/expr_loop.rs:40:5 | LL | println!("I am dead."); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_match.rs b/src/test/ui/reachable/expr_match.rs index d2b96e51a951..193edd774357 100644 --- a/src/test/ui/reachable/expr_match.rs +++ b/src/test/ui/reachable/expr_match.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn a() { // The match is considered unreachable here, because the `return` diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index d4cf21cef281..dfc1417f3d29 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_match.rs:20:5 + --> $DIR/expr_match.rs:19:5 | LL | match {return} { } //~ ERROR unreachable | ^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable statement - --> $DIR/expr_match.rs:25:5 + --> $DIR/expr_match.rs:24:5 | LL | println!("I am dead"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | println!("I am dead"); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement - --> $DIR/expr_match.rs:35:5 + --> $DIR/expr_match.rs:34:5 | LL | println!("I am dead"); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_method.rs b/src/test/ui/reachable/expr_method.rs index 8be71e464b20..7dabb3070976 100644 --- a/src/test/ui/reachable/expr_method.rs +++ b/src/test/ui/reachable/expr_method.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] struct Foo; diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index b9348b5d4815..6d67bfcd54a7 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_method.rs:26:21 + --> $DIR/expr_method.rs:25:21 | LL | Foo.foo(return, 22); //~ ERROR unreachable | ^^ @@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_method.rs:31:5 + --> $DIR/expr_method.rs:30:5 | LL | Foo.bar(return); //~ ERROR unreachable | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_repeat.rs b/src/test/ui/reachable/expr_repeat.rs index 47ee2ba62b82..fd9fca413a7f 100644 --- a/src/test/ui/reachable/expr_repeat.rs +++ b/src/test/ui/reachable/expr_repeat.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] fn a() { diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr index 90cc3183c72e..36393de90b7c 100644 --- a/src/test/ui/reachable/expr_repeat.stderr +++ b/src/test/ui/reachable/expr_repeat.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_repeat.rs:20:25 + --> $DIR/expr_repeat.rs:19:25 | LL | let x: [usize; 2] = [return; 2]; //~ ERROR unreachable | ^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_return.rs b/src/test/ui/reachable/expr_return.rs index fac1116dc689..9bbbe6f90998 100644 --- a/src/test/ui/reachable/expr_return.rs +++ b/src/test/ui/reachable/expr_return.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] fn a() { diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr index 3876da6541df..2dcc50944c5d 100644 --- a/src/test/ui/reachable/expr_return.stderr +++ b/src/test/ui/reachable/expr_return.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_return.rs:21:22 + --> $DIR/expr_return.rs:20:22 | LL | let x = {return {return {return;}}}; //~ ERROR unreachable | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_struct.rs b/src/test/ui/reachable/expr_struct.rs index b5acd395be62..66414f6084b8 100644 --- a/src/test/ui/reachable/expr_struct.rs +++ b/src/test/ui/reachable/expr_struct.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] struct Foo { diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr index 43985bbbb5c0..3f0ecb204798 100644 --- a/src/test/ui/reachable/expr_struct.stderr +++ b/src/test/ui/reachable/expr_struct.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_struct.rs:25:13 + --> $DIR/expr_struct.rs:24:13 | LL | let x = Foo { a: 22, b: 33, ..return }; //~ ERROR unreachable | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,19 +11,19 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_struct.rs:30:33 + --> $DIR/expr_struct.rs:29:33 | LL | let x = Foo { a: return, b: 33, ..return }; //~ ERROR unreachable | ^^ error: unreachable expression - --> $DIR/expr_struct.rs:35:39 + --> $DIR/expr_struct.rs:34:39 | LL | let x = Foo { a: 22, b: return, ..return }; //~ ERROR unreachable | ^^^^^^ error: unreachable expression - --> $DIR/expr_struct.rs:40:13 + --> $DIR/expr_struct.rs:39:13 | LL | let x = Foo { a: 22, b: return }; //~ ERROR unreachable | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_tup.rs b/src/test/ui/reachable/expr_tup.rs index 089020bf3853..e2c100902489 100644 --- a/src/test/ui/reachable/expr_tup.rs +++ b/src/test/ui/reachable/expr_tup.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] fn a() { diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr index ff9aa666d8e3..d372373ced0f 100644 --- a/src/test/ui/reachable/expr_tup.stderr +++ b/src/test/ui/reachable/expr_tup.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_tup.rs:20:38 + --> $DIR/expr_tup.rs:19:38 | LL | let x: (usize, usize) = (return, 2); //~ ERROR unreachable | ^ @@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_tup.rs:25:29 + --> $DIR/expr_tup.rs:24:29 | LL | let x: (usize, usize) = (2, return); //~ ERROR unreachable | ^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_type.rs b/src/test/ui/reachable/expr_type.rs index 29c59d5304f9..2381ea2ac7a1 100644 --- a/src/test/ui/reachable/expr_type.rs +++ b/src/test/ui/reachable/expr_type.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] #![feature(type_ascription)] fn a() { diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr index d6b9f75edf10..9b165d6b3ee1 100644 --- a/src/test/ui/reachable/expr_type.stderr +++ b/src/test/ui/reachable/expr_type.stderr @@ -1,5 +1,5 @@ error: unreachable expression - --> $DIR/expr_type.rs:20:13 + --> $DIR/expr_type.rs:19:13 | LL | let x = {return}: !; //~ ERROR unreachable | ^^^^^^^^^^^ diff --git a/src/test/ui/reachable/expr_unary.rs b/src/test/ui/reachable/expr_unary.rs index ad12cb876fe9..4096865f4c67 100644 --- a/src/test/ui/reachable/expr_unary.rs +++ b/src/test/ui/reachable/expr_unary.rs @@ -12,13 +12,9 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![deny(coerce_never)] -#![feature(never_type)] fn foo() { - let x: ! = ! { return; 22 }; //~ ERROR unreachable - //~^ ERROR cannot coerce - //~| hard error + let x: ! = ! { return; }; //~ ERROR unreachable //~| ERROR cannot apply unary operator `!` to type `!` } diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index beb0f5562929..165eccd42396 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -1,8 +1,14 @@ -error: unreachable expression - --> $DIR/expr_unary.rs:19:28 +error[E0600]: cannot apply unary operator `!` to type `!` + --> $DIR/expr_unary.rs:17:16 | -LL | let x: ! = ! { return; 22 }; //~ ERROR unreachable - | ^^ +LL | let x: ! = ! { return; }; //~ ERROR unreachable + | ^^^^^^^^^^^^^ + +error: unreachable expression + --> $DIR/expr_unary.rs:17:16 + | +LL | let x: ! = ! { return; }; //~ ERROR unreachable + | ^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/expr_unary.rs:14:9 @@ -10,26 +16,6 @@ note: lint level defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: cannot coerce `{integer}` to ! - --> $DIR/expr_unary.rs:19:28 - | -LL | let x: ! = ! { return; 22 }; //~ ERROR unreachable - | ^^ - | -note: lint level defined here - --> $DIR/expr_unary.rs:15:9 - | -LL | #![deny(coerce_never)] - | ^^^^^^^^^^^^ - = 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 #46325 +error: aborting due to 2 previous errors -error[E0600]: cannot apply unary operator `!` to type `!` - --> $DIR/expr_unary.rs:19:16 - | -LL | let x: ! = ! { return; 22 }; //~ ERROR unreachable - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -If you want more information on this error, try using "rustc --explain E0600" +For more information about this error, try `rustc --explain E0600`. diff --git a/src/test/ui/reachable/expr_while.rs b/src/test/ui/reachable/expr_while.rs index 7dcd609fbc8f..79fa69a9289b 100644 --- a/src/test/ui/reachable/expr_while.rs +++ b/src/test/ui/reachable/expr_while.rs @@ -12,7 +12,6 @@ #![allow(unused_assignments)] #![allow(dead_code)] #![deny(unreachable_code)] -#![feature(never_type)] fn foo() { while {return} { diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr index cd0939066151..90c35bfaa7ac 100644 --- a/src/test/ui/reachable/expr_while.stderr +++ b/src/test/ui/reachable/expr_while.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/expr_while.rs:19:9 + --> $DIR/expr_while.rs:18:9 | LL | println!("Hello, world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(unreachable_code)] = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement - --> $DIR/expr_while.rs:33:9 + --> $DIR/expr_while.rs:32:9 | LL | println!("I am dead."); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | println!("I am dead."); = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement - --> $DIR/expr_while.rs:35:5 + --> $DIR/expr_while.rs:34:5 | LL | println!("I am, too."); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/recursive-requirements.stderr b/src/test/ui/recursive-requirements.stderr index 2f5945d9fe45..d9e08102ab6a 100644 --- a/src/test/ui/recursive-requirements.stderr +++ b/src/test/ui/recursive-requirements.stderr @@ -12,4 +12,4 @@ LL | let _: AssertSync = unimplemented!(); //~ ERROR E0275 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0275" +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/region-borrow-params-issue-29793-small.stderr b/src/test/ui/region-borrow-params-issue-29793-small.stderr index a342f51e2570..cfe38fe20040 100644 --- a/src/test/ui/region-borrow-params-issue-29793-small.stderr +++ b/src/test/ui/region-borrow-params-issue-29793-small.stderr @@ -244,5 +244,5 @@ LL | let f = move |t: bool| if t { x } else { y }; // (separate erro error: aborting due to 20 previous errors -You've got a few errors: E0373, E0597 -If you want more information on an error, try using "rustc --explain E0373" +Some errors occurred: E0373, E0597. +For more information about an error, try `rustc --explain E0373`. diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 6a7cd6f0236f..bd10dc8a808d 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -9,4 +9,4 @@ LL | want_F(bar); //~ ERROR E0308 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions-nested-fns-2.stderr b/src/test/ui/regions-nested-fns-2.stderr index 16bec5ee218a..c0aa6f9d5420 100644 --- a/src/test/ui/regions-nested-fns-2.stderr +++ b/src/test/ui/regions-nested-fns-2.stderr @@ -13,4 +13,4 @@ LL | move |z| { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0373" +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/resolve-conflict-item-vs-import.stderr b/src/test/ui/resolve-conflict-item-vs-import.stderr index 73e3e9611375..5ef4bdf4aadd 100644 --- a/src/test/ui/resolve-conflict-item-vs-import.stderr +++ b/src/test/ui/resolve-conflict-item-vs-import.stderr @@ -15,4 +15,4 @@ LL | use std::mem::transmute as other_transmute; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0255" +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/resolve-error.stderr b/src/test/ui/resolve-error.stderr deleted file mode 100644 index 27f93939246c..000000000000 --- a/src/test/ui/resolve-error.stderr +++ /dev/null @@ -1,62 +0,0 @@ -error: cannot find derive macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:37:10 - | -37 | #[derive(FooWithLongNan)] - | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` - -error: cannot find attribute macro `attr_proc_macra` in this scope - --> $DIR/resolve-error.rs:40:3 - | -40 | #[attr_proc_macra] - | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` - -error: cannot find attribute macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:43:3 - | -43 | #[FooWithLongNan] - | ^^^^^^^^^^^^^^ - -error: cannot find derive macro `Dlone` in this scope - --> $DIR/resolve-error.rs:46:10 - | -46 | #[derive(Dlone)] - | ^^^^^ help: try: `Clone` - -error: cannot find derive macro `Dlona` in this scope - --> $DIR/resolve-error.rs:49:10 - | -49 | #[derive(Dlona)] - | ^^^^^ help: try: `Clona` - -error: cannot find derive macro `attr_proc_macra` in this scope - --> $DIR/resolve-error.rs:52:10 - | -52 | #[derive(attr_proc_macra)] - | ^^^^^^^^^^^^^^^ - -error: cannot find macro `FooWithLongNama!` in this scope - --> $DIR/resolve-error.rs:56:5 - | -56 | FooWithLongNama!(); - | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` - -error: cannot find macro `attr_proc_macra!` in this scope - --> $DIR/resolve-error.rs:58:5 - | -58 | attr_proc_macra!(); - | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` - -error: cannot find macro `Dlona!` in this scope - --> $DIR/resolve-error.rs:60:5 - | -60 | Dlona!(); - | ^^^^^ - -error: cannot find macro `bang_proc_macrp!` in this scope - --> $DIR/resolve-error.rs:62:5 - | -62 | bang_proc_macrp!(); - | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` - -error: aborting due to previous error(s) - diff --git a/src/test/ui/resolve-inconsistent-names.stderr b/src/test/ui/resolve-inconsistent-names.stderr index c136b79de003..17caac210d45 100644 --- a/src/test/ui/resolve-inconsistent-names.stderr +++ b/src/test/ui/resolve-inconsistent-names.stderr @@ -16,4 +16,4 @@ LL | a | b => {} //~ ERROR variable `a` is not bound in all patterns error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0408" +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index df65f5dddedd..4b1750a54dc9 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -30,5 +30,5 @@ LL | use namespaced_enums::Foo::C; error: aborting due to 3 previous errors -You've got a few errors: E0422, E0425 -If you want more information on an error, try using "rustc --explain E0422" +Some errors occurred: E0422, E0425. +For more information about an error, try `rustc --explain E0422`. diff --git a/src/test/ui/resolve/issue-14254.rs b/src/test/ui/resolve/issue-14254.rs index 896085329ab9..eab500de2556 100644 --- a/src/test/ui/resolve/issue-14254.rs +++ b/src/test/ui/resolve/issue-14254.rs @@ -111,3 +111,5 @@ impl Foo for Box { //~^ ERROR cannot find value `bah` } } + +fn main() {} diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr index 226fe36dba3e..055cbb2d5791 100644 --- a/src/test/ui/resolve/issue-14254.stderr +++ b/src/test/ui/resolve/issue-14254.stderr @@ -142,9 +142,6 @@ error[E0425]: cannot find value `bah` in this scope LL | bah; | ^^^ help: try: `Self::bah` -error[E0601]: main function not found +error: aborting due to 24 previous errors -error: aborting due to 25 previous errors - -You've got a few errors: E0425, E0601 -If you want more information on an error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr index 36c62408de78..0ea6da3b27d0 100644 --- a/src/test/ui/resolve/issue-16058.stderr +++ b/src/test/ui/resolve/issue-16058.stderr @@ -14,4 +14,4 @@ LL | use std::thread::Result; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0574" +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr index c5d8f457ec74..177b38aae7bb 100644 --- a/src/test/ui/resolve/issue-17518.stderr +++ b/src/test/ui/resolve/issue-17518.stderr @@ -10,4 +10,4 @@ LL | use SomeEnum::E; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0422" +For more information about this error, try `rustc --explain E0422`. diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr index 4ac907b23ec3..8de552ea0898 100644 --- a/src/test/ui/resolve/issue-18252.stderr +++ b/src/test/ui/resolve/issue-18252.stderr @@ -6,4 +6,4 @@ LL | let f = Foo::Variant(42); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr index 508457558665..0dbd4c85a376 100644 --- a/src/test/ui/resolve/issue-19452.stderr +++ b/src/test/ui/resolve/issue-19452.stderr @@ -12,4 +12,4 @@ LL | let homura = issue_19452_aux::Homura::Madoka; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index 8056a47b464c..3edfa33d80a0 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -45,7 +45,7 @@ help: possible candidate is found in another module, you can import it into scop LL | use std::ops::Div; | -error: cannot continue compilation due to previous error +error: aborting due to 4 previous errors -You've got a few errors: E0405, E0412 -If you want more information on an error, try using "rustc --explain E0405" +Some errors occurred: E0405, E0412. +For more information about an error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-21221-2.rs b/src/test/ui/resolve/issue-21221-2.rs index 4ddb4d669fcd..361e8caf7442 100644 --- a/src/test/ui/resolve/issue-21221-2.rs +++ b/src/test/ui/resolve/issue-21221-2.rs @@ -27,3 +27,5 @@ pub mod baz { struct Foo; impl T for Foo { } //~^ ERROR cannot find trait `T` + +fn main() {} diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr index 398c85920fd2..e11fe9ac4cf1 100644 --- a/src/test/ui/resolve/issue-21221-2.stderr +++ b/src/test/ui/resolve/issue-21221-2.stderr @@ -8,9 +8,6 @@ help: possible candidate is found in another module, you can import it into scop LL | use foo::bar::T; | -error[E0601]: main function not found +error: aborting due to previous error -error: cannot continue compilation due to previous error - -You've got a few errors: E0405, E0601 -If you want more information on an error, try using "rustc --explain E0405" +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr index 75601e932dfa..f406cd6e35fc 100644 --- a/src/test/ui/resolve/issue-21221-3.stderr +++ b/src/test/ui/resolve/issue-21221-3.stderr @@ -8,6 +8,6 @@ help: possible candidate is found in another module, you can import it into scop LL | use issue_21221_3::outer::OuterTrait; | -error: cannot continue compilation due to previous error +error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0405" +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr index 10dcf0aa3b9e..c0a7f1734f49 100644 --- a/src/test/ui/resolve/issue-21221-4.stderr +++ b/src/test/ui/resolve/issue-21221-4.stderr @@ -8,6 +8,6 @@ help: possible candidate is found in another module, you can import it into scop LL | use issue_21221_4::T; | -error: cannot continue compilation due to previous error +error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0405" +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index a9d43aeb7426..63b7ab78b13e 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -13,4 +13,4 @@ LL | impl ToNbt {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0391" +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 6cf5fdeeb0db..3e6c38bce51c 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -108,5 +108,5 @@ LL | self += 1; error: aborting due to 17 previous errors -You've got a few errors: E0424, E0425 -If you want more information on an error, try using "rustc --explain E0424" +Some errors occurred: E0424, E0425. +For more information about an error, try `rustc --explain E0424`. diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr index 8aa84f2ed877..9a1d5ea170e6 100644 --- a/src/test/ui/resolve/issue-24968.stderr +++ b/src/test/ui/resolve/issue-24968.stderr @@ -6,4 +6,4 @@ LL | fn foo(_: Self) { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0411" +For more information about this error, try `rustc --explain E0411`. diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr index 2742d4af7121..631a9f6f7242 100644 --- a/src/test/ui/resolve/issue-33876.stderr +++ b/src/test/ui/resolve/issue-33876.stderr @@ -6,4 +6,4 @@ LL | let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index 7d01cd739e0e..567fd31b09ca 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -8,4 +8,4 @@ LL | fn bar(_x: Foo) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0038" +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr index 80ee2e028ebb..3627c09b28fd 100644 --- a/src/test/ui/resolve/issue-3907.stderr +++ b/src/test/ui/resolve/issue-3907.stderr @@ -8,6 +8,6 @@ help: possible better candidate is found in another module, you can import it in LL | use issue_3907::Foo; | -error: cannot continue compilation due to previous error +error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0404" +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index 4d1e3ae9b107..089fb9fa6609 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -9,4 +9,4 @@ LL | handle: Handle error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr index fedb8b607fcd..92309274e844 100644 --- a/src/test/ui/resolve/issue-5035-2.stderr +++ b/src/test/ui/resolve/issue-5035-2.stderr @@ -9,4 +9,4 @@ LL | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisf error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr index 9b3d69d90c0f..353a0b1c3d9d 100644 --- a/src/test/ui/resolve/issue-5035.stderr +++ b/src/test/ui/resolve/issue-5035.stderr @@ -13,7 +13,7 @@ LL | impl K for isize {} //~ ERROR expected trait, found type alias `K` | did you mean `I`? | type aliases cannot be used for traits -error: cannot continue compilation due to previous error +error: aborting due to 2 previous errors -You've got a few errors: E0404, E0432 -If you want more information on an error, try using "rustc --explain E0404" +Some errors occurred: E0404, E0432. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr index 708ff2e5001a..6f2312afe4f7 100644 --- a/src/test/ui/resolve/issue-6702.stderr +++ b/src/test/ui/resolve/issue-6702.stderr @@ -6,4 +6,4 @@ LL | let _m = Monster(); //~ ERROR expected function, found struct `Monster` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index 1a00395f2de8..bb3caf342bfc 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -48,5 +48,5 @@ LL | let b: m::first = m::second; // Misspelled item in module. error: aborting due to 8 previous errors -You've got a few errors: E0412, E0425 -If you want more information on an error, try using "rustc --explain E0412" +Some errors occurred: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/resolve/name-clash-nullary.stderr b/src/test/ui/resolve/name-clash-nullary.stderr index aefdc9b9fe1c..862ad270502f 100644 --- a/src/test/ui/resolve/name-clash-nullary.stderr +++ b/src/test/ui/resolve/name-clash-nullary.stderr @@ -9,4 +9,4 @@ LL | let None: isize = 42; //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 7af2f5931dc8..d8ab21ddb5f3 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -223,5 +223,5 @@ LL | let _: E = E::Unit; error: aborting due to 23 previous errors -You've got a few errors: E0308, E0412, E0423, E0603, E0618 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0412, E0423, E0603, E0618. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index ddd8f238e872..6ea5241fff00 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -75,5 +75,5 @@ LL | xcrate::m::n::Z; error: aborting due to 10 previous errors -You've got a few errors: E0423, E0603 -If you want more information on an error, try using "rustc --explain E0423" +Some errors occurred: E0423, E0603. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index e03a9052e4b6..916fa9793dc1 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -54,5 +54,5 @@ LL | method; error: aborting due to 9 previous errors -You've got a few errors: E0412, E0425, E0531 -If you want more information on an error, try using "rustc --explain E0412" +Some errors occurred: E0412, E0425, E0531. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 82279b7b2df9..9de6fd85de25 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -6,4 +6,4 @@ LL | assert(true); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr index 0e3eb95f9c4b..217bfb425664 100644 --- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr +++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr @@ -24,4 +24,4 @@ LL | method(); error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs index 981a853a0405..d24fced5d313 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs @@ -65,3 +65,5 @@ fn h8() -> i32 { a::b() //~^ ERROR expected function, found module `a::b` } + +fn main() {} diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index c6058c7af030..9216c0b32192 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -72,9 +72,6 @@ LL | a::b() | | | did you mean `I`? -error[E0601]: main function not found +error: aborting due to 9 previous errors -error: aborting due to 10 previous errors - -You've got a few errors: E0423, E0601 -If you want more information on an error, try using "rustc --explain E0423" +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr index 41d77bf16b97..7abc1ba47810 100644 --- a/src/test/ui/resolve/token-error-correct-2.stderr +++ b/src/test/ui/resolve/token-error-correct-2.stderr @@ -18,4 +18,4 @@ LL | if foo { error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 98989f99dd4f..284acd20ba5e 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -44,5 +44,5 @@ LL | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mis error: aborting due to 5 previous errors -You've got a few errors: E0308, E0425 -If you want more information on an error, try using "rustc --explain E0308" +Some errors occurred: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr index 50d997e01daf..cdac6277bcfa 100644 --- a/src/test/ui/resolve/tuple-struct-alias.stderr +++ b/src/test/ui/resolve/tuple-struct-alias.stderr @@ -32,5 +32,5 @@ LL | A(..) => {} //~ ERROR expected tuple struct/variant error: aborting due to 4 previous errors -You've got a few errors: E0423, E0532 -If you want more information on an error, try using "rustc --explain E0423" +Some errors occurred: E0423, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr index c225563b7549..f32c5e9b2c6b 100644 --- a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr +++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr @@ -10,7 +10,7 @@ error[E0404]: expected trait, found type alias `Typedef` LL | fn g isize>(x: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used for traits -error: cannot continue compilation due to previous error +error: aborting due to 2 previous errors -You've got a few errors: E0404, E0405 -If you want more information on an error, try using "rustc --explain E0404" +Some errors occurred: E0404, E0405. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr index 7012419d94cd..262a4983b81a 100644 --- a/src/test/ui/resolve/unresolved_static_type_field.stderr +++ b/src/test/ui/resolve/unresolved_static_type_field.stderr @@ -9,4 +9,4 @@ LL | f(cx); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr index da2ea67ad08f..caae70900dc0 100644 --- a/src/test/ui/resolve/use_suggestion_placement.stderr +++ b/src/test/ui/resolve/use_suggestion_placement.stderr @@ -32,5 +32,5 @@ LL | use std::collections::hash_map::HashMap; error: aborting due to 3 previous errors -You've got a few errors: E0412, E0425 -If you want more information on an error, try using "rustc --explain E0412" +Some errors occurred: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs similarity index 78% rename from src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs rename to src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs index 93e2561adf75..425f51ca2fb5 100644 --- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs @@ -7,9 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(termination_trait)] -fn main() -> char { -//~^ ERROR: the trait bound `char: std::process::Termination` is not satisfied +fn main() -> char { //~ ERROR ' ' } diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr new file mode 100644 index 000000000000..e53872593843 --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `char` + --> $DIR/termination-trait-main-wrong-type.rs:11:14 + | +LL | fn main() -> char { //~ ERROR + | ^^^^ `main` can only return types that implement `std::process::Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.rs b/src/test/ui/rfc-2005-default-binding-mode/const.rs index fca99f064a27..f80e47507ff0 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/const.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/const.rs @@ -10,8 +10,6 @@ // FIXME(tschottdorf): this test should pass. -#![feature(match_default_bindings)] - #[derive(PartialEq, Eq)] struct Foo { bar: i32, diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.stderr b/src/test/ui/rfc-2005-default-binding-mode/const.stderr index b91e64b42bf6..4849c39a5d09 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/const.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/const.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/const.rs:26:9 + --> $DIR/const.rs:24:9 | LL | FOO => {}, //~ ERROR mismatched types | ^^^ expected &Foo, found struct `Foo` @@ -9,4 +9,4 @@ LL | FOO => {}, //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.rs b/src/test/ui/rfc-2005-default-binding-mode/enum.rs index 76ea64e248ef..a108653f85d2 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - enum Wrapper { Wrap(i32), } diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr index 59c857110a9a..a7f3b507508e 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/enum.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/enum.stderr @@ -1,5 +1,5 @@ error[E0594]: cannot assign to immutable borrowed content `*x` - --> $DIR/enum.rs:21:5 + --> $DIR/enum.rs:19:5 | LL | let Wrap(x) = &Wrap(3); | - consider changing this to `x` @@ -7,7 +7,7 @@ LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*x` - --> $DIR/enum.rs:25:9 + --> $DIR/enum.rs:23:9 | LL | if let Some(x) = &Some(3) { | - consider changing this to `x` @@ -15,7 +15,7 @@ LL | *x += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*x` - --> $DIR/enum.rs:31:9 + --> $DIR/enum.rs:29:9 | LL | while let Some(x) = &Some(3) { | - consider changing this to `x` @@ -24,4 +24,4 @@ LL | *x += 1; //~ ERROR cannot assign to immutable error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0594" +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs index 2e43d9722a90..8001d980174e 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - // Verify the binding mode shifts - only when no `&` are auto-dereferenced is the // final default binding mode mutable. diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr index 72e5c1fce1e6..f2b9bde41ab3 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr @@ -1,5 +1,5 @@ error[E0594]: cannot assign to immutable borrowed content `*n` - --> $DIR/explicit-mut.rs:19:13 + --> $DIR/explicit-mut.rs:17:13 | LL | Some(n) => { | - consider changing this to `n` @@ -7,7 +7,7 @@ LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*n` - --> $DIR/explicit-mut.rs:27:13 + --> $DIR/explicit-mut.rs:25:13 | LL | Some(n) => { | - consider changing this to `n` @@ -15,7 +15,7 @@ LL | *n += 1; //~ ERROR cannot assign to immutable | ^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to immutable borrowed content `*n` - --> $DIR/explicit-mut.rs:35:13 + --> $DIR/explicit-mut.rs:33:13 | LL | Some(n) => { | - consider changing this to `n` @@ -24,4 +24,4 @@ LL | *n += 1; //~ ERROR cannot assign to immutable error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0594" +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.rs b/src/test/ui/rfc-2005-default-binding-mode/for.rs index e9004c13a0e2..a354d2216a9c 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/for.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/for.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - struct Foo {} pub fn main() { diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.stderr b/src/test/ui/rfc-2005-default-binding-mode/for.stderr index cdf6a1667aa4..dbd4bd5dbec4 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/for.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/for.stderr @@ -1,5 +1,5 @@ error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/for.rs:18:13 + --> $DIR/for.rs:16:13 | LL | for (n, mut m) in &tups { | - ^^^^^ by-move pattern here @@ -8,4 +8,4 @@ LL | for (n, mut m) in &tups { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0009" +For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs index 9fbcf5d68b6f..4f4c2a149a7d 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - // FIXME(tschottdorf): This should compile. See #44912. pub fn main() { diff --git a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr index e304ae14065a..04fa3708ffb7 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr @@ -1,9 +1,9 @@ error[E0409]: variable `x` is bound in inconsistent ways within the same match arm - --> $DIR/issue-44912-or.rs:18:35 + --> $DIR/issue-44912-or.rs:16:35 | LL | Some((x, 3)) | &Some((ref x, 5)) => x, | - first binding ^ bound in different ways error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0409" +For more information about this error, try `rustc --explain E0409`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/lit.rs b/src/test/ui/rfc-2005-default-binding-mode/lit.rs index 783287fd458b..209f58453461 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/lit.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/lit.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(match_default_bindings)] - // FIXME(tschottdorf): we want these to compile, but they don't. fn with_str() { diff --git a/src/test/ui/rfc-2005-default-binding-mode/lit.stderr b/src/test/ui/rfc-2005-default-binding-mode/lit.stderr index 1d8f544dbadc..d5c230bc8de5 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/lit.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/lit.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/lit.rs:19:13 + --> $DIR/lit.rs:17:13 | LL | "abc" => true, //~ ERROR mismatched types | ^^^^^ expected &str, found str @@ -8,7 +8,7 @@ LL | "abc" => true, //~ ERROR mismatched types found type `&'static str` error[E0308]: mismatched types - --> $DIR/lit.rs:28:9 + --> $DIR/lit.rs:26:9 | LL | b"abc" => true, //~ ERROR mismatched types | ^^^^^^ expected &[u8], found array of 3 elements @@ -18,4 +18,4 @@ LL | b"abc" => true, //~ ERROR mismatched types error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr index b92f9662613b..e3a613f92611 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr @@ -6,4 +6,4 @@ LL | u32::XXX => { } //~ ERROR no associated item named error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfc-2005-default-binding-mode/slice.rs index 40aa957242cb..fbe4dfe21619 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/slice.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(slice_patterns)] -#![feature(match_default_bindings)] pub fn main() { let sl: &[u8] = b"foo"; diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr index f10d0f83f0c2..18dc6b2869ab 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr @@ -1,9 +1,9 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/slice.rs:17:11 + --> $DIR/slice.rs:16:11 | LL | match sl { //~ ERROR non-exhaustive patterns | ^^ pattern `&[]` not covered error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0004" +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr b/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr deleted file mode 100644 index 1d713be96d7d..000000000000 --- a/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: non-reference pattern used to match a reference (see issue #42640) - --> $DIR/suggestion.rs:12:12 - | -LL | if let Some(y) = &Some(22) { //~ ERROR non-reference pattern - | ^^^^^^^ help: consider using a reference: `&Some(y)` - | - = help: add #![feature(match_default_bindings)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs new file mode 100644 index 000000000000..06651a71d0c0 --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs @@ -0,0 +1,67 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// must-compile-successfully + +#![feature(underscore_imports)] +#![warn(unused_imports, unused_extern_crates)] + +struct S; + +mod m { + pub trait Tr1 { + fn tr1_is_in_scope(&self) {} + } + pub trait Tr2 { + fn tr2_is_in_scope(&self) {} + } + + impl Tr1 for ::S {} + impl Tr2 for ::S {} +} + +mod unused { + use m::Tr1 as _; //~ WARN unused import + use S as _; //~ WARN unused import + extern crate core as _; //~ WARN unused extern crate +} + +mod outer { + mod middle { + pub use m::Tr1 as _; + pub use m::Tr2 as _; // OK, no name conflict + struct Tr1; // OK, no name conflict + fn check() { + // Both traits are in scope + ::S.tr1_is_in_scope(); + ::S.tr2_is_in_scope(); + } + + mod inner { + // `_` imports are fetched by glob imports + use super::*; + fn check() { + // Both traits are in scope + ::S.tr1_is_in_scope(); + ::S.tr2_is_in_scope(); + } + } + } + + // `_` imports are fetched by glob imports + use self::middle::*; + fn check() { + // Both traits are in scope + ::S.tr1_is_in_scope(); + ::S.tr2_is_in_scope(); + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr new file mode 100644 index 000000000000..4530d0fa604a --- /dev/null +++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr @@ -0,0 +1,30 @@ +warning: unused import: `m::Tr1 as _` + --> $DIR/basic.rs:31:9 + | +LL | use m::Tr1 as _; //~ WARN unused import + | ^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/basic.rs:14:9 + | +LL | #![warn(unused_imports, unused_extern_crates)] + | ^^^^^^^^^^^^^^ + +warning: unused import: `S as _` + --> $DIR/basic.rs:32:9 + | +LL | use S as _; //~ WARN unused import + | ^^^^^^ + +warning: unused extern crate + --> $DIR/basic.rs:33:5 + | +LL | extern crate core as _; //~ WARN unused extern crate + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/basic.rs:14:25 + | +LL | #![warn(unused_imports, unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr index 67e50346ace0..054530e24bd1 100644 --- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr @@ -6,4 +6,4 @@ LL | type Quux<'a> = ::Bar<'a, 'static>; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0110" +For more information about this error, try `rustc --explain E0110`. diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr index bb55d86f620b..e69de29bb2d1 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr @@ -1,2 +0,0 @@ -error: cannot continue compilation due to previous error - diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr index bc342119e592..64e82c0d1097 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -30,5 +30,5 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; error: aborting due to 5 previous errors -You've got a few errors: E0110, E0261 -If you want more information on an error, try using "rustc --explain E0110" +Some errors occurred: E0110, E0261. +For more information about an error, try `rustc --explain E0110`. diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr index 0c126236d0eb..d33eebb42d60 100644 --- a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr @@ -18,4 +18,4 @@ LL | fn iter<'a>(&'a self) -> Self::Iter<'a>; error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0110" +For more information about this error, try `rustc --explain E0110`. diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr index 6df4ceed66df..3e772eee4f49 100644 --- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr @@ -24,4 +24,4 @@ LL | fn new(value: T) -> Self::Pointer { error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0109" +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr index df03c15aaa74..9ab80151a7ed 100644 --- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr @@ -18,4 +18,4 @@ LL | fn next<'a>(&'a self) -> Option>; error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0110" +For more information about this error, try `rustc --explain E0110`. diff --git a/src/test/ui/self-impl.stderr b/src/test/ui/self-impl.stderr index e17c2b6e7926..a5a5135faad7 100644 --- a/src/test/ui/self-impl.stderr +++ b/src/test/ui/self-impl.stderr @@ -16,4 +16,4 @@ LL | let _: Self::Baz = true; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0223" +For more information about this error, try `rustc --explain E0223`. diff --git a/src/test/ui/shadowed-lifetime.stderr b/src/test/ui/shadowed-lifetime.stderr index efb9faa0963b..8d7c00bb61e1 100644 --- a/src/test/ui/shadowed-lifetime.stderr +++ b/src/test/ui/shadowed-lifetime.stderr @@ -16,4 +16,4 @@ LL | let x: for<'b> fn(&'b isize) = panic!(); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0496" +For more information about this error, try `rustc --explain E0496`. diff --git a/src/test/ui/shadowed-type-parameter.stderr b/src/test/ui/shadowed-type-parameter.stderr index d13c75b25c36..c40343e31b44 100644 --- a/src/test/ui/shadowed-type-parameter.stderr +++ b/src/test/ui/shadowed-type-parameter.stderr @@ -26,4 +26,4 @@ LL | fn shadow_in_method(&self) {} error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0194" +For more information about this error, try `rustc --explain E0194`. diff --git a/src/test/ui/span/E0046.stderr b/src/test/ui/span/E0046.stderr index 047a9115caf2..035e2e08720c 100644 --- a/src/test/ui/span/E0046.stderr +++ b/src/test/ui/span/E0046.stderr @@ -9,4 +9,4 @@ LL | impl Foo for Bar {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0046" +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr index 0d6cd77de070..fb3e710b8cf9 100644 --- a/src/test/ui/span/E0057.stderr +++ b/src/test/ui/span/E0057.stderr @@ -12,4 +12,4 @@ LL | let c = f(2, 3); //~ ERROR E0057 error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0057" +For more information about this error, try `rustc --explain E0057`. diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 1c03cfe0e9e0..f8bf41fefa8f 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -11,4 +11,4 @@ LL | tail: Option, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr index aa21c6762e7b..8be1af61d80b 100644 --- a/src/test/ui/span/E0204.stderr +++ b/src/test/ui/span/E0204.stderr @@ -36,4 +36,4 @@ LL | Bar(&'a mut bool), error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0204" +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index 74a85c0164e1..85d83de9d80e 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -6,4 +6,4 @@ LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0493" +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr index 309696eebc48..2191aebbeb21 100644 --- a/src/test/ui/span/E0535.stderr +++ b/src/test/ui/span/E0535.stderr @@ -6,4 +6,4 @@ LL | #[inline(unknown)] //~ ERROR E0535 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0535" +For more information about this error, try `rustc --explain E0535`. diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr index ff8f45438747..2b998356c20b 100644 --- a/src/test/ui/span/E0536.stderr +++ b/src/test/ui/span/E0536.stderr @@ -6,4 +6,4 @@ LL | #[cfg(not())] //~ ERROR E0536 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0536" +For more information about this error, try `rustc --explain E0536`. diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr index 88e74b1cce58..7257c73acb52 100644 --- a/src/test/ui/span/E0537.stderr +++ b/src/test/ui/span/E0537.stderr @@ -6,4 +6,4 @@ LL | #[cfg(unknown())] //~ ERROR E0537 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0537" +For more information about this error, try `rustc --explain E0537`. diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 901a1af94bcd..01c0603256c1 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -84,5 +84,5 @@ LL | *x.y_mut() = 3; //~ ERROR cannot borrow error: aborting due to 10 previous errors -You've got a few errors: E0499, E0596 -If you want more information on an error, try using "rustc --explain E0499" +Some errors occurred: E0499, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 948d6d175dec..3a28ef36d059 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -32,4 +32,4 @@ LL | **x = 3; //~ ERROR cannot borrow error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index 8e03c303e54d..e8227971691e 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -58,7 +58,10 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} - let mut f = |g: Box, b: isize| {}; + let s = String::new(); // Capture to make f !Copy + let mut f = move |g: Box, b: isize| { + let _ = s.len(); + }; f(Box::new(|a| { foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index a06b7097ee37..2e7e1e074414 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -28,7 +28,7 @@ LL | f.f.call_mut(()) | ^^^ cannot borrow as mutable error[E0504]: cannot move `f` into closure because it is borrowed - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 | LL | f(Box::new(|a| { | - borrow of `f` occurs here @@ -36,15 +36,15 @@ LL | foo(f); | ^ move into closure occurs here error[E0507]: cannot move out of captured outer variable in an `FnMut` closure - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 | -LL | let mut f = |g: Box, b: isize| {}; +LL | let mut f = move |g: Box, b: isize| { | ----- captured outer variable -LL | f(Box::new(|a| { +... LL | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure error: aborting due to 5 previous errors -You've got a few errors: E0499, E0504, E0507, E0596 -If you want more information on an error, try using "rustc --explain E0499" +Some errors occurred: E0499, E0504, E0507, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index 8111f80690aa..a18d3c55394d 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -9,4 +9,4 @@ LL | x.h(); //~ ERROR cannot borrow error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 1d4af884b232..4b6c62e6ec83 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -8,4 +8,4 @@ LL | x.push(format!("this is broken")); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index 6de2eecb61b6..dfcd082c0c2c 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -50,4 +50,4 @@ LL | } error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index 2f1a6c631412..5bc07949a951 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -18,4 +18,4 @@ LL | x.borrowed_mut(); //~ ERROR cannot borrow error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr index cf423c278e12..5de3fc4ab0ac 100644 --- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr +++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr @@ -14,4 +14,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index 251f33b63fee..5153d8097882 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -61,4 +61,4 @@ LL | s = format!("foo"); error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr index 15ddfb352405..0ca77a91f2d7 100644 --- a/src/test/ui/span/destructor-restrictions.stderr +++ b/src/test/ui/span/destructor-restrictions.stderr @@ -10,4 +10,4 @@ LL | }; //~^ ERROR `*a` does not live long enough error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr index 2a426ca3a294..7b3855917c9d 100644 --- a/src/test/ui/span/dropck-object-cycle.stderr +++ b/src/test/ui/span/dropck-object-cycle.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr index 5e6512c06bf4..44803b281541 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.stderr +++ b/src/test/ui/span/dropck_arr_cycle_checked.stderr @@ -66,4 +66,4 @@ LL | } error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr index cf507df4e819..d20421c327fc 100644 --- a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr +++ b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr index 42469018e94d..af56448d4061 100644 --- a/src/test/ui/span/dropck_misc_variants.stderr +++ b/src/test/ui/span/dropck_misc_variants.stderr @@ -21,4 +21,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr index f4ab3293543c..63b0ab52d395 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr @@ -66,4 +66,4 @@ LL | } error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr index 87ad9312fa41..179daf83c3c0 100644 --- a/src/test/ui/span/gated-features-attr-spans.stderr +++ b/src/test/ui/span/gated-features-attr-spans.stderr @@ -24,4 +24,4 @@ LL | #[must_use] //~ WARN is experimental error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index ec5cfebedf9d..4f1ac3b94594 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -68,5 +68,5 @@ LL | impl Debug for FooTypeForMethod { error: aborting due to 8 previous errors -You've got a few errors: E0046, E0323, E0324, E0325, E0437 -If you want more information on an error, try using "rustc --explain E0046" +Some errors occurred: E0046, E0323, E0324, E0325, E0437. +For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr index 1185dc6a0cc8..bd66a5bc3929 100644 --- a/src/test/ui/span/issue-11925.stderr +++ b/src/test/ui/span/issue-11925.stderr @@ -12,4 +12,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index c3298a4a0b5c..1d239c712fe9 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -13,4 +13,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr index ec5c7e637f4a..6932134f4cdc 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -20,4 +20,4 @@ LL | }; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr index d80e3352ee4a..83a7671b8f93 100644 --- a/src/test/ui/span/issue-23729.stderr +++ b/src/test/ui/span/issue-23729.stderr @@ -8,4 +8,4 @@ LL | impl Iterator for Recurrence { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0046" +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr index a94debd575c5..c8b55290aa09 100644 --- a/src/test/ui/span/issue-23827.stderr +++ b/src/test/ui/span/issue-23827.stderr @@ -8,4 +8,4 @@ LL | impl FnOnce<(C,)> for Prototype { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0046" +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr index 17a25821fd41..7c599138ef3c 100644 --- a/src/test/ui/span/issue-24356.stderr +++ b/src/test/ui/span/issue-24356.stderr @@ -8,4 +8,4 @@ LL | impl Deref for Thing { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0046" +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 6a4ec73b27a6..b496a1a76c01 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -36,3 +36,5 @@ LL | | println!("{}", theTwo); LL | | } | |_^ +error: aborting due to previous error + diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr index 284c07edf034..13a79035003c 100644 --- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr +++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr index e0e10ff672a4..a2e25492c194 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr @@ -30,4 +30,4 @@ LL | } error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr index 31ad51400a26..1f6c96d4a0c5 100644 --- a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr +++ b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr index fe2df9ce7113..bee83b532baa 100644 --- a/src/test/ui/span/issue-25199.stderr +++ b/src/test/ui/span/issue-25199.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr index e15af193bec5..98f0c90ed781 100644 --- a/src/test/ui/span/issue-26656.stderr +++ b/src/test/ui/span/issue-26656.stderr @@ -10,4 +10,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr index b171fde0f0f7..9b61ecae6512 100644 --- a/src/test/ui/span/issue-27522.stderr +++ b/src/test/ui/span/issue-27522.stderr @@ -4,9 +4,9 @@ error[E0307]: invalid `self` type: &SomeType LL | fn handler(self: &SomeType); //~ ERROR invalid `self` type | ^^^^^^^^^ | - = note: type must be `Self` or a type that dereferences to it` + = note: type must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0307" +For more information about this error, try `rustc --explain E0307`. diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr index 3d7bd2232e43..23e53c9852d5 100644 --- a/src/test/ui/span/issue-29106.stderr +++ b/src/test/ui/span/issue-29106.stderr @@ -20,4 +20,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr index 026d2ba41c7b..15d56abca508 100644 --- a/src/test/ui/span/issue-29595.stderr +++ b/src/test/ui/span/issue-29595.stderr @@ -12,4 +12,4 @@ LL | const C: Self; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index fc79b79877a4..c47d28b45625 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -10,4 +10,4 @@ LL | stream.write_fmt(format!("message received")) error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index bf2de0f11250..bfa81a398a4a 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -45,5 +45,5 @@ LL | bar(1, 2, 3); //~ ERROR this function takes error: aborting due to 6 previous errors -You've got a few errors: E0061, E0308 -If you want more information on an error, try using "rustc --explain E0061" +Some errors occurred: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/span/issue-35987.rs b/src/test/ui/span/issue-35987.rs index fa0410686c26..19e05f33825f 100644 --- a/src/test/ui/span/issue-35987.rs +++ b/src/test/ui/span/issue-35987.rs @@ -20,3 +20,5 @@ impl Add for Foo { unimplemented!(); } } + +fn main() {} diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index 596f2d76da6b..1dd45bb1e5ef 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -8,9 +8,6 @@ help: possible better candidate is found in another module, you can import it in LL | use std::ops::Add; | -error[E0601]: main function not found +error: aborting due to previous error -error: cannot continue compilation due to previous error - -You've got a few errors: E0404, E0601 -If you want more information on an error, try using "rustc --explain E0404" +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr index 69dd330838df..cbec4f6b0a63 100644 --- a/src/test/ui/span/issue-36530.stderr +++ b/src/test/ui/span/issue-36530.stderr @@ -16,4 +16,4 @@ LL | #![foo] //~ ERROR is currently unknown to the compiler error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr index 058e83ba4fdf..73a0cf63c949 100644 --- a/src/test/ui/span/issue-36537.stderr +++ b/src/test/ui/span/issue-36537.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr index ad72a0649710..5477146a5518 100644 --- a/src/test/ui/span/issue-37767.stderr +++ b/src/test/ui/span/issue-37767.stderr @@ -57,4 +57,4 @@ LL | fn foo(self) {} error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0034" +For more information about this error, try `rustc --explain E0034`. diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index d300357fa0b6..ee6334e8164c 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -32,4 +32,4 @@ LL | let x = "Hello " + &"World!".to_owned(); error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/span/issue-39698.stderr b/src/test/ui/span/issue-39698.stderr index 4222d40a12bc..e8dab8dc4650 100644 --- a/src/test/ui/span/issue-39698.stderr +++ b/src/test/ui/span/issue-39698.stderr @@ -40,4 +40,4 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0408" +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr index cc029ae84b6b..8c6d3339e983 100644 --- a/src/test/ui/span/issue-40157.stderr +++ b/src/test/ui/span/issue-40157.stderr @@ -12,4 +12,4 @@ LL | {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 508608bd202a..23315e3b76a4 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -15,4 +15,4 @@ LL | | .sum::<_>() error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 37e8200a308c..dc2cd4c2ddc3 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -67,4 +67,4 @@ LL | fn is_str() -> bool { error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr index adbbd6766154..fb6eeb4de5dd 100644 --- a/src/test/ui/span/issue28498-reject-ex1.stderr +++ b/src/test/ui/span/issue28498-reject-ex1.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr index a701ff6eb3ea..841ea5b25c84 100644 --- a/src/test/ui/span/issue28498-reject-lifetime-param.stderr +++ b/src/test/ui/span/issue28498-reject-lifetime-param.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr index 934863fa4da1..2a5e34290ec9 100644 --- a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr +++ b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr index 4630022e9c49..6e46f67a1d51 100644 --- a/src/test/ui/span/issue28498-reject-trait-bound.stderr +++ b/src/test/ui/span/issue28498-reject-trait-bound.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/loan-extend.stderr b/src/test/ui/span/loan-extend.stderr deleted file mode 100644 index af498129fc44..000000000000 --- a/src/test/ui/span/loan-extend.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0597]: `short` does not live long enough - --> $DIR/loan-extend.rs:21:1 - | -19 | long = borrow(&mut short); - | ----- borrow occurs here -20 | -21 | } - | ^ `short` dropped here while still borrowed - | - = note: values in a scope are dropped in the opposite order they are created - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0597" diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index a7417b006ad4..be514fdd81ce 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -67,4 +67,4 @@ LL | S.generic::<()>(()); //~ ERROR this function takes error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr index 497224b7b534..1c629ee9841c 100644 --- a/src/test/ui/span/move-closure.stderr +++ b/src/test/ui/span/move-closure.stderr @@ -9,4 +9,4 @@ LL | let x: () = move || (); //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index 42ec3764fffa..d087a3aaabff 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -14,4 +14,4 @@ LL | | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index e3bb8349f8a1..463d5baae64e 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -8,4 +8,4 @@ LL | foo(1 as u32 + //~ ERROR cannot add `()` to `u32` error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 73a63aabe674..730592b31002 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -24,4 +24,4 @@ LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed conte error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0596" +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr index 15694106fe8d..7898b066acd4 100644 --- a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr +++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/non-existing-module-import.stderr b/src/test/ui/span/non-existing-module-import.stderr index ed9ae1f21b4d..5518b42ac652 100644 --- a/src/test/ui/span/non-existing-module-import.stderr +++ b/src/test/ui/span/non-existing-module-import.stderr @@ -6,4 +6,4 @@ LL | use std::bar::{foo1, foo2}; //~ ERROR unresolved import error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0432" +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr index 40819e2e8baa..4d2a48aef00a 100644 --- a/src/test/ui/span/pub-struct-field.stderr +++ b/src/test/ui/span/pub-struct-field.stderr @@ -17,4 +17,4 @@ LL | pub(crate) bar: u8, //~ ERROR is already declared error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0124" +For more information about this error, try `rustc --explain E0124`. diff --git a/src/test/ui/span/range-2.stderr b/src/test/ui/span/range-2.stderr index 6378e55f8038..e2ee86ae1f59 100644 --- a/src/test/ui/span/range-2.stderr +++ b/src/test/ui/span/range-2.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr index 7ac63d3ca6ec..74ccb74ac2b5 100644 --- a/src/test/ui/span/recursive-type-field.stderr +++ b/src/test/ui/span/recursive-type-field.stderr @@ -29,4 +29,4 @@ LL | x: Bar<'a>, error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr index c9e8a6d8f56b..db47a9010e09 100644 --- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index 785a47182530..2b63d5bd6c75 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.stderr index 9e8c4000d064..79c6a0be1790 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.stderr @@ -11,4 +11,4 @@ LL | }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/regions-escape-loop-via-variable.stderr b/src/test/ui/span/regions-escape-loop-via-variable.stderr index 1bc8e996d013..0ff0d76a5e46 100644 --- a/src/test/ui/span/regions-escape-loop-via-variable.stderr +++ b/src/test/ui/span/regions-escape-loop-via-variable.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr index 2cb8df235b4b..1d4911bd5af7 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr @@ -37,5 +37,5 @@ LL | x += 1; //~ ERROR cannot assign error: aborting due to 4 previous errors -You've got a few errors: E0503, E0506, E0597 -If you want more information on an error, try using "rustc --explain E0503" +Some errors occurred: E0503, E0506, E0597. +For more information about an error, try `rustc --explain E0503`. diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr index 42240509a9ea..87dc0682199b 100644 --- a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr +++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -12,4 +12,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr index 462c01d849b6..0447b578d44c 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr @@ -26,4 +26,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.stderr index ed6363a2e330..53f4d685d0c2 100644 --- a/src/test/ui/span/send-is-not-static-std-sync-2.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync-2.stderr @@ -34,4 +34,4 @@ LL | } error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr index ffaccf010a9d..066715cd5b5f 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.stderr @@ -57,5 +57,5 @@ LL | drop(y); //~ ERROR cannot move out error: aborting due to 6 previous errors -You've got a few errors: E0505, E0597 -If you want more information on an error, try using "rustc --explain E0505" +Some errors occurred: E0505, E0597. +For more information about an error, try `rustc --explain E0505`. diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 3cc791a05800..503d1f72c354 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -13,4 +13,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index 331d18fad54e..f74d4a5caefc 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -6,4 +6,4 @@ LL | println!("☃{}", tup[0]); //~ ERROR cannot index into a value of type error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0608" +For more information about this error, try `rustc --explain E0608`. diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr index 407897bfcfe6..d8bfdff142b5 100644 --- a/src/test/ui/span/type-binding.stderr +++ b/src/test/ui/span/type-binding.stderr @@ -6,4 +6,4 @@ LL | fn homura>(_: T) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0220" +For more information about this error, try `rustc --explain E0220`. diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr index 010565970130..0ac3a94e7128 100644 --- a/src/test/ui/span/typo-suggestion.stderr +++ b/src/test/ui/span/typo-suggestion.stderr @@ -12,4 +12,4 @@ LL | println!("Hello {}", fob); //~ ERROR cannot find value error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0425" +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr index f9a942906038..b461f74c7599 100644 --- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr +++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr index cdf0cd6de5cb..0dd7288ce64a 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.stderr @@ -22,4 +22,4 @@ LL | } error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/wf-method-late-bound-regions.stderr b/src/test/ui/span/wf-method-late-bound-regions.stderr index 30b1086bbd72..f455707366a5 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.stderr @@ -11,4 +11,4 @@ LL | } error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0597" +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/specialization-feature-gate-default.stderr b/src/test/ui/specialization-feature-gate-default.stderr index 0ce10ec8184d..30548bb24504 100644 --- a/src/test/ui/specialization-feature-gate-default.stderr +++ b/src/test/ui/specialization-feature-gate-default.stderr @@ -8,4 +8,4 @@ LL | default fn foo(&self) {} //~ ERROR specialization is unstable error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0658" +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/specialization-feature-gate-overlap.stderr b/src/test/ui/specialization-feature-gate-overlap.stderr index 00b495dbacd0..bb2d071c93df 100644 --- a/src/test/ui/specialization-feature-gate-overlap.stderr +++ b/src/test/ui/specialization-feature-gate-overlap.stderr @@ -9,4 +9,4 @@ LL | impl Foo for u8 { //~ ERROR E0119 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0119" +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr index abd82cd78ae1..4fe4e569df95 100644 --- a/src/test/ui/static-lifetime.stderr +++ b/src/test/ui/static-lifetime.stderr @@ -13,4 +13,4 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lif error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0478" +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/str-concat-on-double-ref.stderr b/src/test/ui/str-concat-on-double-ref.stderr index 8216455ece4b..d42c859598fd 100644 --- a/src/test/ui/str-concat-on-double-ref.stderr +++ b/src/test/ui/str-concat-on-double-ref.stderr @@ -8,4 +8,4 @@ LL | let c = a + b; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/str-lit-type-mismatch.stderr b/src/test/ui/str-lit-type-mismatch.stderr index 52be4e80393e..de18851636df 100644 --- a/src/test/ui/str-lit-type-mismatch.stderr +++ b/src/test/ui/str-lit-type-mismatch.stderr @@ -36,4 +36,4 @@ LL | let z: &str = b"foo"; //~ ERROR mismatched types error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/struct-fields-decl-dupe.stderr b/src/test/ui/struct-fields-decl-dupe.stderr index 272ce6b1607d..b5068b4abda5 100644 --- a/src/test/ui/struct-fields-decl-dupe.stderr +++ b/src/test/ui/struct-fields-decl-dupe.stderr @@ -8,4 +8,4 @@ LL | foo: isize, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0124" +For more information about this error, try `rustc --explain E0124`. diff --git a/src/test/ui/struct-fields-hints-no-dupe.stderr b/src/test/ui/struct-fields-hints-no-dupe.stderr index 7c276098febd..d04d193c6655 100644 --- a/src/test/ui/struct-fields-hints-no-dupe.stderr +++ b/src/test/ui/struct-fields-hints-no-dupe.stderr @@ -6,4 +6,4 @@ LL | bar : 42, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0560" +For more information about this error, try `rustc --explain E0560`. diff --git a/src/test/ui/struct-fields-hints.stderr b/src/test/ui/struct-fields-hints.stderr index 6e4d30086601..6d0ec8bdf92c 100644 --- a/src/test/ui/struct-fields-hints.stderr +++ b/src/test/ui/struct-fields-hints.stderr @@ -6,4 +6,4 @@ LL | bar : 42, error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0560" +For more information about this error, try `rustc --explain E0560`. diff --git a/src/test/ui/struct-fields-too-many.stderr b/src/test/ui/struct-fields-too-many.stderr index 8132cf687a31..01b3fe16fbb6 100644 --- a/src/test/ui/struct-fields-too-many.stderr +++ b/src/test/ui/struct-fields-too-many.stderr @@ -8,4 +8,4 @@ LL | bar: 0 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0560" +For more information about this error, try `rustc --explain E0560`. diff --git a/src/test/ui/struct-path-self-type-mismatch.stderr b/src/test/ui/struct-path-self-type-mismatch.stderr index a038a7234021..cfba3be61306 100644 --- a/src/test/ui/struct-path-self-type-mismatch.stderr +++ b/src/test/ui/struct-path-self-type-mismatch.stderr @@ -30,4 +30,4 @@ LL | | } error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggest-private-fields.stderr b/src/test/ui/suggest-private-fields.stderr index fb3d8a675699..51a96df951ae 100644 --- a/src/test/ui/suggest-private-fields.stderr +++ b/src/test/ui/suggest-private-fields.stderr @@ -26,4 +26,4 @@ LL | bb: 20, error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0560" +For more information about this error, try `rustc --explain E0560`. diff --git a/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs b/src/test/ui/suggest-remove-refs-1.rs similarity index 75% rename from src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs rename to src/test/ui/suggest-remove-refs-1.rs index 2d5597949198..0f19c48337b1 100644 --- a/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs +++ b/src/test/ui/suggest-remove-refs-1.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] - -fn to_fn_once>(f: F) -> F { f } - fn main() { - let f = to_fn_once(move|| ()); - f(); - f(); //~ ERROR use of moved value + let v = vec![0, 1, 2, 3]; + + for (i, n) in &v.iter().enumerate() { + //~^ ERROR the trait bound + println!("{}", i); + } } diff --git a/src/test/ui/suggest-remove-refs-1.stderr b/src/test/ui/suggest-remove-refs-1.stderr new file mode 100644 index 000000000000..c47b4d283d7c --- /dev/null +++ b/src/test/ui/suggest-remove-refs-1.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&std::iter::Enumerate>: std::iter::Iterator` is not satisfied + --> $DIR/suggest-remove-refs-1.rs:14:19 + | +LL | for (i, n) in &v.iter().enumerate() { + | -^^^^^^^^^^^^^^^^^^^^ + | | + | `&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method + | help: consider removing 1 leading `&`-references + | + = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` + = note: required by `std::iter::IntoIterator::into_iter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggest-remove-refs-2.rs b/src/test/ui/suggest-remove-refs-2.rs new file mode 100644 index 000000000000..c427f697ae1e --- /dev/null +++ b/src/test/ui/suggest-remove-refs-2.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, n) in & & & & &v.iter().enumerate() { + //~^ ERROR the trait bound + println!("{}", i); + } +} diff --git a/src/test/ui/suggest-remove-refs-2.stderr b/src/test/ui/suggest-remove-refs-2.stderr new file mode 100644 index 000000000000..fdd654ea3923 --- /dev/null +++ b/src/test/ui/suggest-remove-refs-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&&&&&std::iter::Enumerate>: std::iter::Iterator` is not satisfied + --> $DIR/suggest-remove-refs-2.rs:14:19 + | +LL | for (i, n) in & & & & &v.iter().enumerate() { + | ---------^^^^^^^^^^^^^^^^^^^^ + | | + | `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method + | help: consider removing 5 leading `&`-references + | + = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate>` + = note: required by `std::iter::IntoIterator::into_iter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggest-remove-refs-3.rs b/src/test/ui/suggest-remove-refs-3.rs new file mode 100644 index 000000000000..f54ae30caebc --- /dev/null +++ b/src/test/ui/suggest-remove-refs-3.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, n) in & & & + & &v + .iter() + .enumerate() { + //~^^^^ ERROR the trait bound + println!("{}", i); + } +} diff --git a/src/test/ui/suggest-remove-refs-3.stderr b/src/test/ui/suggest-remove-refs-3.stderr new file mode 100644 index 000000000000..b0920a0fa523 --- /dev/null +++ b/src/test/ui/suggest-remove-refs-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `&&&&&std::iter::Enumerate>: std::iter::Iterator` is not satisfied + --> $DIR/suggest-remove-refs-3.rs:14:19 + | +LL | for (i, n) in & & & + | ___________________^ + | |___________________| + | || +LL | || & &v + | ||___________- help: consider removing 5 leading `&`-references +LL | | .iter() +LL | | .enumerate() { + | |_____________________^ `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method + | + = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate>` + = note: required by `std::iter::IntoIterator::into_iter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr index a6fda3d7987f..3353e2c72917 100644 --- a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr @@ -8,4 +8,4 @@ LL | foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0594" +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr index 69b2ab0eadd5..b1e3105a5f92 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr @@ -11,4 +11,4 @@ LL | o.closure(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr index 29138441a912..bd5efcd9fee7 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr @@ -121,4 +121,4 @@ LL | (*self.container).f3(1); //~ ERROR no method named `f3` found error: aborting due to 11 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr index e405300b136d..95b764b43ede 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr @@ -11,4 +11,4 @@ LL | demo.example(1); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr index a58ea05221cd..b7f13320eec6 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr @@ -24,4 +24,4 @@ LL | s.c_fn_ptr(); //~ ERROR no method named `c_fn_ptr` found error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr index 3e934ca391a2..145df8b156bf 100644 --- a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr +++ b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr @@ -9,4 +9,4 @@ LL | let dog_age = dog.dog_age(); //~ ERROR no method error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/const-type-mismatch.rs b/src/test/ui/suggestions/const-type-mismatch.rs new file mode 100644 index 000000000000..ddad4e79cfda --- /dev/null +++ b/src/test/ui/suggestions/const-type-mismatch.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// `const`s shouldn't suggest `.into()` + +const TEN: u8 = 10; +const TWELVE: u16 = TEN + 2; +//~^ ERROR mismatched types [E0308] + +fn main() { + const TEN: u8 = 10; + const ALSO_TEN: u16 = TEN; + //~^ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/const-type-mismatch.stderr b/src/test/ui/suggestions/const-type-mismatch.stderr new file mode 100644 index 000000000000..965995f82c53 --- /dev/null +++ b/src/test/ui/suggestions/const-type-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/const-type-mismatch.rs:14:21 + | +LL | const TWELVE: u16 = TEN + 2; + | ^^^^^^^ expected u16, found u8 + +error[E0308]: mismatched types + --> $DIR/const-type-mismatch.rs:19:27 + | +LL | const ALSO_TEN: u16 = TEN; + | ^^^ expected u16, found u8 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/conversion-methods.stderr b/src/test/ui/suggestions/conversion-methods.stderr index b8d1c89ec375..970ccad23169 100644 --- a/src/test/ui/suggestions/conversion-methods.stderr +++ b/src/test/ui/suggestions/conversion-methods.stderr @@ -48,4 +48,4 @@ LL | let _prove_piercing_earnest: Vec = &[1, 2, 3]; //~ ERROR mismatc error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-suggest-dereference-on-arg.rs b/src/test/ui/suggestions/dont-suggest-dereference-on-arg.rs deleted file mode 100644 index 0a2e7ef32260..000000000000 --- a/src/test/ui/suggestions/dont-suggest-dereference-on-arg.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn foo(s: &str) -> bool { true } - -fn main() { - let x = vec![(String::new(), String::new())]; - x.iter() - .filter(|&(ref a, _)| foo(a)) - //~^ ERROR non-reference pattern used to match a reference - .collect(); -} diff --git a/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr b/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr deleted file mode 100644 index 9a9f64b94a76..000000000000 --- a/src/test/ui/suggestions/dont-suggest-dereference-on-arg.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: non-reference pattern used to match a reference (see issue #42640) - --> $DIR/dont-suggest-dereference-on-arg.rs:16:18 - | -LL | .filter(|&(ref a, _)| foo(a)) - | ^^^^^^^^^^^ help: consider using a reference: `&&(ref a, _)` - | - = help: add #![feature(match_default_bindings)] to the crate attributes to enable - -error: aborting due to previous error - -If you want more information on this error, try using "rustc --explain E0658" diff --git a/src/test/ui/suggestions/dont-suggest-private-trait-method.stderr b/src/test/ui/suggestions/dont-suggest-private-trait-method.stderr index 2dfedac8be24..81ecc546a6de 100644 --- a/src/test/ui/suggestions/dont-suggest-private-trait-method.stderr +++ b/src/test/ui/suggestions/dont-suggest-private-trait-method.stderr @@ -9,4 +9,4 @@ LL | T::new(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/extern-crate-rename.stderr b/src/test/ui/suggestions/extern-crate-rename.stderr index aefbbc79ba92..2c2723fe4c5c 100644 --- a/src/test/ui/suggestions/extern-crate-rename.stderr +++ b/src/test/ui/suggestions/extern-crate-rename.stderr @@ -13,4 +13,4 @@ LL | extern crate m2 as m1; //~ ERROR is defined multiple times error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0259" +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.stderr b/src/test/ui/suggestions/fn-closure-mutable-capture.stderr index e46900ba49dc..a58d663dc0ab 100644 --- a/src/test/ui/suggestions/fn-closure-mutable-capture.stderr +++ b/src/test/ui/suggestions/fn-closure-mutable-capture.stderr @@ -13,4 +13,4 @@ LL | bar(move || x = 1); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0594" +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/for-c-in-str.stderr b/src/test/ui/suggestions/for-c-in-str.stderr index f3130d0587c4..b249df3b4ef6 100644 --- a/src/test/ui/suggestions/for-c-in-str.stderr +++ b/src/test/ui/suggestions/for-c-in-str.stderr @@ -9,4 +9,4 @@ LL | for c in "asdf" { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr b/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr index c9babb6a6d91..7cf7a1d15a27 100644 --- a/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr +++ b/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr @@ -14,4 +14,4 @@ LL | use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERRO error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0252" +For more information about this error, try `rustc --explain E0252`. diff --git a/src/test/ui/suggestions/issue-43420-no-over-suggest.stderr b/src/test/ui/suggestions/issue-43420-no-over-suggest.stderr index 387b9cfcf32c..80bbdd11289a 100644 --- a/src/test/ui/suggestions/issue-43420-no-over-suggest.stderr +++ b/src/test/ui/suggestions/issue-43420-no-over-suggest.stderr @@ -9,4 +9,4 @@ LL | foo(&a); //~ ERROR mismatched types error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr index 22c82be100c9..8e2b2d845e9b 100644 --- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr +++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr @@ -12,4 +12,4 @@ LL | extern crate std as other_std; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0259" +For more information about this error, try `rustc --explain E0259`. diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr index 4d75ee0284c3..e89e9dce94dc 100644 --- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr +++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr @@ -24,4 +24,4 @@ LL | light_flows_our_war_of_mocking_words(with_tears + 4); error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr index ddd38ca5c3c4..92ad22806156 100644 --- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr +++ b/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr @@ -20,4 +20,4 @@ LL | let y: f32 = 2.0; error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0689" +For more information about this error, try `rustc --explain E0689`. diff --git a/src/test/ui/suggestions/numeric-cast-2.stderr b/src/test/ui/suggestions/numeric-cast-2.stderr index 84f01309bd0a..3d4855837172 100644 --- a/src/test/ui/suggestions/numeric-cast-2.stderr +++ b/src/test/ui/suggestions/numeric-cast-2.stderr @@ -18,4 +18,4 @@ LL | let z: i32 = x + x; error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/numeric-cast.stderr b/src/test/ui/suggestions/numeric-cast.stderr index a19ca7de4b06..4aac65ff4cbd 100644 --- a/src/test/ui/suggestions/numeric-cast.stderr +++ b/src/test/ui/suggestions/numeric-cast.stderr @@ -904,4 +904,4 @@ LL | foo::((-x_i8).into()); error: aborting due to 134 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/return-type.stderr b/src/test/ui/suggestions/return-type.stderr index b09615a2fa69..7d7653eee28f 100644 --- a/src/test/ui/suggestions/return-type.stderr +++ b/src/test/ui/suggestions/return-type.stderr @@ -17,4 +17,4 @@ LL | fn bar() -> S { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/str-array-assignment.stderr b/src/test/ui/suggestions/str-array-assignment.stderr index 352954597b19..76db882742a0 100644 --- a/src/test/ui/suggestions/str-array-assignment.stderr +++ b/src/test/ui/suggestions/str-array-assignment.stderr @@ -44,5 +44,5 @@ LL | let w: &str = s[..2]; error: aborting due to 4 previous errors -You've got a few errors: E0277, E0308 -If you want more information on an error, try using "rustc --explain E0277" +Some errors occurred: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-labels.stderr b/src/test/ui/suggestions/suggest-labels.stderr index 1943e8c65611..671ff1a56db6 100644 --- a/src/test/ui/suggestions/suggest-labels.stderr +++ b/src/test/ui/suggestions/suggest-labels.stderr @@ -18,4 +18,4 @@ LL | break 'longlable; //~ ERROR use of undeclared label error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0426" +For more information about this error, try `rustc --explain E0426`. diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index fbbd6247d566..cb352361f33e 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -33,4 +33,4 @@ LL | let _ = 63u32.count_o(); //~ ERROR no method named error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0599" +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/try-on-option.stderr b/src/test/ui/suggestions/try-on-option.stderr index da7f07a8b162..265ee593bb70 100644 --- a/src/test/ui/suggestions/try-on-option.stderr +++ b/src/test/ui/suggestions/try-on-option.stderr @@ -6,7 +6,7 @@ LL | x?; //~ the trait bound | = note: required by `std::convert::From::from` -error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) --> $DIR/try-on-option.rs:23:5 | LL | x?; //~ the `?` operator @@ -17,4 +17,4 @@ LL | x?; //~ the `?` operator error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/try-operator-on-main.stderr b/src/test/ui/suggestions/try-operator-on-main.stderr index 2fa97d770af8..121ae14f999c 100644 --- a/src/test/ui/suggestions/try-operator-on-main.stderr +++ b/src/test/ui/suggestions/try-operator-on-main.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) --> $DIR/try-operator-on-main.rs:19:5 | LL | std::fs::File::open("foo")?; //~ ERROR the `?` operator can only @@ -39,4 +39,4 @@ LL | ()?; //~ ERROR the `?` operator can only error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr b/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr index 80d1569bf1cd..3722d2a0e3ff 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr @@ -15,4 +15,4 @@ LL | let x: Vec::with_capacity(10, 20); //~ ERROR expected type, found `10` error: aborting due to 2 previous errors -If you want more information on this error, try using "rustc --explain E0061" +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/suggestions/type-ascription-with-fn-call.stderr b/src/test/ui/suggestions/type-ascription-with-fn-call.stderr index 4d36449d26ae..78df97139b6a 100644 --- a/src/test/ui/suggestions/type-ascription-with-fn-call.stderr +++ b/src/test/ui/suggestions/type-ascription-with-fn-call.stderr @@ -11,4 +11,4 @@ LL | f(); //~ ERROR expected type, found function error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0573" +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/svh-change-lit.stderr b/src/test/ui/svh-change-lit.stderr index 588e293b255b..bf018cdf8297 100644 --- a/src/test/ui/svh-change-lit.stderr +++ b/src/test/ui/svh-change-lit.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/svh-change-significant-cfg.stderr b/src/test/ui/svh-change-significant-cfg.stderr index a57a5e7a5dd2..e8926cda9e9f 100644 --- a/src/test/ui/svh-change-significant-cfg.stderr +++ b/src/test/ui/svh-change-significant-cfg.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/svh-change-trait-bound.stderr b/src/test/ui/svh-change-trait-bound.stderr index f0e433ea894f..d9824876a95a 100644 --- a/src/test/ui/svh-change-trait-bound.stderr +++ b/src/test/ui/svh-change-trait-bound.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/svh-change-type-arg.stderr b/src/test/ui/svh-change-type-arg.stderr index bc08c8cf5797..1f942cc19891 100644 --- a/src/test/ui/svh-change-type-arg.stderr +++ b/src/test/ui/svh-change-type-arg.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/svh-change-type-ret.stderr b/src/test/ui/svh-change-type-ret.stderr index 187ebda21ef7..0d59f31ccb66 100644 --- a/src/test/ui/svh-change-type-ret.stderr +++ b/src/test/ui/svh-change-type-ret.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/svh-change-type-static.stderr b/src/test/ui/svh-change-type-static.stderr index c0ca2e94cea7..cbfb74f59ed6 100644 --- a/src/test/ui/svh-change-type-static.stderr +++ b/src/test/ui/svh-change-type-static.stderr @@ -11,4 +11,4 @@ LL | extern crate b; //~ ERROR: found possibly newer version of crate `a` which error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/svh-use-trait.stderr b/src/test/ui/svh-use-trait.stderr index fd57ecf6c3fe..612f52ba9592 100644 --- a/src/test/ui/svh-use-trait.stderr +++ b/src/test/ui/svh-use-trait.stderr @@ -11,4 +11,4 @@ LL | extern crate utb; //~ ERROR: found possibly newer version of crate `uta` wh error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0460" +For more information about this error, try `rustc --explain E0460`. diff --git a/src/test/ui/switched-expectations.stderr b/src/test/ui/switched-expectations.stderr index 0020d14f5cb9..9db318735bdc 100644 --- a/src/test/ui/switched-expectations.stderr +++ b/src/test/ui/switched-expectations.stderr @@ -9,4 +9,4 @@ LL | let ref string: String = var; //~ ERROR mismatched types [E0308] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs index c1e6245d24be..56acbed47210 100644 --- a/src/test/ui/target-feature-wrong.rs +++ b/src/test/ui/target-feature-wrong.rs @@ -33,6 +33,11 @@ fn bar() {} //~^ ERROR: should be applied to a function mod another {} +#[inline(always)] +//~^ ERROR: cannot use #[inline(always)] +#[target_feature(enable = "sse2")] +unsafe fn test() {} + fn main() { unsafe { foo(); diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr index 0fa6910f2bb3..8773f8504cb0 100644 --- a/src/test/ui/target-feature-wrong.stderr +++ b/src/test/ui/target-feature-wrong.stderr @@ -37,5 +37,11 @@ LL | //~^ ERROR: should be applied to a function LL | mod another {} | -------------- not a function -error: aborting due to 5 previous errors +error: cannot use #[inline(always)] with #[target_feature] + --> $DIR/target-feature-wrong.rs:36:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/test/ui/token/issue-10636-2.rs b/src/test/ui/token/issue-10636-2.rs index 4aa412701937..711803754408 100644 --- a/src/test/ui/token/issue-10636-2.rs +++ b/src/test/ui/token/issue-10636-2.rs @@ -17,3 +17,5 @@ pub fn trace_option(option: Option) { } //~ ERROR: incorrect close delimiter //~^ ERROR: expected expression, found `)` + +fn main() {} diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr index 26816ca0ca22..56a30423171d 100644 --- a/src/test/ui/token/issue-10636-2.stderr +++ b/src/test/ui/token/issue-10636-2.stderr @@ -22,8 +22,5 @@ error: expected expression, found `)` LL | } //~ ERROR: incorrect close delimiter | ^ expected expression -error[E0601]: main function not found +error: aborting due to 3 previous errors -error: aborting due to 4 previous errors - -If you want more information on this error, try using "rustc --explain E0601" diff --git a/src/test/ui/token/issue-15980.stderr b/src/test/ui/token/issue-15980.stderr index 4078797474e5..d52368bf96a7 100644 --- a/src/test/ui/token/issue-15980.stderr +++ b/src/test/ui/token/issue-15980.stderr @@ -24,4 +24,4 @@ LL | let x: io::IoResult<()> = Ok(()); error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0412" +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/token/issue-41155.rs b/src/test/ui/token/issue-41155.rs index 550a90fc6af2..7bd8506af90b 100644 --- a/src/test/ui/token/issue-41155.rs +++ b/src/test/ui/token/issue-41155.rs @@ -11,3 +11,5 @@ impl S { //~ ERROR cannot find type pub } //~ ERROR expected one of + +fn main() {} diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr index ece803b75dc5..b56b95a8aafd 100644 --- a/src/test/ui/token/issue-41155.stderr +++ b/src/test/ui/token/issue-41155.stderr @@ -12,9 +12,6 @@ error[E0412]: cannot find type `S` in this scope LL | impl S { //~ ERROR cannot find type | ^ not found in this scope -error[E0601]: main function not found +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -You've got a few errors: E0412, E0601 -If you want more information on an error, try using "rustc --explain E0412" +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/trait-alias.stderr b/src/test/ui/trait-alias.stderr index 731ea8b8c4c4..5d290e5c7fba 100644 --- a/src/test/ui/trait-alias.stderr +++ b/src/test/ui/trait-alias.stderr @@ -36,4 +36,4 @@ LL | trait CD = Clone + Default; //~ERROR E0645 error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0645" +For more information about this error, try `rustc --explain E0645`. diff --git a/src/test/ui/trait-duplicate-methods.stderr b/src/test/ui/trait-duplicate-methods.stderr index 2aec3f3377dd..1dfddd937ca2 100644 --- a/src/test/ui/trait-duplicate-methods.stderr +++ b/src/test/ui/trait-duplicate-methods.stderr @@ -10,4 +10,4 @@ LL | fn orange(&self); //~ ERROR the name `orange` is defined multiple times error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0428" +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/trait-method-private.stderr b/src/test/ui/trait-method-private.stderr index f89da4d4bf20..3a625ae25a46 100644 --- a/src/test/ui/trait-method-private.stderr +++ b/src/test/ui/trait-method-private.stderr @@ -12,4 +12,4 @@ LL | use inner::Bar; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0624" +For more information about this error, try `rustc --explain E0624`. diff --git a/src/test/ui/trait-safety-fn-body.stderr b/src/test/ui/trait-safety-fn-body.stderr index 894d0c8c3f7f..432df4382227 100644 --- a/src/test/ui/trait-safety-fn-body.stderr +++ b/src/test/ui/trait-safety-fn-body.stderr @@ -6,4 +6,4 @@ LL | *self += 1; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0133" +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/trait-suggest-where-clause.stderr b/src/test/ui/trait-suggest-where-clause.stderr index 71fa93d5e0c8..abd9f5a8b73f 100644 --- a/src/test/ui/trait-suggest-where-clause.stderr +++ b/src/test/ui/trait-suggest-where-clause.stderr @@ -65,4 +65,4 @@ LL | mem::size_of::<[&U]>(); error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits-multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits-multidispatch-convert-ambig-dest.stderr index 65f2de8bad53..46c86cd767a0 100644 --- a/src/test/ui/traits-multidispatch-convert-ambig-dest.stderr +++ b/src/test/ui/traits-multidispatch-convert-ambig-dest.stderr @@ -6,4 +6,4 @@ LL | test(22, std::default::Default::default()); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index d412788af5d8..7f6ee749c4fd 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -36,4 +36,4 @@ LL | let x: Foo = transmute(10); //~ ERROR transmute called with types of di error: aborting due to 4 previous errors -If you want more information on this error, try using "rustc --explain E0512" +For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 00723060307a..1591b06f3ac5 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -88,5 +88,5 @@ LL | mem::transmute::<_, Option>(Some(baz)); error: aborting due to 9 previous errors -You've got a few errors: E0512, E0591 -If you want more information on an error, try using "rustc --explain E0512" +Some errors occurred: E0512, E0591. +For more information about an error, try `rustc --explain E0512`. diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr index fd9c132383ce..ab0bd8fe2d81 100644 --- a/src/test/ui/transmute/transmute-type-parameters.stderr +++ b/src/test/ui/transmute/transmute-type-parameters.stderr @@ -54,4 +54,4 @@ LL | let _: i32 = transmute(x); error: aborting due to 6 previous errors -If you want more information on this error, try using "rustc --explain E0512" +For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/ui/type-alias-bounds.rs b/src/test/ui/type-alias-bounds.rs new file mode 100644 index 000000000000..c1cdeef3a463 --- /dev/null +++ b/src/test/ui/type-alias-bounds.rs @@ -0,0 +1,69 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test ignored_generic_bounds lint warning about bounds in type aliases + +// must-compile-successfully +#![allow(dead_code)] + +use std::rc::Rc; + +type SVec = Vec; +//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] +type S2Vec where T: Send = Vec; +//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds] +type VVec<'b, 'a: 'b+'b> = (&'b u32, Vec<&'a i32>); +//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] +type WVec<'b, T: 'b+'b> = (&'b u32, Vec); +//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] +type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); +//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds] + +static STATIC : u32 = 0; + +fn foo<'a>(y: &'a i32) { + // If any of the bounds above would matter, the code below would be rejected. + // This can be seen when replacing the type aliases above by newtype structs. + // (The type aliases have no unused parameters to make that a valid transformation.) + let mut x : SVec<_> = Vec::new(); + x.push(Rc::new(42)); // is not send + + let mut x : S2Vec<_> = Vec::new(); + x.push(Rc::new(42)); // is not send + + let mut x : VVec<'static, 'a> = (&STATIC, Vec::new()); + x.1.push(y); // 'a: 'static does not hold + + let mut x : WVec<'static, &'a i32> = (&STATIC, Vec::new()); + x.1.push(y); // &'a i32: 'static does not hold + + let mut x : W2Vec<'static, &'a i32> = (&STATIC, Vec::new()); + x.1.push(y); // &'a i32: 'static does not hold +} + +// Bounds are not checked either, i.e. the definition is not necessarily well-formed +struct Sendable(T); +type MySendable = Sendable; // no error here! + +// However, bounds *are* taken into account when accessing associated types +trait Bound { type Assoc; } +type T1 = U::Assoc; //~ WARN not enforced in type aliases +type T2 where U: Bound = U::Assoc; //~ WARN not enforced in type aliases + +// This errors +// type T3 = U::Assoc; +// Do this instead +type T4 = ::Assoc; + +// Make sure the help about associatd types is not shown incorrectly +type T5 = ::Assoc; //~ WARN not enforced in type aliases +type T6 = ::std::vec::Vec; //~ WARN not enforced in type aliases + +fn main() {} diff --git a/src/test/ui/type-alias-bounds.stderr b/src/test/ui/type-alias-bounds.stderr new file mode 100644 index 000000000000..2a2b0b0f26e3 --- /dev/null +++ b/src/test/ui/type-alias-bounds.stderr @@ -0,0 +1,83 @@ +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:18:14 + | +LL | type SVec = Vec; + | ^^^^ ^^^^ + | + = note: #[warn(type_alias_bounds)] on by default + = help: the bound will not be checked when the type alias is used, and should be removed + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:20:21 + | +LL | type S2Vec where T: Send = Vec; + | ^^^^^^^ + | + = help: the clause will not be checked when the type alias is used, and should be removed + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:22:19 + | +LL | type VVec<'b, 'a: 'b+'b> = (&'b u32, Vec<&'a i32>); + | ^^ ^^ + | + = help: the bound will not be checked when the type alias is used, and should be removed + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:24:18 + | +LL | type WVec<'b, T: 'b+'b> = (&'b u32, Vec); + | ^^ ^^ + | + = help: the bound will not be checked when the type alias is used, and should be removed + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:26:25 + | +LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); + | ^^^^^ ^^^^^ + | + = help: the clause will not be checked when the type alias is used, and should be removed + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:57:12 + | +LL | type T1 = U::Assoc; //~ WARN not enforced in type aliases + | ^^^^^ + | + = help: the bound will not be checked when the type alias is used, and should be removed +help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases + --> $DIR/type-alias-bounds.rs:57:21 + | +LL | type T1 = U::Assoc; //~ WARN not enforced in type aliases + | ^^^^^^^^ + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:58:18 + | +LL | type T2 where U: Bound = U::Assoc; //~ WARN not enforced in type aliases + | ^^^^^^^^ + | + = help: the clause will not be checked when the type alias is used, and should be removed +help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases + --> $DIR/type-alias-bounds.rs:58:29 + | +LL | type T2 where U: Bound = U::Assoc; //~ WARN not enforced in type aliases + | ^^^^^^^^ + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:66:12 + | +LL | type T5 = ::Assoc; //~ WARN not enforced in type aliases + | ^^^^^ + | + = help: the bound will not be checked when the type alias is used, and should be removed + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:67:12 + | +LL | type T6 = ::std::vec::Vec; //~ WARN not enforced in type aliases + | ^^^^^ + | + = help: the bound will not be checked when the type alias is used, and should be removed + diff --git a/src/test/ui/type-annotation-needed.stderr b/src/test/ui/type-annotation-needed.stderr index 67c0698a6c29..d48891596df2 100644 --- a/src/test/ui/type-annotation-needed.stderr +++ b/src/test/ui/type-annotation-needed.stderr @@ -12,4 +12,4 @@ LL | fn foo>(x: i32) {} error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0283" +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr index f39b7dcb31f0..a2d6e53df050 100644 --- a/src/test/ui/type-check-defaults.stderr +++ b/src/test/ui/type-check-defaults.stderr @@ -72,4 +72,4 @@ LL | trait ProjectionPred> where T::Item : Add {} error: aborting due to 7 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-check/assignment-in-if.stderr b/src/test/ui/type-check/assignment-in-if.stderr index 32b4315bb83a..7f3ce0d2a5fe 100644 --- a/src/test/ui/type-check/assignment-in-if.stderr +++ b/src/test/ui/type-check/assignment-in-if.stderr @@ -57,4 +57,4 @@ LL | if (if true { x = 4 } else { x = 5 }) { error: aborting due to 5 previous errors -If you want more information on this error, try using "rustc --explain E0308" +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr index 27679e165370..90191ae67451 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_array.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr @@ -8,4 +8,4 @@ LL | let x = []; //~ ERROR type annotations needed error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr index 5c024437b774..e58a5b67c196 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr @@ -10,4 +10,4 @@ LL | let x = vec![]; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 3a1b2879593c..d7887216bc91 100644 --- a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -10,4 +10,4 @@ LL | let (x, ) = (vec![], ); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr index 1e6830601b65..e2374809dd6b 100644 --- a/src/test/ui/type-check/issue-22897.stderr +++ b/src/test/ui/type-check/issue-22897.stderr @@ -6,4 +6,4 @@ LL | []; //~ ERROR type annotations needed error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr index 1eb1f8effbb3..fbb7427ae3e8 100644 --- a/src/test/ui/type-check/issue-40294.stderr +++ b/src/test/ui/type-check/issue-40294.stderr @@ -18,4 +18,4 @@ LL | trait Foo: Sized { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0283" +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/type-check/issue-41314.stderr b/src/test/ui/type-check/issue-41314.stderr index 95b046bf184a..f7d4bb9a02f4 100644 --- a/src/test/ui/type-check/issue-41314.stderr +++ b/src/test/ui/type-check/issue-41314.stderr @@ -2,7 +2,7 @@ error[E0026]: variant `X::Y` does not have a field named `number` --> $DIR/issue-41314.rs:17:16 | LL | X::Y { number } => {} //~ ERROR does not have a field named `number` - | ^^^^^^ variant `X::Y` does not have field `number` + | ^^^^^^ variant `X::Y` does not have this field error[E0027]: pattern does not mention field `0` --> $DIR/issue-41314.rs:17:9 @@ -14,5 +14,5 @@ LL | X::Y { number } => {} //~ ERROR does not have a field named `number error: aborting due to 2 previous errors -You've got a few errors: E0026, E0027 -If you want more information on an error, try using "rustc --explain E0026" +Some errors occurred: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/type-check/missing_trait_impl.stderr b/src/test/ui/type-check/missing_trait_impl.stderr index ef02708fe53f..777f16b12ce6 100644 --- a/src/test/ui/type-check/missing_trait_impl.stderr +++ b/src/test/ui/type-check/missing_trait_impl.stderr @@ -8,4 +8,4 @@ LL | let z = x + y; //~ ERROR binary operation `+` cannot be applied to type error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0369" +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr index ce9c0dc4e409..25283f5e76b1 100644 --- a/src/test/ui/type-check/unknown_type_for_closure.stderr +++ b/src/test/ui/type-check/unknown_type_for_closure.stderr @@ -6,4 +6,4 @@ LL | let x = |_| { }; //~ ERROR type annotations needed error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-dependent-def-issue-49241.rs b/src/test/ui/type-dependent-def-issue-49241.rs new file mode 100644 index 000000000000..64264999fd2f --- /dev/null +++ b/src/test/ui/type-dependent-def-issue-49241.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = vec![0]; + const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item + let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error +} diff --git a/src/test/ui/type-dependent-def-issue-49241.stderr b/src/test/ui/type-dependent-def-issue-49241.stderr new file mode 100644 index 000000000000..f00edccae5d5 --- /dev/null +++ b/src/test/ui/type-dependent-def-issue-49241.stderr @@ -0,0 +1,18 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/type-dependent-def-issue-49241.rs:13:22 + | +LL | const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item + | ^ + | + = help: use the `|| { ... }` closure form instead + +error[E0080]: constant evaluation error + --> $DIR/type-dependent-def-issue-49241.rs:14:18 + | +LL | let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error + | ^ encountered constants with type errors, stopping evaluation + +error: aborting due to 2 previous errors + +Some errors occurred: E0080, E0434. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/type-recursive.stderr b/src/test/ui/type-recursive.stderr index ea90feee3246..c0c2cbc857a8 100644 --- a/src/test/ui/type-recursive.stderr +++ b/src/test/ui/type-recursive.stderr @@ -11,4 +11,4 @@ LL | foolish: t1 error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0072" +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/typeck-builtin-bound-type-parameters.stderr b/src/test/ui/typeck-builtin-bound-type-parameters.stderr index cf4011f5dbe3..221f05b91509 100644 --- a/src/test/ui/typeck-builtin-bound-type-parameters.stderr +++ b/src/test/ui/typeck-builtin-bound-type-parameters.stderr @@ -36,5 +36,5 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} error: aborting due to 6 previous errors -You've got a few errors: E0107, E0244 -If you want more information on an error, try using "rustc --explain E0107" +Some errors occurred: E0107, E0244. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/typeck_type_placeholder_item.stderr b/src/test/ui/typeck_type_placeholder_item.stderr index b00fbafcd691..3f814085955f 100644 --- a/src/test/ui/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck_type_placeholder_item.stderr @@ -204,4 +204,4 @@ LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } error: aborting due to 34 previous errors -If you want more information on this error, try using "rustc --explain E0121" +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck_type_placeholder_lifetime_1.stderr b/src/test/ui/typeck_type_placeholder_lifetime_1.stderr index 19b308f33340..fe9566b31815 100644 --- a/src/test/ui/typeck_type_placeholder_lifetime_1.stderr +++ b/src/test/ui/typeck_type_placeholder_lifetime_1.stderr @@ -6,4 +6,4 @@ LL | let c: Foo<_, _> = Foo { r: &5 }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0244" +For more information about this error, try `rustc --explain E0244`. diff --git a/src/test/ui/typeck_type_placeholder_lifetime_2.stderr b/src/test/ui/typeck_type_placeholder_lifetime_2.stderr index 12712e1e88cf..64ec42454666 100644 --- a/src/test/ui/typeck_type_placeholder_lifetime_2.stderr +++ b/src/test/ui/typeck_type_placeholder_lifetime_2.stderr @@ -6,4 +6,4 @@ LL | let c: Foo<_, usize> = Foo { r: &5 }; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0244" +For more information about this error, try `rustc --explain E0244`. diff --git a/src/test/ui/ui-testing-optout.stderr b/src/test/ui/ui-testing-optout.stderr index 1c13da57b0d0..aab3399a6fcc 100644 --- a/src/test/ui/ui-testing-optout.stderr +++ b/src/test/ui/ui-testing-optout.stderr @@ -18,4 +18,4 @@ error[E0412]: cannot find type `F` in this scope error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0412" +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/unboxed-closure-no-cyclic-sig.stderr b/src/test/ui/unboxed-closure-no-cyclic-sig.stderr index 633ae13ca104..0c0c339286ec 100644 --- a/src/test/ui/unboxed-closure-no-cyclic-sig.stderr +++ b/src/test/ui/unboxed-closure-no-cyclic-sig.stderr @@ -10,4 +10,4 @@ LL | g(|_| { }); //~ ERROR closure/generator type that references itself error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0644" +For more information about this error, try `rustc --explain E0644`. diff --git a/src/test/ui/unboxed-closure-sugar-wrong-trait.stderr b/src/test/ui/unboxed-closure-sugar-wrong-trait.stderr index 8ef0828fba58..82ba4e66393d 100644 --- a/src/test/ui/unboxed-closure-sugar-wrong-trait.stderr +++ b/src/test/ui/unboxed-closure-sugar-wrong-trait.stderr @@ -12,5 +12,5 @@ LL | fn f isize>(x: F) {} error: aborting due to 2 previous errors -You've got a few errors: E0220, E0244 -If you want more information on an error, try using "rustc --explain E0220" +Some errors occurred: E0220, E0244. +For more information about an error, try `rustc --explain E0220`. diff --git a/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr index 3b78481504ce..0062ea77c0b5 100644 --- a/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -11,4 +11,4 @@ LL | foo(c); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0525" +For more information about this error, try `rustc --explain E0525`. diff --git a/src/test/ui/unconstrained-none.stderr b/src/test/ui/unconstrained-none.stderr index 6fdbc8414b61..34d524abed9e 100644 --- a/src/test/ui/unconstrained-none.stderr +++ b/src/test/ui/unconstrained-none.stderr @@ -6,4 +6,4 @@ LL | None; //~ ERROR type annotations needed [E0282] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/unconstrained-ref.stderr b/src/test/ui/unconstrained-ref.stderr index 7aeec39ae14a..1fddf4531199 100644 --- a/src/test/ui/unconstrained-ref.stderr +++ b/src/test/ui/unconstrained-ref.stderr @@ -6,4 +6,4 @@ LL | S { o: &None }; //~ ERROR type annotations needed [E0282] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/underscore-ident-matcher.rs b/src/test/ui/underscore-ident-matcher.rs new file mode 100644 index 000000000000..eee99296c794 --- /dev/null +++ b/src/test/ui/underscore-ident-matcher.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! identity { + ($i: ident) => ( + $i + ) +} + +fn main() { + let identity!(_) = 10; //~ ERROR no rules expected the token `_` +} diff --git a/src/test/ui/underscore-ident-matcher.stderr b/src/test/ui/underscore-ident-matcher.stderr new file mode 100644 index 000000000000..7f2b6ac30b0d --- /dev/null +++ b/src/test/ui/underscore-ident-matcher.stderr @@ -0,0 +1,8 @@ +error: no rules expected the token `_` + --> $DIR/underscore-ident-matcher.rs:18:19 + | +LL | let identity!(_) = 10; //~ ERROR no rules expected the token `_` + | ^ + +error: aborting due to previous error + diff --git a/src/test/run-pass/move-guard-const.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs similarity index 62% rename from src/test/run-pass/move-guard-const.rs rename to src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs index 6e49538e98a3..e573ad8fc1f0 100644 --- a/src/test/run-pass/move-guard-const.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs @@ -8,20 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// pretty-expanded FIXME #23616 +// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision, +// and not like an object lifetime default. +// +// cc #48468 -#![feature(box_syntax)] +#![feature(dyn_trait)] -fn main() { - let x: Box<_> = box 1; +use std::fmt::Debug; - let v = (1, 2); - - match v { - (2, 1) if take(x) => (), - (1, 2) if take(x) => (), - _ => (), - } +struct Foo { + x: Box, //~ ERROR missing lifetime specifier + //~^ ERROR E0228 } -fn take(_: T) -> bool { false } +fn main() { } diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr new file mode 100644 index 000000000000..6d777841f031 --- /dev/null +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -0,0 +1,16 @@ +error[E0106]: missing lifetime specifier + --> $DIR/dyn-trait-underscore-in-struct.rs:21:24 + | +LL | x: Box, //~ ERROR missing lifetime specifier + | ^^ expected lifetime parameter + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/dyn-trait-underscore-in-struct.rs:21:12 + | +LL | x: Box, //~ ERROR missing lifetime specifier + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors occurred: E0106, E0228. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs new file mode 100644 index 000000000000..9640d3465978 --- /dev/null +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision, +// and not like an object lifetime default. +// +// cc #48468 + +#![feature(dyn_trait)] + +fn a(items: &[T]) -> Box> { + // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` + Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime +} + +fn b(items: &[T]) -> Box + '_> { + Box::new(items.iter()) // OK, equivalent to c +} + +fn c<'a, T>(items: &'a [T]) -> Box + 'a> { + Box::new(items.iter()) // OK, equivalent to b +} + +fn main() { } diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr new file mode 100644 index 000000000000..f1e59aed54a3 --- /dev/null +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements + --> $DIR/dyn-trait-underscore.rs:20:20 + | +LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + | ^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 18:1... + --> $DIR/dyn-trait-underscore.rs:18:1 + | +LL | / fn a(items: &[T]) -> Box> { +LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime +LL | | } + | |_^ +note: ...so that reference does not outlive borrowed content + --> $DIR/dyn-trait-underscore.rs:20:14 + | +LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + | ^^^^^ + = note: but, the lifetime must be valid for the static lifetime... + = note: ...so that the expression is assignable: + expected std::boxed::Box + 'static> + found std::boxed::Box> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/unevaluated_fixed_size_array_len.rs b/src/test/ui/unevaluated_fixed_size_array_len.rs new file mode 100644 index 000000000000..a6ed9f32106f --- /dev/null +++ b/src/test/ui/unevaluated_fixed_size_array_len.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// https://github.com/rust-lang/rust/issues/49208 + +trait Foo { + fn foo(); +} + +impl Foo for [(); 1] { + fn foo() {} +} + +fn main() { + <[(); 0] as Foo>::foo() //~ ERROR E0277 +} diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr new file mode 100644 index 000000000000..6e959da99397 --- /dev/null +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied + --> $DIR/unevaluated_fixed_size_array_len.rs:22:5 + | +LL | <[(); 0] as Foo>::foo() //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` + | + = help: the following implementations were found: + <[(); 1] as Foo> +note: required by `Foo::foo` + --> $DIR/unevaluated_fixed_size_array_len.rs:14:5 + | +LL | fn foo(); + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-derive-eq.stderr b/src/test/ui/union/union-derive-eq.stderr index 88b33c3e96e1..02fa0ca6f831 100644 --- a/src/test/ui/union/union-derive-eq.stderr +++ b/src/test/ui/union/union-derive-eq.stderr @@ -8,4 +8,4 @@ LL | a: PartialEqNotEq, //~ ERROR the trait bound `PartialEqNotEq: std::cmp: error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.stderr index d902ad1629cd..cfb5bc7520b5 100644 --- a/src/test/ui/union/union-fields-2.stderr +++ b/src/test/ui/union/union-fields-2.stderr @@ -52,7 +52,7 @@ error[E0026]: union `U` does not have a field named `c` --> $DIR/union-fields-2.rs:28:19 | LL | let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field - | ^ union `U` does not have field `c` + | ^ union `U` does not have this field error: union patterns should have exactly one field --> $DIR/union-fields-2.rs:28:9 @@ -80,5 +80,5 @@ LL | let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns error: aborting due to 13 previous errors -You've got a few errors: E0026, E0436, E0560 -If you want more information on an error, try using "rustc --explain E0026" +Some errors occurred: E0026, E0436, E0560. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr index 4f2d00aaa3e2..fb81a7b695d4 100644 --- a/src/test/ui/union/union-sized-field.stderr +++ b/src/test/ui/union/union-sized-field.stderr @@ -30,4 +30,4 @@ LL | Value(T), //~ ERROR the trait bound `T: std::marker::Sized` is not sati error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr index f2ff38bd0c7c..631aacb0289f 100644 --- a/src/test/ui/union/union-suggest-field.stderr +++ b/src/test/ui/union/union-suggest-field.stderr @@ -20,5 +20,5 @@ LL | let y = u.calculate; //~ ERROR attempted to take value of method `calcu error: aborting due to 3 previous errors -You've got a few errors: E0560, E0609, E0615 -If you want more information on an error, try using "rustc --explain E0560" +Some errors occurred: E0560, E0609, E0615. +For more information about an error, try `rustc --explain E0560`. diff --git a/src/test/ui/unknown-language-item.stderr b/src/test/ui/unknown-language-item.stderr index b97971c29dc7..95ce5db33ae5 100644 --- a/src/test/ui/unknown-language-item.stderr +++ b/src/test/ui/unknown-language-item.stderr @@ -6,4 +6,4 @@ LL | #[lang = "foo"] error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0522" +For more information about this error, try `rustc --explain E0522`. diff --git a/src/test/ui/unsafe-const-fn.stderr b/src/test/ui/unsafe-const-fn.stderr index 43b8e36baf23..270b90ec3fcb 100644 --- a/src/test/ui/unsafe-const-fn.stderr +++ b/src/test/ui/unsafe-const-fn.stderr @@ -6,4 +6,4 @@ LL | const VAL: u32 = dummy(0xFFFF); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0133" +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsized-enum2.stderr b/src/test/ui/unsized-enum2.stderr index f2bfa6b82141..c05c1cfe4129 100644 --- a/src/test/ui/unsized-enum2.stderr +++ b/src/test/ui/unsized-enum2.stderr @@ -188,4 +188,4 @@ LL | VL{u: isize, x: Path4}, //~ ERROR `PathHelper4 + 'static: std::marker:: error: aborting due to 20 previous errors -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/use-mod.stderr b/src/test/ui/use-mod.stderr index 0a63f370d97d..dcdba6fce9ad 100644 --- a/src/test/ui/use-mod.stderr +++ b/src/test/ui/use-mod.stderr @@ -30,5 +30,5 @@ LL | self as other_bar error: aborting due to 3 previous errors -You've got a few errors: E0252, E0430, E0431 -If you want more information on an error, try using "rustc --explain E0252" +Some errors occurred: E0252, E0430, E0431. +For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/use-nested-groups-error.stderr b/src/test/ui/use-nested-groups-error.stderr index 64bbc7b588ed..5e0fd503bc27 100644 --- a/src/test/ui/use-nested-groups-error.stderr +++ b/src/test/ui/use-nested-groups-error.stderr @@ -6,4 +6,4 @@ LL | use a::{b1::{C1, C2}, B2}; error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0432" +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/variadic-ffi-3.stderr b/src/test/ui/variadic-ffi-3.stderr index b9a84a0cd37d..c7355405b2ac 100644 --- a/src/test/ui/variadic-ffi-3.stderr +++ b/src/test/ui/variadic-ffi-3.stderr @@ -72,5 +72,5 @@ LL | foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function error: aborting due to 10 previous errors -You've got a few errors: E0060, E0308, E0617 -If you want more information on an error, try using "rustc --explain E0060" +Some errors occurred: E0060, E0308, E0617. +For more information about an error, try `rustc --explain E0060`. diff --git a/src/test/ui/variance-unused-type-param.stderr b/src/test/ui/variance-unused-type-param.stderr index d606c5ef6ed0..b3ae91a6fa58 100644 --- a/src/test/ui/variance-unused-type-param.stderr +++ b/src/test/ui/variance-unused-type-param.stderr @@ -24,4 +24,4 @@ LL | enum ListCell { error: aborting due to 3 previous errors -If you want more information on this error, try using "rustc --explain E0392" +For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/vector-no-ann.stderr index c3849bb82ba4..90acc2f86d74 100644 --- a/src/test/ui/vector-no-ann.stderr +++ b/src/test/ui/vector-no-ann.stderr @@ -8,4 +8,4 @@ LL | let _foo = Vec::new(); error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0282" +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/wasm-custom-section/malformed.rs b/src/test/ui/wasm-custom-section/malformed.rs new file mode 100644 index 000000000000..13b1685a4807 --- /dev/null +++ b/src/test/ui/wasm-custom-section/malformed.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(wasm_custom_section)] + +#[wasm_custom_section] //~ ERROR: must be of the form +const A: [u8; 1] = [0]; + +#[wasm_custom_section(foo)] //~ ERROR: must be of the form +const B: [u8; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/wasm-custom-section/malformed.stderr b/src/test/ui/wasm-custom-section/malformed.stderr new file mode 100644 index 000000000000..c716c824aebd --- /dev/null +++ b/src/test/ui/wasm-custom-section/malformed.stderr @@ -0,0 +1,14 @@ +error: must be of the form #[wasm_custom_section = "foo"] + --> $DIR/malformed.rs:13:1 + | +LL | #[wasm_custom_section] //~ ERROR: must be of the form + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: must be of the form #[wasm_custom_section = "foo"] + --> $DIR/malformed.rs:16:1 + | +LL | #[wasm_custom_section(foo)] //~ ERROR: must be of the form + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/wasm-custom-section/not-const.rs b/src/test/ui/wasm-custom-section/not-const.rs new file mode 100644 index 000000000000..68077fb2fe4a --- /dev/null +++ b/src/test/ui/wasm-custom-section/not-const.rs @@ -0,0 +1,29 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(wasm_custom_section)] + +#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts +static A: [u8; 2] = [1, 2]; + +#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts +struct B {} + +#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts +enum C {} + +#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts +impl B {} + +#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts +mod d {} + +#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts +fn main() {} diff --git a/src/test/ui/wasm-custom-section/not-const.stderr b/src/test/ui/wasm-custom-section/not-const.stderr new file mode 100644 index 000000000000..17c85b3e848e --- /dev/null +++ b/src/test/ui/wasm-custom-section/not-const.stderr @@ -0,0 +1,38 @@ +error: only allowed on consts + --> $DIR/not-const.rs:13:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: only allowed on consts + --> $DIR/not-const.rs:16:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: only allowed on consts + --> $DIR/not-const.rs:19:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: only allowed on consts + --> $DIR/not-const.rs:22:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: only allowed on consts + --> $DIR/not-const.rs:25:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: only allowed on consts + --> $DIR/not-const.rs:28:1 + | +LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/wasm-custom-section/not-slice.rs b/src/test/ui/wasm-custom-section/not-slice.rs new file mode 100644 index 000000000000..2d91641a5f75 --- /dev/null +++ b/src/test/ui/wasm-custom-section/not-slice.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(wasm_custom_section)] + +#[wasm_custom_section = "foo"] +const A: u8 = 0; //~ ERROR: must be an array of bytes + +#[wasm_custom_section = "foo"] +const B: &[u8] = &[0]; //~ ERROR: must be an array of bytes + +#[wasm_custom_section = "foo"] +const C: &[u8; 1] = &[0]; //~ ERROR: must be an array of bytes + +fn main() {} diff --git a/src/test/ui/wasm-custom-section/not-slice.stderr b/src/test/ui/wasm-custom-section/not-slice.stderr new file mode 100644 index 000000000000..f2563ce0dddc --- /dev/null +++ b/src/test/ui/wasm-custom-section/not-slice.stderr @@ -0,0 +1,20 @@ +error: must be an array of bytes like `[u8; N]` + --> $DIR/not-slice.rs:14:1 + | +LL | const A: u8 = 0; //~ ERROR: must be an array of bytes + | ^^^^^^^^^^^^^^^^ + +error: must be an array of bytes like `[u8; N]` + --> $DIR/not-slice.rs:17:1 + | +LL | const B: &[u8] = &[0]; //~ ERROR: must be an array of bytes + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: must be an array of bytes like `[u8; N]` + --> $DIR/not-slice.rs:20:1 + | +LL | const C: &[u8; 1] = &[0]; //~ ERROR: must be an array of bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/wasm-import-module.rs b/src/test/ui/wasm-import-module.rs new file mode 100644 index 000000000000..0b743d9e486b --- /dev/null +++ b/src/test/ui/wasm-import-module.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(wasm_import_module)] + +#[wasm_import_module] //~ ERROR: must be of the form +extern {} + +#[wasm_import_module = "foo"] //~ ERROR: must only be attached to +fn foo() {} + +fn main() {} + diff --git a/src/test/ui/wasm-import-module.stderr b/src/test/ui/wasm-import-module.stderr new file mode 100644 index 000000000000..bf301ce5269a --- /dev/null +++ b/src/test/ui/wasm-import-module.stderr @@ -0,0 +1,14 @@ +error: must be of the form #[wasm_import_module = "..."] + --> $DIR/wasm-import-module.rs:13:1 + | +LL | #[wasm_import_module] //~ ERROR: must be of the form + | ^^^^^^^^^^^^^^^^^^^^^ + +error: must only be attached to foreign modules + --> $DIR/wasm-import-module.rs:16:1 + | +LL | #[wasm_import_module = "foo"] //~ ERROR: must only be attached to + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/cargo b/src/tools/cargo index 1d6dfea44f97..b70ab13b3162 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 1d6dfea44f97199d5d5c177c7dadcde393eaff9a +Subproject commit b70ab13b31628e91b05961d55c07abf20ad49de6 diff --git a/src/tools/clippy b/src/tools/clippy index d5e233a72049..b45801ff192e 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit d5e233a720495c52af25d8f6dcc9e55e1193beb9 +Subproject commit b45801ff192e6f1bd3504c05e612a1004f52a24e diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 08630628b718..761d1e511d52 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -24,6 +24,7 @@ struct Diagnostic { level: String, spans: Vec, children: Vec, + rendered: Option, } #[derive(Deserialize, Clone)] @@ -56,6 +57,25 @@ struct DiagnosticCode { explanation: Option, } +pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String { + output.lines() + .filter_map(|line| if line.starts_with('{') { + match serde_json::from_str::(line) { + Ok(diagnostic) => diagnostic.rendered, + Err(error) => { + proc_res.fatal(Some(&format!("failed to decode compiler output as json: \ + `{}`\noutput: {}\nline: {}", + error, + line, + output))); + } + } + } else { + None + }) + .collect() +} + pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec { output.lines() .flat_map(|line| parse_line(file_name, line, output, proc_res)) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index d3f571dd8aeb..e826c5366a81 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -248,7 +248,7 @@ impl<'test> TestCx<'test> { } fn run_cfail_test(&self) { - let proc_res = self.compile_test(&[]); + let proc_res = self.compile_test(); self.check_if_test_should_compile(&proc_res); self.check_no_compiler_crash(&proc_res); @@ -267,7 +267,7 @@ impl<'test> TestCx<'test> { } fn run_rfail_test(&self) { - let proc_res = self.compile_test(&[]); + let proc_res = self.compile_test(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); @@ -309,7 +309,7 @@ impl<'test> TestCx<'test> { } fn run_rpass_test(&self) { - let proc_res = self.compile_test(&[]); + let proc_res = self.compile_test(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); @@ -336,7 +336,7 @@ impl<'test> TestCx<'test> { return self.run_rpass_test(); } - let mut proc_res = self.compile_test(&[]); + let mut proc_res = self.compile_test(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); @@ -578,7 +578,7 @@ impl<'test> TestCx<'test> { let mut cmds = commands.join("\n"); // compile test file (it should have 'compile-flags:-g' in the header) - let compiler_run_result = self.compile_test(&[]); + let compiler_run_result = self.compile_test(); if !compiler_run_result.status.success() { self.fatal_proc_rec("compilation failed!", &compiler_run_result); } @@ -835,7 +835,7 @@ impl<'test> TestCx<'test> { fn run_debuginfo_lldb_test_no_opt(&self) { // compile test file (it should have 'compile-flags:-g' in the header) - let compile_result = self.compile_test(&[]); + let compile_result = self.compile_test(); if !compile_result.status.success() { self.fatal_proc_rec("compilation failed!", &compile_result); } @@ -1272,15 +1272,12 @@ impl<'test> TestCx<'test> { } } - fn compile_test(&self, extra_args: &[&'static str]) -> ProcRes { + fn compile_test(&self) -> ProcRes { let mut rustc = self.make_compile_args( &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name()), ); - if !extra_args.is_empty() { - rustc.args(extra_args); - } rustc.arg("-L").arg(&self.aux_output_dir_name()); match self.config.mode { @@ -1327,6 +1324,8 @@ impl<'test> TestCx<'test> { let mut rustdoc = Command::new(rustdoc_path); rustdoc + .arg("-L") + .arg(self.config.run_lib_path.to_str().unwrap()) .arg("-L") .arg(aux_dir) .arg("-o") @@ -1626,12 +1625,14 @@ impl<'test> TestCx<'test> { if self.props.error_patterns.is_empty() { rustc.args(&["--error-format", "json"]); } + if !self.props.disable_ui_testing_normalization { + rustc.arg("-Zui-testing"); + } } Ui => { - // In case no "--error-format" has been given in the test, we'll compile - // a first time to get the compiler's output then compile with - // "--error-format json" to check if all expected errors are actually there - // and that no new one appeared. + if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) { + rustc.args(&["--error-format", "json"]); + } if !self.props.disable_ui_testing_normalization { rustc.arg("-Zui-testing"); } @@ -2114,7 +2115,7 @@ impl<'test> TestCx<'test> { fn run_codegen_units_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); - let proc_res = self.compile_test(&[]); + let proc_res = self.compile_test(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); @@ -2359,11 +2360,6 @@ impl<'test> TestCx<'test> { } fn run_rmake_test(&self) { - // FIXME(#11094): we should fix these tests - if self.config.host != self.config.target { - return; - } - let cwd = env::current_dir().unwrap(); let src_root = self.config .src_base @@ -2400,19 +2396,27 @@ impl<'test> TestCx<'test> { .env("S", src_root) .env("RUST_BUILD_STAGE", &self.config.stage_id) .env("RUSTC", cwd.join(&self.config.rustc_path)) - .env( - "RUSTDOC", - cwd.join(&self.config - .rustdoc_path - .as_ref() - .expect("--rustdoc-path passed")), - ) .env("TMPDIR", &tmpdir) .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path)) .env("LLVM_COMPONENTS", &self.config.llvm_components) - .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags); + .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags) + + // We for sure don't want these tests to run in parallel, so make + // sure they don't have access to these vars if we we run via `make` + // at the top level + .env_remove("MAKEFLAGS") + .env_remove("MFLAGS") + .env_remove("CARGO_MAKEFLAGS"); + + if let Some(ref rustdoc) = self.config.rustdoc_path { + cmd.env("RUSTDOC", cwd.join(rustdoc)); + } + + if let Some(ref node) = self.config.nodejs { + cmd.env("NODE", node); + } if let Some(ref linker) = self.config.linker { cmd.env("RUSTC_LINKER", linker); @@ -2422,7 +2426,7 @@ impl<'test> TestCx<'test> { // compiler flags set in the test cases: cmd.env_remove("RUSTFLAGS"); - if self.config.target.contains("msvc") { + if self.config.target.contains("msvc") && self.config.cc != "" { // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe` // and that `lib.exe` lives next to it. let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe"); @@ -2498,7 +2502,7 @@ impl<'test> TestCx<'test> { .iter() .any(|s| s.contains("--error-format")); - let proc_res = self.compile_test(&[]); + let proc_res = self.compile_test(); self.check_if_test_should_compile(&proc_res); let expected_stderr_path = self.expected_output_path(UI_STDERR); @@ -2510,8 +2514,13 @@ impl<'test> TestCx<'test> { let normalized_stdout = self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); - let normalized_stderr = self.normalize_output(&proc_res.stderr, - &self.props.normalize_stderr); + let stderr = if explicit { + proc_res.stderr.clone() + } else { + json::extract_rendered(&proc_res.stderr, &proc_res) + }; + + let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); let mut errors = 0; errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); @@ -2544,7 +2553,6 @@ impl<'test> TestCx<'test> { } } if !explicit { - let proc_res = self.compile_test(&["--error-format", "json"]); if !expected_errors.is_empty() || !proc_res.status.success() { // "// error-pattern" comments self.check_expected_errors(expected_errors, &proc_res); @@ -2556,7 +2564,7 @@ impl<'test> TestCx<'test> { } fn run_mir_opt_test(&self) { - let proc_res = self.compile_test(&[]); + let proc_res = self.compile_test(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index cf63cb2e5d90..c612f0117aaf 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -14,21 +14,25 @@ use common::Config; /// Conversion table from triple OS name to Rust SYSNAME const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("android", "android"), + ("androideabi", "android"), ("bitrig", "bitrig"), ("cloudabi", "cloudabi"), ("darwin", "macos"), ("dragonfly", "dragonfly"), + ("emscripten", "emscripten"), ("freebsd", "freebsd"), + ("fuchsia", "fuchsia"), ("haiku", "haiku"), ("ios", "ios"), + ("l4re", "l4re"), ("linux", "linux"), ("mingw32", "windows"), ("netbsd", "netbsd"), ("openbsd", "openbsd"), + ("redox", "redox"), + ("solaris", "solaris"), ("win32", "windows"), ("windows", "windows"), - ("solaris", "solaris"), - ("emscripten", "emscripten"), ]; const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ @@ -36,19 +40,33 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("amd64", "x86_64"), ("arm", "arm"), ("arm64", "aarch64"), + ("armv4t", "arm"), + ("armv5te", "arm"), + ("armv7", "arm"), + ("armv7s", "arm"), + ("asmjs", "asmjs"), ("hexagon", "hexagon"), ("i386", "x86"), ("i586", "x86"), ("i686", "x86"), ("mips", "mips"), + ("mips64", "mips64"), + ("mips64el", "mips64"), + ("mipsel", "mips"), ("msp430", "msp430"), ("powerpc", "powerpc"), + ("powerpc64", "powerpc64"), + ("powerpc64le", "powerpc64"), ("s390x", "s390x"), ("sparc", "sparc"), + ("sparc64", "sparc64"), + ("sparcv9", "sparc64"), + ("thumbv6m", "thumb"), + ("thumbv7em", "thumb"), + ("thumbv7m", "thumb"), + ("wasm32", "wasm32"), ("x86_64", "x86_64"), ("xcore", "xcore"), - ("asmjs", "asmjs"), - ("wasm32", "wasm32"), ]; pub fn matches_os(triple: &str, name: &str) -> bool { @@ -57,16 +75,18 @@ pub fn matches_os(triple: &str, name: &str) -> bool { if triple == "wasm32-unknown-unknown" { return name == "emscripten" || name == "wasm32-bare" } + let triple: Vec<_> = triple.split('-').collect(); for &(triple_os, os) in OS_TABLE { - if triple.contains(triple_os) { + if triple.contains(&triple_os) { return os == name; } } panic!("Cannot determine OS from triple"); } pub fn get_arch(triple: &str) -> &'static str { + let triple: Vec<_> = triple.split('-').collect(); for &(triple_arch, arch) in ARCH_TABLE { - if triple.contains(triple_arch) { + if triple.contains(&triple_arch) { return arch; } } diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 76f5f98358c9..ade7ae0a4aee 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -61,8 +61,8 @@ impl Formatter for HTMLFormatter { Rust Compiler Error Index - - + +