IMAGE: x86_64-gnu-full-bootstrap
x86_64-gnu-aux:
IMAGE: x86_64-gnu-aux
- # FIXME: needs reenabling here rather than Travis
- # x86_64-gnu-tools:
- # IMAGE: x86_64-gnu-tools
+ x86_64-gnu-tools:
+ IMAGE: x86_64-gnu-tools
x86_64-gnu-debug:
IMAGE: x86_64-gnu-debug
x86_64-gnu-nopt:
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
VCVARS_BAT: vcvars64.bat
# MSVC tools tests
- # FIXME: broken on azure right now, need to figure out a cause and
- # reenable
- # x86_64-msvc-tools:
- # MSYS_BITS: 64
- # SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
- # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
+ x86_64-msvc-tools:
+ MSYS_BITS: 64
+ SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
+ RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
# 32/64-bit MinGW builds.
#
steps:
+# Disable automatic line ending conversion, which is enabled by default on
+# Azure's Windows image. Having the conversion enabled caused regressions both
+# in our test suite (it broke miri tests) and in the ecosystem, since we
+# started shipping install scripts with CRLF endings instead of the old LF.
+- bash: git config --global core.autocrlf false
+ displayName: "Disable git automatic line ending conversion"
+
- checkout: self
fetchDepth: 2
Melody Horn <melody@boringcactus.com> <mathphreak@gmail.com>
Michael Williams <m.t.williams@live.com>
Michael Woerister <michaelwoerister@posteo> <michaelwoerister@gmail>
+Michael Woerister <michaelwoerister@posteo> <michaelwoerister@users.noreply.github.com>
+Michael Woerister <michaelwoerister@posteo> <michaelwoerister@posteo.net>
Mickaël Raybaud-Roig <raybaudroigm@gmail.com> m-r-r <raybaudroigm@gmail.com>
Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com>
Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
language: shell
-sudo: required
-dist: xenial
-services:
- - docker
-addons:
- apt:
- packages:
- - gdb
+script: echo Travis CI is not used anymore
-git:
- depth: 2
- submodules: false
-
-env:
- global:
- - CI_JOB_NAME=$TRAVIS_JOB_NAME
-
-matrix:
- fast_finish: true
- include:
- - env: IMAGE=x86_64-gnu-tools
- name: x86_64-gnu-tools
- if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/)
-
-before_install:
- # We'll use the AWS cli to download/upload cached docker layers as well as
- # push our deployments, so download that here.
- - pip install --user awscli; export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/
- - 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.
- # see https://github.com/travis-ci/travis-ci/issues/8891#issuecomment-353403729
- - if [ "$TRAVIS_OS_NAME" = linux ]; then
- echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json;
- sudo service docker restart;
- fi
-
-install:
- - case "$TRAVIS_OS_NAME" in
- linux)
- travis_retry curl -fo $HOME/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl &&
- chmod +x $HOME/stamp &&
- export PATH=$PATH:$HOME
- ;;
- osx)
- if [[ "$SCRIPT" == "./x.py dist" ]]; then
- travis_retry brew update &&
- travis_retry brew install xz &&
- travis_retry brew install swig@3 &&
- brew link --force swig@3;
- fi &&
- 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 &&
- travis_retry curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - &&
- export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang &&
- export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ &&
- export AR=ar
- ;;
- esac
-
-before_script:
- - >
- echo "#### Disk usage before running script:";
- df -h;
- du . | sort -nr | head -n100
- - >
- RUN_SCRIPT="src/ci/init_repo.sh . $HOME/rustsrc";
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
- export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh";
- else
- export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE";
- # Enable core dump on Linux.
- sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern';
- fi
- - >
- if [ "$IMAGE" = mingw-check ]; then
- # verify the publish_toolstate script works.
- git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git;
- cd rust-toolstate;
- python2.7 "$TRAVIS_BUILD_DIR/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "";
- cd ..;
- rm -rf rust-toolstate;
- fi
-
-# Log time information from this machine and an external machine for insight into possible
-# clock drift. Timezones don't matter since relative deltas give all the necessary info.
-script:
- - >
- date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
- - stamp sh -x -c "$RUN_SCRIPT"
- - >
- date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
-
-after_success:
- - >
- echo "#### Build successful; Disk usage after running script:";
- df -h;
- du . | sort -nr | head -n100
- - >
- if [ "$DEPLOY$DEPLOY_ALT" == "1" ]; then
- mkdir -p deploy/$TRAVIS_COMMIT;
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
- rm -rf build/dist/doc &&
- cp -r build/dist/* deploy/$TRAVIS_COMMIT;
- else
- rm -rf obj/build/dist/doc &&
- cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
- fi;
- ls -la deploy/$TRAVIS_COMMIT;
- deploy_dir=rustc-builds;
- if [ "$DEPLOY_ALT" == "1" ]; then
- deploy_dir=rustc-builds-alt;
- fi;
- travis_retry aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://rust-lang-ci2/$deploy_dir
- fi
-
-after_failure:
- - >
- echo "#### Build failed; Disk usage after running script:";
- df -h;
- du . | sort -nr | head -n100
-
- # Random attempt at debugging currently. Just poking around in here to see if
- # anything shows up.
-
- # Dump backtrace for macOS
- - 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 \; || true
-
- # Dump backtrace for Linux
- - ln -s . checkout &&
- for CORE in obj/cores/core.*; do
- EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|');
- if [ -f "$EXE" ]; then
- printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE";
- gdb --batch -q -c "$CORE" "$EXE"
- -iex 'set auto-load off'
- -iex 'dir src/'
- -iex 'set sysroot .'
- -ex bt
- -ex q;
- echo travis_fold":"end:crashlog;
- fi;
- done || true
-
- # see #50887
- - cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
-
- # attempt to debug anything killed by the oom killer on linux, just to see if
- # it happened
- - dmesg | grep -i kill
+branches:
+ only:
+ - auto
+ - try
notifications:
email: false
version = "0.0.0"
dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "openssl-src"
-version = "111.1.0+1.1.1a"
+version = "111.3.0+1.1.1c"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
dependencies = [
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-src 111.3.0+1.1.1c (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum opener 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "998c59e83d9474c01127a96e023b7a04bb061dd286bf8bb939d31dc8d31a7448"
"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-"checksum openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)" = "26bb632127731bf4ac49bf86a5dde12d2ca0918c2234fc39d79d4da2ccbc6da7"
+"checksum openssl-src 111.3.0+1.1.1c (registry+https://github.com/rust-lang/crates.io-index)" = "53ed5f31d294bdf5f7a4ba0a206c2754b0f60e9a63b7e3076babc5317873c797"
"checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d"
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
"checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
_Note: If you wish to contribute to the compiler, you should read
[this chapter](https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html)
-of the rustc-guide instead._
+of the rustc-guide instead of this section._
### Building on *nix
1. Make sure you have installed the dependencies:
Compatibility Notes
-------------------
-- [`Command::before_exec` is now deprecated in favor of the
- unsafe method `Command::pre_exec`.][58059]
-- [Use of `ATOMIC_{BOOL, ISIZE, USIZE}_INIT` is now deprecated.][57425] As you
+- [`Command::before_exec` is being replaced by the unsafe method
+ `Command::pre_exec`][58059] and will be deprecated with Rust 1.37.0.
+- [Use of `ATOMIC_{BOOL, ISIZE, USIZE}_INIT` is now deprecated][57425] as you
can now use `const` functions in `static` variables.
[58370]: https://github.com/rust-lang/rust/pull/58370/
-environment:
- # This is required for at least an AArch64 compiler in one image, and is also
- # going to soon be required for compiling LLVM.
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview
-
- # By default schannel checks revocation of certificates unlike some other SSL
- # backends, but we've historically had problems on CI where a revocation
- # server goes down presumably. See #43333 for more info
- CARGO_HTTP_CHECK_REVOKE: false
-
- matrix:
- # MSVC tools tests
- - CI_JOB_NAME: x86_64-msvc-tools
- MSYS_BITS: 64
- SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
- RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
-
-matrix:
- fast_finish: true
-
-clone_depth: 2
+clone_depth: 1
build: false
-install:
- # Print which AppVeyor agent version we're running on.
- - appveyor version
- # If we need to download a custom MinGW, do so here and set the path
- # appropriately.
- #
- # Note that this *also* means that we're not using what is typically
- # /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where
- # /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we
- # move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe`
- # file exists in there (which it doesn't by default).
- - if defined MINGW_URL appveyor-retry appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE%
- - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul
- - if defined MINGW_URL set PATH=%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH%
-
- # If we're compiling for MSVC then we, like most other distribution builders,
- # switch to clang as the compiler. This'll allow us eventually to enable LTO
- # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think
- # clang has an output mode compatible with MinGW that we need. If it does we
- # should switch to clang for MinGW as well!
- #
- # Note that the LLVM installer is an NSIS installer
- #
- # Original downloaded here came from
- # http://releases.llvm.org/8.0.0/LLVM-8.0.0-win64.exe
- - if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-8.0.0-win64.exe
- - if NOT defined MINGW_URL .\LLVM-8.0.0-win64.exe /S /NCRC /D=C:\clang-rust
- - if NOT defined MINGW_URL set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=C:\clang-rust\bin\clang-cl.exe
-
- # Here we do a pretty heinous thing which is to mangle the MinGW installation
- # we just had above. Currently, as of this writing, we're using MinGW-w64
- # builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to
- # be the first version which contains a fix for #40546, builds randomly
- # failing during LLVM due to ar.exe/ranlib.exe failures.
- #
- # Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds
- # to contain a regression in gdb (#40184). As a result if we were to use the
- # gdb provided (7.11.1) then we would fail all debuginfo tests.
- #
- # In order to fix spurious failures (pretty high priority) we use 6.3.0. To
- # avoid disabling gdb tests we download an *old* version of gdb, specifically
- # that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb
- # with the 6.2.0 gdb to get tests passing.
- #
- # Note that we don't literally overwrite the gdb.exe binary because it appears
- # to just use gdborig.exe, so that's the binary we deal with instead.
- - if defined MINGW_URL appveyor-retry appveyor DownloadFile %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe
- - if defined MINGW_URL mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe
-
- # Otherwise pull in the MinGW installed on appveyor
- - if NOT defined MINGW_URL set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH%
-
- # Prefer the "native" Python as LLVM has trouble building with MSYS sometimes
- - copy C:\Python27\python.exe C:\Python27\python2.7.exe
- - set PATH=C:\Python27;%PATH%
-
- # Download and install sccache
- - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc
- - mv 2018-04-26-sccache-x86_64-pc-windows-msvc sccache.exe
- - set PATH=%PATH%;%CD%
-
- # Download and install ninja
- #
- # Note that this is originally from the github releases patch of Ninja
- - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip
- - 7z x 2017-03-15-ninja-win.zip
- - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja
- # - set PATH=%PATH%;%CD% -- this already happens above for sccache
-
- # Install InnoSetup to get `iscc` used to produce installers
- - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-08-22-is.exe
- - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
- - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
-
- # Help debug some handle issues on AppVeyor
- - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-05-15-Handle.zip
- - mkdir handle
- - 7z x -ohandle 2017-05-15-Handle.zip
- - set PATH=%PATH%;%CD%\handle
- - handle.exe -accepteula -help
-
test_script:
- - if not exist C:\cache\rustsrc\NUL mkdir C:\cache\rustsrc
- - sh src/ci/init_repo.sh . /c/cache/rustsrc
- - set SRC=.
- - set NO_CCACHE=1
- - sh src/ci/run.sh
+ - echo AppVeyor is not used anymore
branches:
only:
}
// This is required for internal lints.
- cmd.arg("-Zunstable-options");
+ if let Some(crate_name) = args.windows(2).find(|a| &*a[0] == "--crate-name") {
+ let crate_name = crate_name[1].to_string_lossy();
+ if crate_name != "rustc_version"
+ && (crate_name.starts_with("rustc")
+ || crate_name.starts_with("syntax")
+ || crate_name == "arena"
+ || crate_name == "fmt_macros")
+ {
+ cmd.arg("-Zunstable-options");
+ if stage != "0" {
+ cmd.arg("-Wrustc::internal");
+ }
+ }
+ }
// Force all crates compiled by this compiler to (a) be unstable and (b)
// allow the `rustc_private` feature to link to other unstable crates
use crate::Build;
// The version number
-pub const CFG_RELEASE_NUM: &str = "1.37.0";
+pub const CFG_RELEASE_NUM: &str = "1.38.0";
pub struct GitInfo {
inner: Option<Info>,
config.incremental = flags.incremental;
config.dry_run = flags.dry_run;
config.keep_stage = flags.keep_stage;
- if let Some(value) = flags.warnings {
+ if let Some(value) = flags.deny_warnings {
config.deny_warnings = value;
}
config.rustc_default_linker = rust.default_linker.clone();
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
- set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
+ set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
pub rustc_error_format: Option<String>,
pub dry_run: bool,
- // true => deny
- pub warnings: Option<bool>,
+ // This overrides the deny-warnings configuation option,
+ // which passes -Dwarnings to the compiler invocations.
+ //
+ // true => deny, false => allow
+ pub deny_warnings: Option<bool>,
}
pub enum Subcommand {
.into_iter()
.map(|p| p.into())
.collect::<Vec<_>>(),
- warnings: matches.opt_str("warnings").map(|v| v == "deny"),
+ deny_warnings: parse_deny_warnings(&matches),
}
}
}
.map(|s| s.to_string())
.collect()
}
+
+fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
+ match matches.opt_str("warnings").as_ref().map(|v| v.as_str()) {
+ Some("deny") => Some(true),
+ Some("allow") => Some(false),
+ Some(value) => {
+ eprintln!(
+ r#"invalid value for --warnings: {:?}, expected "allow" or "deny""#,
+ value,
+ );
+ process::exit(1);
+ },
+ None => None,
+ }
+}
-Subproject commit abf512fc9cc969dcbea69aa15b44586bbeb13c2d
+Subproject commit b5a2b9353c661000378415ecfeb757eb7df42d66
- [Targets](targets/index.md)
- [Built-in Targets](targets/built-in.md)
- [Custom Targets](targets/custom.md)
+- [Profile-guided Optimization](profile-guided-optimization.md)
- [Linker-plugin based LTO](linker-plugin-lto.md)
- [Contributing to `rustc`](contributing.md)
## incremental
This flag allows you to enable incremental compilation.
+
+## profile-generate
+
+This flag allows for creating instrumented binaries that will collect
+profiling data for use with profile-guided optimization (PGO). The flag takes
+an optional argument which is the path to a directory into which the
+instrumented binary will emit the collected data. See the chapter on
+[profile-guided optimization](profile-guided-optimization.html) for more
+information.
+
+## profile-use
+
+This flag specifies the profiling data file to be used for profile-guided
+optimization (PGO). The flag takes a mandatory argument which is the path
+to a valid `.profdata` file. See the chapter on
+[profile-guided optimization](profile-guided-optimization.html) for more
+information.
--- /dev/null
+# Profile Guided Optimization
+
+`rustc` supports doing profile-guided optimization (PGO).
+This chapter describes what PGO is, what it is good for, and how it can be used.
+
+## What Is Profiled-Guided Optimization?
+
+The basic concept of PGO is to collect data about the typical execution of
+a program (e.g. which branches it is likely to take) and then use this data
+to inform optimizations such as inlining, machine-code layout,
+register allocation, etc.
+
+There are different ways of collecting data about a program's execution.
+One is to run the program inside a profiler (such as `perf`) and another
+is to create an instrumented binary, that is, a binary that has data
+collection built into it, and run that.
+The latter usually provides more accurate data and it is also what is
+supported by `rustc`.
+
+## Usage
+
+Generating a PGO-optimized program involves following a workflow with four steps:
+
+1. Compile the program with instrumentation enabled
+ (e.g. `rustc -Cprofile-generate=/tmp/pgo-data main.rs`)
+2. Run the instrumented program (e.g. `./main`) which generates a
+ `default_<id>.profraw` file
+3. Convert the `.profraw` file into a `.profdata` file using
+ LLVM's `llvm-profdata` tool
+4. Compile the program again, this time making use of the profiling data
+ (for example `rustc -Cprofile-use=merged.profdata main.rs`)
+
+An instrumented program will create one or more `.profraw` files, one for each
+instrumented binary. E.g. an instrumented executable that loads two instrumented
+dynamic libraries at runtime will generate three `.profraw` files. Running an
+instrumented binary multiple times, on the other hand, will re-use the
+respective `.profraw` files, updating them in place.
+
+These `.profraw` files have to be post-processed before they can be fed back
+into the compiler. This is done by the `llvm-profdata` tool. This tool
+is most easily installed via
+
+```bash
+rustup component add llvm-tools-preview
+```
+
+Note that installing the `llvm-tools-preview` component won't add
+`llvm-profdata` to the `PATH`. Rather, the tool can be found in:
+
+```bash
+~/.rustup/toolchains/<toolchain>/lib/rustlib/<target-triple>/bin/
+```
+
+Alternatively, an `llvm-profdata` coming with a recent LLVM or Clang
+version usually works too.
+
+The `llvm-profdata` tool merges multiple `.profraw` files into a single
+`.profdata` file that can then be fed back into the compiler via
+`-Cprofile-use`:
+
+```bash
+# STEP 1: Compile the binary with instrumentation
+rustc -Cprofile-generate=/tmp/pgo-data -O ./main.rs
+
+# STEP 2: Run the binary a few times, maybe with common sets of args.
+# Each run will create or update `.profraw` files in /tmp/pgo-data
+./main mydata1.csv
+./main mydata2.csv
+./main mydata3.csv
+
+# STEP 3: Merge and post-process all the `.profraw` files in /tmp/pgo-data
+llvm-profdata merge -o ./merged.profdata /tmp/pgo-data
+
+# STEP 4: Use the merged `.profdata` file during optimization. All `rustc`
+# flags have to be the same.
+rustc -Cprofile-use=./merged.profdata -O ./main.rs
+```
+
+### A Complete Cargo Workflow
+
+Using this feature with Cargo works very similar to using it with `rustc`
+directly. Again, we generate an instrumented binary, run it to produce data,
+merge the data, and feed it back into the compiler. Some things of note:
+
+- We use the `RUSTFLAGS` environment variable in order to pass the PGO compiler
+ flags to the compilation of all crates in the program.
+
+- We pass the `--target` flag to Cargo, which prevents the `RUSTFLAGS`
+ arguments to be passed to Cargo build scripts. We don't want the build
+ scripts to generate a bunch of `.profraw` files.
+
+- We pass `--release` to Cargo because that's where PGO makes the most sense.
+ In theory, PGO can also be done on debug builds but there is little reason
+ to do so.
+
+- It is recommended to use *absolute paths* for the argument of
+ `-Cprofile-generate` and `-Cprofile-use`. Cargo can invoke `rustc` with
+ varying working directories, meaning that `rustc` will not be able to find
+ the supplied `.profdata` file. With absolute paths this is not an issue.
+
+- It is good practice to make sure that there is no left-over profiling data
+ from previous compilation sessions. Just deleting the directory is a simple
+ way of doing so (see `STEP 0` below).
+
+This is what the entire workflow looks like:
+
+```bash
+# STEP 0: Make sure there is no left-over profiling data from previous runs
+rm -rf /tmp/pgo-data
+
+# STEP 1: Build the instrumented binaries
+RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data" \
+ cargo build --release --target=x86_64-unknown-linux-gnu
+
+# STEP 2: Run the instrumented binaries with some typical data
+./target/x86_64-unknown-linux-gnu/release/myprogram mydata1.csv
+./target/x86_64-unknown-linux-gnu/release/myprogram mydata2.csv
+./target/x86_64-unknown-linux-gnu/release/myprogram mydata3.csv
+
+# STEP 3: Merge the `.profraw` files into a `.profdata` file
+llvm-profdata merge -o /tmp/pgo-data/merged.profdata /tmp/pgo-data
+
+# STEP 4: Use the `.profdata` file for guiding optimizations
+RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \
+ cargo build --release --target=x86_64-unknown-linux-gnu
+```
+
+## Further Reading
+
+`rustc`'s PGO support relies entirely on LLVM's implementation of the feature
+and is equivalent to what Clang offers via the `-fprofile-generate` /
+`-fprofile-use` flags. The [Profile Guided Optimization][clang-pgo] section
+in Clang's documentation is therefore an interesting read for anyone who wants
+to use PGO with Rust.
+
+[clang-pgo]: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization
that you must write the `(())` in one sequence without intermediate whitespace
so that rustdoc understands you want an implicit `Result`-returning function.
-As of version 1.37.0, this simplification also works with `Option`s, which can
-be handy to test e.g. iterators or checked arithmetic, for example:
-
-```ignore
-/// ```
-/// let _ = &[].iter().next()?;
-///# Some(())
-/// ```
-```
-
-Note that the result must be a `Some(())` and this has to be written in one go.
-In this case disambiguating the result isn't required.
-
## Documenting macros
Here’s an example of documenting a macro:
--- /dev/null
+# `member_constraints`
+
+The tracking issue for this feature is: [#61977]
+
+[#61977]: https://github.com/rust-lang/rust/issues/61977
+
+------------------------
+
+The `member_constraints` feature gate lets you use `impl Trait` syntax with
+multiple unrelated lifetime parameters.
+
+A simple example is:
+
+```rust
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T {}
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
+ (x, y)
+}
+
+fn main() { }
+```
+
+Without the `member_constraints` feature gate, the above example is an
+error because both `'a` and `'b` appear in the impl Trait bounds, but
+neither outlives the other.
# `slice_patterns`
-The tracking issue for this feature is: [#23121]
+The tracking issue for this feature is: [#62254]
-[#23121]: https://github.com/rust-lang/rust/issues/23121
+[#62254]: https://github.com/rust-lang/rust/issues/62254
------------------------
+++ /dev/null
-# `type_alias_enum_variants`
-
-The tracking issue for this feature is: [#49683]
-
-[#49683]: https://github.com/rust-lang/rust/issues/49683
-
-------------------------
-
-The `type_alias_enum_variants` feature enables the use of variants on type
-aliases that refer to enums, as both a constructor and a pattern. That is,
-it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same
-as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type
-`Enum`).
-
-Note that since `Self` exists as a type alias, this feature also enables the
-use of the syntax `Self::Variant` within an impl block for an enum type.
-
-```rust
-#![feature(type_alias_enum_variants)]
-
-enum Foo {
- Bar(i32),
- Baz { i: i32 },
-}
-
-type Alias = Foo;
-
-fn main() {
- let t = Alias::Bar(0);
- let t = Alias::Baz { i: 0 };
- match t {
- Alias::Bar(_i) => {}
- Alias::Baz { i: _i } => {}
- }
-}
-```
set -ex
-bucket=rust-lang-ci-evalazure
+bucket=rust-lang-ci2
commit=$1
builder=$2
+import gdb
import gdb_rust_pretty_printing
gdb_rust_pretty_printing.register_printers(gdb.current_objfile())
// them from the `#[global_allocator]` attribute if there is one, or uses the
// default implementations in libstd (`__rdl_alloc` etc in `src/libstd/alloc.rs`)
// otherwise.
- #[cfg_attr(bootstrap, allocator)]
- #[cfg_attr(not(bootstrap), rustc_allocator)]
+ #[rustc_allocator]
#[rustc_allocator_nounwind]
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
#[rustc_allocator_nounwind]
/// This conversion does not allocate on the heap and happens in place.
///
/// This is also available via [`From`].
- #[unstable(feature = "box_into_pin", issue = "0")]
+ #[unstable(feature = "box_into_pin", issue = "62370")]
pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>> {
// It's not possible to move or replace the insides of a `Pin<Box<T>>`
// when `T: !Unpin`, so it's safe to pin it directly without any
/// ```
/// let x = Box::new(5);
/// let y = x.clone();
+ ///
+ /// // The value is the same
+ /// assert_eq!(x, y);
+ ///
+ /// // But they are unique objects
+ /// assert_ne!(&*x as *const i32, &*y as *const i32);
/// ```
#[rustfmt::skip]
#[inline]
fn clone(&self) -> Box<T> {
box { (**self).clone() }
}
+
/// Copies `source`'s contents into `self` without creating a new allocation.
///
/// # Examples
/// ```
/// let x = Box::new(5);
/// let mut y = Box::new(10);
+ /// let yp: *const i32 = &*y;
///
/// y.clone_from(&x);
///
- /// assert_eq!(*y, 5);
+ /// // The value is the same
+ /// assert_eq!(x, y);
+ ///
+ /// // And no allocation occurred
+ /// assert_eq!(yp, &*y);
/// ```
#[inline]
fn clone_from(&mut self, source: &Box<T>) {
(**self).nth(n)
}
}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator + Sized> Iterator for Box<I> {
+ fn last(self) -> Option<I::Item> where I: Sized {
+ (*self).last()
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
fn next_back(&mut self) -> Option<I::Item> {
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+
+ #[inline]
+ fn last(self) -> Option<&'a T> {
+ self.iter.last()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
}
// First, we merge `self` and `other` into a sorted sequence in linear time.
- let self_iter = mem::replace(self, BTreeMap::new()).into_iter();
- let other_iter = mem::replace(other, BTreeMap::new()).into_iter();
+ let self_iter = mem::take(self).into_iter();
+ let other_iter = mem::take(other).into_iter();
let iter = MergeIter {
left: self_iter.peekable(),
right: other_iter.peekable(),
fn size_hint(&self) -> (usize, Option<usize>) {
(self.length, Some(self.length))
}
+
+ fn last(mut self) -> Option<(&'a K, &'a V)> {
+ self.next_back()
+ }
}
#[stable(feature = "fused", since = "1.26.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.length, Some(self.length))
}
+
+ fn last(mut self) -> Option<(&'a K, &'a mut V)> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+
+ fn last(mut self) -> Option<&'a K> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+
+ fn last(mut self) -> Option<&'a V> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe { Some(self.next_unchecked()) }
}
}
+
+ fn last(mut self) -> Option<(&'a K, &'a V)> {
+ self.next_back()
+ }
}
#[stable(feature = "map_values_mut", since = "1.10.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+
+ fn last(mut self) -> Option<&'a mut V> {
+ self.next_back()
+ }
}
#[stable(feature = "map_values_mut", since = "1.10.0")]
unsafe { Some(self.next_unchecked()) }
}
}
+
+ fn last(mut self) -> Option<(&'a K, &'a mut V)> {
+ self.next_back()
+ }
}
impl<'a, K, V> RangeMut<'a, K, V> {
/// assert_eq!(keys, [1, 2]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
+ pub fn keys(&self) -> Keys<'_, K, V> {
Keys { inner: self.iter() }
}
/// assert_eq!(values, ["hello", "goodbye"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+ pub fn values(&self) -> Values<'_, K, V> {
Values { inner: self.iter() }
}
Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
}
-fn handle_underfull_node<'a, K, V>(node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>)
- -> UnderflowResult<'a, K, V> {
+fn handle_underfull_node<K, V>(node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>)
+ -> UnderflowResult<'_, K, V> {
let parent = if let Ok(parent) = node.ascend() {
parent
} else {
}
/// Temporarily takes out another, immutable reference to the same node.
- fn reborrow<'a>(&'a self) -> NodeRef<marker::Immut<'a>, K, V, Type> {
+ fn reborrow(&self) -> NodeRef<marker::Immut<'_>, K, V, Type> {
NodeRef {
height: self.height,
node: self.node,
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+ fn last(mut self) -> Option<&'a T> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
fn next(&mut self) -> Option<&'a T> {
self.iter.next().map(|(k, _)| k)
}
+
+ fn last(mut self) -> Option<&'a T> {
+ self.next_back()
+ }
}
#[stable(feature = "btree_range", since = "1.17.0")]
let len = self.len();
assert!(at <= len, "Cannot split off at a nonexistent index");
if at == 0 {
- return mem::replace(self, Self::new());
+ return mem::take(self);
} else if at == len {
return Self::new();
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a T> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a mut T> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
self.tail = self.head - iter.len();
final_res
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a T> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
accum = front.iter_mut().fold(accum, &mut f);
back.iter_mut().fold(accum, &mut f)
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a mut T> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
-#![cfg_attr(bootstrap, feature(custom_attribute))]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(fmt_internals)]
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]
+#![feature(mem_take)]
// Allow testing this library
}
fn clone_into(&self, target: &mut String) {
- let mut b = mem::replace(target, String::new()).into_bytes();
+ let mut b = mem::take(target).into_bytes();
self.as_bytes().clone_into(&mut b);
*target = unsafe { String::from_utf8_unchecked(b) }
}
/// assert_eq!("Hello �World", output);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> {
+ pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
let (first_valid, first_broken) = if let Some(chunk) = iter.next() {
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
+
+ #[inline]
+ fn last(mut self) -> Option<char> {
+ self.next_back()
+ }
}
#[stable(feature = "drain", since = "1.6.0")]
it.next().unwrap();
let vec = it.collect::<Vec<_>>();
assert_eq!(vec, [2, 3]);
- #[cfg(not(miri))] // Miri does not support comparing dangling pointers
assert!(ptr != vec.as_ptr());
}
self.truncate(new_len);
}
}
+
+ /// Consumes and leaks the `Vec`, returning a mutable reference to the contents,
+ /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime
+ /// `'a`. If the type has only static references, or none at all, then this
+ /// may be chosen to be `'static`.
+ ///
+ /// This function is similar to the `leak` function on `Box`.
+ ///
+ /// This function is mainly useful for data that lives for the remainder of
+ /// the program's life. Dropping the returned reference will cause a memory
+ /// leak.
+ ///
+ /// # Examples
+ ///
+ /// Simple usage:
+ ///
+ /// ```
+ /// #![feature(vec_leak)]
+ ///
+ /// fn main() {
+ /// let x = vec![1, 2, 3];
+ /// let static_ref: &'static mut [usize] = Vec::leak(x);
+ /// static_ref[0] += 1;
+ /// assert_eq!(static_ref, &[2, 2, 3]);
+ /// }
+ /// ```
+ #[unstable(feature = "vec_leak", issue = "62195")]
+ #[inline]
+ pub fn leak<'a>(vec: Vec<T>) -> &'a mut [T]
+ where
+ T: 'a // Technically not needed, but kept to be explicit.
+ {
+ Box::leak(vec.into_boxed_slice())
+ }
}
impl<T: Clone> Vec<T> {
test(no_crate_inject, attr(deny(warnings))))]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(core_intrinsics)]
type Item = u8;
fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+ fn last(mut self) -> Option<u8> { self.next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
/// ```
/// // as chars
/// let eastern = '東';
- /// let capitol = '京';
+ /// let capital = '京';
///
/// // both can be represented as three bytes
/// assert_eq!(3, eastern.len_utf8());
- /// assert_eq!(3, capitol.len_utf8());
+ /// assert_eq!(3, capital.len_utf8());
///
/// // as a &str, these two are encoded in UTF-8
/// let tokyo = "東京";
///
- /// let len = eastern.len_utf8() + capitol.len_utf8();
+ /// let len = eastern.len_utf8() + capital.len_utf8();
///
/// // we can see that they take six bytes total...
/// assert_eq!(6, tokyo.len());
///
/// # Examples
///
-/// [`String`] implements `Into<Vec<u8>>`:
+/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:
///
/// In order to express that we want a generic function to take all arguments that can be
/// converted to a specified type `T`, we can use a trait bound of [`Into`]`<T>`.
/// For example: The function `is_hello` takes all arguments that can be converted into a
-/// `Vec<u8>`.
+/// [`Vec`]`<`[`u8`]`>`.
///
/// ```
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
/// [`String`]: ../../std/string/struct.String.html
/// [`From`]: trait.From.html
/// [`Into`]: trait.Into.html
+/// [`Vec`]: ../../std/vec/struct.Vec.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
/// Performs the conversion.
///
/// This is useful when you are doing a type conversion that may
/// trivially succeed but may also need special handling.
-/// For example, there is no way to convert an `i64` into an `i32`
-/// using the [`From`] trait, because an `i64` may contain a value
-/// that an `i32` cannot represent and so the conversion would lose data.
-/// This might be handled by truncating the `i64` to an `i32` (essentially
-/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning
-/// `i32::MAX`, or by some other method. The `From` trait is intended
+/// For example, there is no way to convert an [`i64`] into an [`i32`]
+/// using the [`From`] trait, because an [`i64`] may contain a value
+/// that an [`i32`] cannot represent and so the conversion would lose data.
+/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
+/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
+/// [`i32::MAX`], or by some other method. The [`From`] trait is intended
/// for perfect conversions, so the `TryFrom` trait informs the
/// programmer when a type conversion could go bad and lets them
/// decide how to handle it.
/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
/// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
/// is implemented and cannot fail -- the associated `Error` type for
-/// calling `T::try_from()` on a value of type `T` is `Infallible`.
-/// When the `!` type is stablized `Infallible` and `!` will be
+/// calling `T::try_from()` on a value of type `T` is [`Infallible`].
+/// When the [`!`] type is stablized [`Infallible`] and [`!`] will be
/// equivalent.
///
/// `TryFrom<T>` can be implemented as follows:
///
/// # Examples
///
-/// As described, [`i32`] implements `TryFrom<i64>`:
+/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
///
/// ```
/// use std::convert::TryFrom;
///
/// [`try_from`]: trait.TryFrom.html#tymethod.try_from
/// [`TryInto`]: trait.TryInto.html
+/// [`i32::MAX`]: ../../std/i32/constant.MAX.html
+/// [`!`]: ../../std/primitive.never.html
#[stable(feature = "try_from", since = "1.34.0")]
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
issue = "44930")]
-#[cfg(not(bootstrap))]
impl<'f> VaListImpl<'f> {
/// Advance to the next arg.
#[inline]
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
issue = "44930")]
-#[cfg(not(bootstrap))]
impl<'f> Clone for VaListImpl<'f> {
#[inline]
fn clone(&self) -> Self {
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
issue = "44930")]
-#[cfg(not(bootstrap))]
impl<'f> Drop for VaListImpl<'f> {
fn drop(&mut self) {
// FIXME: this should call `va_end`, but there's no clean way to
extern "rust-intrinsic" {
/// Destroy the arglist `ap` after initialization with `va_start` or
/// `va_copy`.
- #[cfg(not(bootstrap))]
fn va_end(ap: &mut VaListImpl<'_>);
/// Copies the current location of arglist `src` to the arglist `dst`.
- #[cfg(not(bootstrap))]
fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
/// Loads an argument of type `T` from the `va_list` `ap` and increment the
/// argument `ap` points to.
- #[cfg(not(bootstrap))]
fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
}
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
-#[cfg_attr(not(bootstrap), lang = "future_trait")]
+#[lang = "future_trait"]
pub trait Future {
/// The type of value produced on completion.
#[stable(feature = "futures_api", since = "1.36.0")]
/// which is unsafe unless `T` is `Copy`. Also, even if T is
/// `Copy`, an all-zero value may not correspond to any legitimate
/// state for the type in question.
+ #[unstable(feature = "core_intrinsics",
+ reason = "intrinsics are unlikely to ever be stabilized, instead \
+ they should be used through stabilized interfaces \
+ in the rest of the standard library",
+ issue = "0")]
+ #[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUnint instead",
+ since = "1.38.0")]
pub fn init<T>() -> T;
- /// Creates an uninitialized value.
- ///
- /// `uninit` is unsafe because there is no guarantee of what its
- /// contents are. In particular its drop-flag may be set to any
- /// state, which means it may claim either dropped or
- /// undropped. In the general case one must use `ptr::write` to
- /// initialize memory previous set to the result of `uninit`.
- pub fn uninit<T>() -> T;
-
/// Moves a value out of scope without running drop glue.
pub fn forget<T: ?Sized>(_: T);
pub fn fabsf64(x: f64) -> f64;
/// Returns the minimum of two `f32` values.
- #[cfg(not(bootstrap))]
pub fn minnumf32(x: f32, y: f32) -> f32;
/// Returns the minimum of two `f64` values.
- #[cfg(not(bootstrap))]
pub fn minnumf64(x: f64, y: f64) -> f64;
/// Returns the maximum of two `f32` values.
- #[cfg(not(bootstrap))]
pub fn maxnumf32(x: f32, y: f32) -> f32;
/// Returns the maximum of two `f64` values.
- #[cfg(not(bootstrap))]
pub fn maxnumf64(x: f64, y: f64) -> f64;
/// Copies the sign from `y` to `x` for `f32` values.
/// Returns the result of an unchecked addition, resulting in
/// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
- #[cfg(not(bootstrap))]
pub fn unchecked_add<T>(x: T, y: T) -> T;
/// Returns the result of an unchecked substraction, resulting in
/// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
- #[cfg(not(bootstrap))]
pub fn unchecked_sub<T>(x: T, y: T) -> T;
/// Returns the result of an unchecked multiplication, resulting in
/// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
- #[cfg(not(bootstrap))]
pub fn unchecked_mul<T>(x: T, y: T) -> T;
/// Performs rotate left.
}
write_bytes(dst, val, count)
}
-
-// Simple bootstrap implementations of minnum/maxnum for stage0 compilation.
-
-/// Returns the minimum of two `f32` values.
-#[cfg(bootstrap)]
-pub fn minnumf32(x: f32, y: f32) -> f32 {
- // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
- // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
- // is either x or y, canonicalized (this means results might differ among implementations).
- // When either x or y is a signaling NaN, then the result is according to 6.2.
- //
- // Since we do not support sNaN in Rust yet, we do not need to handle them.
- // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
- // multiplying by 1.0. Should switch to the `canonicalize` when it works.
- (if x < y || y != y { x } else { y }) * 1.0
-}
-
-/// Returns the minimum of two `f64` values.
-#[cfg(bootstrap)]
-pub fn minnumf64(x: f64, y: f64) -> f64 {
- // Identical to the `f32` case.
- (if x < y || y != y { x } else { y }) * 1.0
-}
-
-/// Returns the maximum of two `f32` values.
-#[cfg(bootstrap)]
-pub fn maxnumf32(x: f32, y: f32) -> f32 {
- // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
- // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
- // is either x or y, canonicalized (this means results might differ among implementations).
- // When either x or y is a signaling NaN, then the result is according to 6.2.
- //
- // Since we do not support sNaN in Rust yet, we do not need to handle them.
- // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
- // multiplying by 1.0. Should switch to the `canonicalize` when it works.
- (if x < y || x != x { y } else { x }) * 1.0
-}
-
-/// Returns the maximum of two `f64` values.
-#[cfg(bootstrap)]
-pub fn maxnumf64(x: f64, y: f64) -> f64 {
- // Identical to the `f32` case.
- (if x < y || x != x { y } else { x }) * 1.0
-}
-
-/// For bootstrapping, implement unchecked_sub as just wrapping_sub.
-#[cfg(bootstrap)]
-pub unsafe fn unchecked_sub<T>(x: T, y: T) -> T {
- sub_with_overflow(x, y).0
-}
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_fn_union)]
+#![feature(custom_inner_attributes)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
-#![cfg_attr(not(bootstrap), feature(transparent_unions))]
+#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]
#![feature(untagged_unions)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice, maybe_uninit_array)]
#![feature(external_doc)]
+#![feature(mem_take)]
#[prelude_import]
#[allow(unused)]
/// # end: *const T,
/// # phantom: PhantomData<&'a T>,
/// # }
-/// fn borrow_vec<'a, T>(vec: &'a Vec<T>) -> Slice<'a, T> {
+/// fn borrow_vec<T>(vec: &Vec<T>) -> Slice<'_, T> {
/// let ptr = vec.as_ptr();
/// Slice {
/// start: ptr,
#[allow(missing_debug_implementations)]
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[derive(Copy)]
-#[cfg_attr(not(bootstrap), repr(transparent))]
+#[repr(transparent)]
pub union MaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn zeroed<T>() -> T {
- intrinsics::panic_if_uninhabited::<T>();
- intrinsics::init()
+ MaybeUninit::zeroed().assume_init()
}
/// Bypasses Rust's normal memory-initialization checks by pretending to
#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::panic_if_uninhabited::<T>();
- intrinsics::uninit()
+ MaybeUninit::uninit().assume_init()
}
/// Swaps the values at two mutable locations, without deinitializing either one.
/// mem::take(&mut self.buf)
/// }
/// }
+///
+/// let mut buffer = Buffer { buf: vec![0, 1] };
+/// assert_eq!(buffer.buf.len(), 2);
+///
+/// assert_eq!(buffer.get_and_reset(), vec![0, 1]);
+/// assert_eq!(buffer.buf.len(), 0);
/// ```
///
/// [`Clone`]: ../../std/clone/trait.Clone.html
/// struct Buffer<T> { buf: Vec<T> }
///
/// impl<T> Buffer<T> {
-/// fn get_and_reset(&mut self) -> Vec<T> {
+/// fn replace_index(&mut self, i: usize, v: T) -> T {
/// // error: cannot move out of dereference of `&mut`-pointer
-/// let buf = self.buf;
-/// self.buf = Vec::new();
-/// buf
+/// let t = self.buf[i];
+/// self.buf[i] = v;
+/// t
/// }
/// }
/// ```
///
-/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset
-/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
+/// Note that `T` does not necessarily implement [`Clone`], so we can't even clone `self.buf[i]` to
+/// avoid the move. But `replace` can be used to disassociate the original value at that index from
/// `self`, allowing it to be returned:
///
/// ```
///
/// # struct Buffer<T> { buf: Vec<T> }
/// impl<T> Buffer<T> {
-/// fn get_and_reset(&mut self) -> Vec<T> {
-/// mem::replace(&mut self.buf, Vec::new())
+/// fn replace_index(&mut self, i: usize, v: T) -> T {
+/// mem::replace(&mut self.buf[i], v)
/// }
/// }
+///
+/// let mut buffer = Buffer { buf: vec![0, 1] };
+/// assert_eq!(buffer.buf[0], 0);
+///
+/// assert_eq!(buffer.replace_index(0, 2), 0);
+/// assert_eq!(buffer.buf[0], 2);
/// ```
///
/// [`Clone`]: ../../std/clone/trait.Clone.html
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
- #[cfg_attr(not(bootstrap), rustc_nonnull_optimization_guaranteed)]
+ #[rustc_nonnull_optimization_guaranteed]
pub struct $Ty($Int);
}
/// impl Index<Side> for Balance {
/// type Output = Weight;
///
-/// fn index<'a>(&'a self, index: Side) -> &'a Self::Output {
+/// fn index(&self, index: Side) -> &Self::Output {
/// println!("Accessing {:?}-side of balance immutably", index);
/// match index {
/// Side::Left => &self.left,
/// }
///
/// impl IndexMut<Side> for Balance {
-/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Self::Output {
+/// fn index_mut(&mut self, index: Side) -> &mut Self::Output {
/// println!("Accessing {:?}-side of balance mutably", index);
/// match index {
/// Side::Left => &mut self.left,
#[inline]
#[stable(feature = "option_entry", since = "1.20.0")]
pub fn get_or_insert(&mut self, v: T) -> &mut T {
- match *self {
- None => *self = Some(v),
- _ => (),
- }
-
- match *self {
- Some(ref mut v) => v,
- None => unsafe { hint::unreachable_unchecked() },
- }
+ self.get_or_insert_with(|| v)
}
/// Inserts a value computed from `f` into the option if it is [`None`], then
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn take(&mut self) -> Option<T> {
- mem::replace(self, None)
+ mem::take(self)
}
/// Replaces the actual value in the option by the value given in parameter,
/// as the compiler doesn't need to prove that it's sound to elide the
/// copy.
///
+/// Unaligned values cannot be dropped in place, they must be copied to an aligned
+/// location first using [`ptr::read_unaligned`].
+///
/// [`ptr::read`]: ../ptr/fn.read.html
+/// [`ptr::read_unaligned`]: ../ptr/fn.read_unaligned.html
///
/// # Safety
///
///
/// * `to_drop` must be [valid] for reads.
///
-/// * `to_drop` must be properly aligned. See the example below for how to drop
-/// an unaligned pointer.
+/// * `to_drop` must be properly aligned.
///
/// Additionally, if `T` is not [`Copy`], using the pointed-to value after
/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
/// assert!(weak.upgrade().is_none());
/// ```
///
-/// Unaligned values cannot be dropped in place, they must be copied to an aligned
-/// location first:
-/// ```
-/// use std::ptr;
-/// use std::mem::{self, MaybeUninit};
-///
-/// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
-/// let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
-/// ptr::copy(to_drop, copy.as_mut_ptr(), 1);
-/// drop(copy.assume_init());
-/// }
-///
-/// #[repr(packed, C)]
-/// struct Packed {
-/// _padding: u8,
-/// unaligned: Vec<i32>,
-/// }
-///
-/// let mut p = Packed { _padding: 0, unaligned: vec![42] };
-/// unsafe {
-/// drop_after_copy(&mut p.unaligned as *mut _);
-/// mem::forget(p);
-/// }
-/// ```
-///
/// Notice that the compiler performs this copy automatically when dropping packed structs,
/// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
/// manually.
/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
/// [valid]: ../ptr/index.html#safety
///
-/// # Examples
+/// ## On `packed` structs
///
-/// Access members of a packed struct by reference:
+/// It is currently impossible to create raw pointers to unaligned fields
+/// of a packed struct.
///
-/// ```
-/// use std::ptr;
+/// Attempting to create a raw pointer to an `unaligned` struct field with
+/// an expression such as `&packed.unaligned as *const FieldType` creates an
+/// intermediate unaligned reference before converting that to a raw pointer.
+/// That this reference is temporary and immediately cast is inconsequential
+/// as the compiler always expects references to be properly aligned.
+/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
+/// *undefined behavior* in your program.
///
+/// An example of what not to do and how this relates to `read_unaligned` is:
+///
+/// ```no_run
/// #[repr(packed, C)]
/// struct Packed {
/// _padding: u8,
/// unaligned: u32,
/// }
///
-/// let x = Packed {
+/// let packed = Packed {
/// _padding: 0x00,
/// unaligned: 0x01020304,
/// };
///
/// let v = unsafe {
-/// // Take the address of a 32-bit integer which is not aligned.
-/// // This must be done as a raw pointer; unaligned references are invalid.
-/// let unaligned = &x.unaligned as *const u32;
-///
-/// // Dereferencing normally will emit an aligned load instruction,
-/// // causing undefined behavior.
-/// // let v = *unaligned; // ERROR
+/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
+/// let unaligned =
+/// // A temporary unaligned reference is created here which results in
+/// // undefined behavior regardless of whether the reference is used or not.
+/// &packed.unaligned
+/// // Casting to a raw pointer doesn't help; the mistake already happened.
+/// as *const u32;
///
-/// // Instead, use `read_unaligned` to read improperly aligned values.
-/// let v = ptr::read_unaligned(unaligned);
+/// let v = std::ptr::read_unaligned(unaligned);
///
/// v
/// };
-///
-/// // Accessing unaligned values directly is safe.
-/// assert!(x.unaligned == v);
/// ```
+///
+/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
+// FIXME: Update docs based on outcome of RFC #2582 and friends.
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
///
/// [valid]: ../ptr/index.html#safety
///
-/// # Examples
+/// ## On `packed` structs
///
-/// Access fields in a packed struct:
+/// It is currently impossible to create raw pointers to unaligned fields
+/// of a packed struct.
///
-/// ```
-/// use std::{mem, ptr};
+/// Attempting to create a raw pointer to an `unaligned` struct field with
+/// an expression such as `&packed.unaligned as *const FieldType` creates an
+/// intermediate unaligned reference before converting that to a raw pointer.
+/// That this reference is temporary and immediately cast is inconsequential
+/// as the compiler always expects references to be properly aligned.
+/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
+/// *undefined behavior* in your program.
///
+/// An example of what not to do and how this relates to `write_unaligned` is:
+///
+/// ```no_run
/// #[repr(packed, C)]
-/// #[derive(Default)]
/// struct Packed {
/// _padding: u8,
/// unaligned: u32,
/// }
///
/// let v = 0x01020304;
-/// let mut x: Packed = unsafe { mem::zeroed() };
-///
-/// unsafe {
-/// // Take a reference to a 32-bit integer which is not aligned.
-/// let unaligned = &mut x.unaligned as *mut u32;
+/// let mut packed: Packed = unsafe { std::mem::zeroed() };
///
-/// // Dereferencing normally will emit an aligned store instruction,
-/// // causing undefined behavior because the pointer is not aligned.
-/// // *unaligned = v; // ERROR
+/// let v = unsafe {
+/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
+/// let unaligned =
+/// // A temporary unaligned reference is created here which results in
+/// // undefined behavior regardless of whether the reference is used or not.
+/// &mut packed.unaligned
+/// // Casting to a raw pointer doesn't help; the mistake already happened.
+/// as *mut u32;
///
-/// // Instead, use `write_unaligned` to write improperly aligned values.
-/// ptr::write_unaligned(unaligned, v);
-/// }
+/// std::ptr::write_unaligned(unaligned, v);
///
-/// // Accessing unaligned values directly is safe.
-/// assert!(x.unaligned == v);
+/// v
+/// };
/// ```
+///
+/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
+// FIXME: Update docs based on outcome of RFC #2582 and friends.
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
-#[cfg_attr(not(bootstrap), rustc_nonnull_optimization_guaranteed)]
+#[rustc_nonnull_optimization_guaranteed]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
Some(snd)
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let len = self.len();
+ if n >= len {
+ self.v = &[];
+ None
+ } else {
+ let start = (len - 1 - n) * self.chunk_size;
+ let end = start + self.chunk_size;
+ let nth_back = &self.v[start..end];
+ self.v = &self.v[..start];
+ Some(nth_back)
+ }
+ }
}
#[stable(feature = "chunks_exact", since = "1.31.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a str> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
///
/// # Text directionality
///
- /// A string is a sequence of bytes. 'Left' in this context means the first
- /// position of that byte string; for a language like Arabic or Hebrew
- /// which are 'right to left' rather than 'left to right', this will be
- /// the _right_ side, not the left.
+ /// A string is a sequence of bytes. `start` in this context means the first
+ /// position of that byte string; for a left-to-right language like English or
+ /// Russian, this will be left side, and for right-to-left languages like
+ /// like Arabic or Hebrew, this will be the right side.
///
/// # Examples
///
///
/// # Text directionality
///
- /// A string is a sequence of bytes. 'Right' in this context means the last
- /// position of that byte string; for a language like Arabic or Hebrew
- /// which are 'right to left' rather than 'left to right', this will be
- /// the _left_ side, not the right.
+ /// A string is a sequence of bytes. `end` in this context means the last
+ /// position of that byte string; for a left-to-right language like English or
+ /// Russian, this will be right side, and for right-to-left languages like
+ /// like Arabic or Hebrew, this will be the left side.
///
/// # Examples
///
///
/// # Text directionality
///
- /// A string is a sequence of bytes. `start` in this context means the first
- /// position of that byte string; for a left-to-right language like English or
- /// Russian, this will be left side, and for right-to-left languages like
- /// like Arabic or Hebrew, this will be the right side.
+ /// A string is a sequence of bytes. 'Left' in this context means the first
+ /// position of that byte string; for a language like Arabic or Hebrew
+ /// which are 'right to left' rather than 'left to right', this will be
+ /// the _right_ side, not the left.
///
/// # Examples
///
///
/// # Text directionality
///
- /// A string is a sequence of bytes. `end` in this context means the last
- /// position of that byte string; for a left-to-right language like English or
- /// Russian, this will be right side, and for right-to-left languages like
- /// like Arabic or Hebrew, this will be the left side.
+ /// A string is a sequence of bytes. 'Right' in this context means the last
+ /// position of that byte string; for a language like Arabic or Hebrew
+ /// which are 'right to left' rather than 'left to right', this will be
+ /// the _left_ side, not the right.
///
/// # Examples
///
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a str> {
+ self.next_back()
+ }
}
#[stable(feature = "split_whitespace", since = "1.1.0")]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
+
+ #[inline]
+ fn last(mut self) -> Option<&'a str> {
+ self.next_back()
+ }
}
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
stringify!($what), b);
}
}
- )*
+ )+
}};
($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
}
mod num;
#[test]
-#[cfg(not(miri))] // Miri cannot print pointers
fn test_format_flags() {
// No residual flags left by pointer formatting
let p = "".as_ptr();
}
#[test]
-#[cfg(not(miri))] // Miri cannot print pointers
fn test_pointer_formats_data_pointer() {
let b: &[u8] = b"";
let s: &str = "";
macro_rules! search_asserts {
($haystack:expr, $needle:expr, $testname:expr, [$($func:ident),*], $result:expr) => {
let mut searcher = $needle.into_searcher($haystack);
- let arr = [$( Step::from(searcher.$func()) ),+];
+ let arr = [$( Step::from(searcher.$func()) ),*];
assert_eq!(&arr[..], &$result, $testname);
}
}
#[test]
#[allow(warnings)]
-#[cfg(not(miri))] // Miri cannot hash pointers
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
// ABI, or even point to an actual executable code, because the function itself is never invoked.
#[no_mangle]
}
#[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn align_offset_zst() {
// For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
// all, because no amount of elements will align the pointer.
}
#[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn align_offset_stride1() {
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
// number of bytes.
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_chunks_exact_nth_back() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.chunks_exact(2);
+ assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[0, 1]);
+ assert_eq!(c.next(), None);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c2 = v2.chunks_exact(3);
+ assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]);
+ assert_eq!(c2.next(), None);
+ assert_eq!(c2.next_back(), None);
+
+ let v3: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c3 = v3.chunks_exact(10);
+ assert_eq!(c3.nth_back(0), None);
+}
+
#[test]
fn test_chunks_exact_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
}
#[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn test_align_to_simple() {
let bytes = [1u8, 2, 3, 4, 5, 6, 7];
let (prefix, aligned, suffix) = unsafe { bytes.align_to::<u16>() };
}
#[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
fn test_align_to_non_trivial() {
#[repr(align(8))] struct U64(u64, u64);
#[repr(align(8))] struct U64U64U32(u64, u64, u32);
test(attr(deny(warnings))))]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(nll)]
}
pub(super) fn take(&mut self) -> Self {
- mem::replace(self, Self::default())
+ mem::take(self)
}
pub(super) fn extend_from_slice(&mut self, xs: &[T]) {
}
/// Sets the value in `self` to `value` while running `f`.
- pub fn set<'a, R>(&self, value: <T as ApplyL<'a>>::Out, f: impl FnOnce() -> R) -> R {
+ pub fn set<R>(&self, value: <T as ApplyL<'_>>::Out, f: impl FnOnce() -> R) -> R {
self.replace(value, |_| f())
}
}
#![feature(extern_types)]
#![feature(in_band_lifetimes)]
#![feature(optin_builtin_traits)]
+#![feature(mem_take)]
#![feature(non_exhaustive)]
#![feature(specialization)]
use crate::cfg::*;
use crate::middle::region;
use rustc_data_structures::graph::implementation as graph;
-use syntax::ptr::P;
use crate::ty::{self, TyCtxt};
use crate::hir::{self, PatKind};
use crate::hir::def_id::DefId;
+use crate::hir::ptr::P;
struct CFGBuilder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
break_index: CFGIndex, // where to go on a `break`
}
-pub fn construct<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body) -> CFG {
+pub fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
let mut graph = graph::Graph::new();
let entry = graph.add_node(CFGNodeData::Entry);
pub type CFGEdge = graph::Edge<CFGEdgeData>;
impl CFG {
- pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body) -> CFG {
+ pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
construct::construct(tcx, body)
}
///
/// ```
/// fn type_of_item(..., item: &hir::Item) -> Ty<'tcx> {
- /// let item_def_id = ccx.tcx.hir().local_def_id(it.id);
+ /// let item_def_id = ccx.tcx.hir().local_def_id(it.hir_id);
/// ccx.tcx.item_types.memoized(item_def_id, || {
/// ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // (*)
/// compute_type_of_item(ccx, item)
//
// This method will only load queries that will end up in the disk cache.
// Other queries will not be executed.
- pub fn exec_cache_promotions<'tcx>(&self, tcx: TyCtxt<'tcx>) {
+ pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) {
let data = self.data.as_ref().unwrap();
for prev_index in data.colors.values.indices() {
match data.colors.get(prev_index) {
/// Checks any attribute.
fn check_attributes(&self, item: &hir::Item, target: Target) {
if target == Target::Fn || target == Target::Const {
- self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(item.hir_id));
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name(sym::target_feature)) {
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
.span_label(item.span, "not a function")
}
}
-fn check_mod_attrs<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
&mut CheckAttrVisitor { tcx }.as_deep_visitor()
use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use crate::hir::def::{Res, DefKind, PartialRes, PerNS};
use crate::hir::{GenericArg, ConstArg};
+use crate::hir::ptr::P;
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
ELIDED_LIFETIMES_IN_PATHS};
use crate::middle::cstore::CrateStore;
use syntax::errors;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::print::pprust;
-use syntax::ptr::P;
use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned};
use syntax::source_map::CompilerDesugaringKind::IfTemporary;
use syntax::std_inject;
},
);
- lowered_generics.params = lowered_generics
+ let mut lowered_params: Vec<_> = lowered_generics
.params
.into_iter()
.chain(in_band_defs)
// unsorted generic parameters at the moment, so we make sure
// that they're ordered correctly here for now. (When we chain
// the `in_band_defs`, we might make the order unsorted.)
- lowered_generics.params.sort_by_key(|param| {
+ lowered_params.sort_by_key(|param| {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
hir::GenericParamKind::Type { .. } => ParamKindOrd::Type,
}
});
+ lowered_generics.params = lowered_params.into();
+
(lowered_generics, res)
}
&mut self,
capture_clause: CaptureBy,
closure_node_id: NodeId,
- ret_ty: Option<&Ty>,
+ ret_ty: Option<syntax::ptr::P<Ty>>,
span: Span,
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
) -> hir::ExprKind {
let capture_clause = self.lower_capture_clause(capture_clause);
let output = match ret_ty {
- Some(ty) => FunctionRetTy::Ty(P(ty.clone())),
+ Some(ty) => FunctionRetTy::Ty(ty),
None => FunctionRetTy::Default(span),
};
let ast_decl = FnDecl {
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
- let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
- let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
+ let catch_scopes = mem::take(&mut self.catch_scopes);
+ let loop_scopes = mem::take(&mut self.loop_scopes);
let ret = f(self);
self.catch_scopes = catch_scopes;
self.loop_scopes = loop_scopes;
// ::std::future::Future<future_params>
let future_path =
- self.std_path(span, &[sym::future, sym::Future], Some(future_params), false);
+ P(self.std_path(span, &[sym::future, sym::Future], Some(future_params), false));
hir::GenericBound::Trait(
hir::PolyTraitRef {
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext<'_>) -> hir::TraitRef {
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
- hir::QPath::Resolved(None, path) => path.and_then(|path| path),
+ hir::QPath::Resolved(None, path) => path,
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
};
hir::TraitRef {
hir::Item {
hir_id: new_id,
ident,
- attrs: attrs.clone(),
+ attrs: attrs.into_iter().cloned().collect(),
node: item,
vis,
span,
hir::Item {
hir_id: new_hir_id,
ident,
- attrs: attrs.clone(),
+ attrs: attrs.into_iter().cloned().collect(),
node: item,
vis,
span: use_tree.span,
// `|x: u8| future_from_generator(|| -> X { ... })`.
let body_id = this.lower_fn_body(&outer_decl, |this| {
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
- Some(&**ty)
+ Some(ty.clone())
} else { None };
let async_body = this.make_async_expr(
capture_clause, closure_id, async_ret_ty, body.span,
let principal = hir::PolyTraitRef {
bound_generic_params: hir::HirVec::new(),
trait_ref: hir::TraitRef {
- path: path.and_then(|path| path),
+ path,
hir_ref_id: hir_id,
},
span,
None
}
- // FIXME(@ljedrz): replace the NodeId variant
#[inline]
pub fn as_local_hir_id(&self, def_id: DefId) -> Option<hir::HirId> {
if def_id.krate == LOCAL_CRATE {
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter};
-pub fn check_crate<'hir>(hir_map: &hir::map::Map<'hir>) {
+pub fn check_crate(hir_map: &hir::map::Map<'_>) {
hir_map.dep_graph.assert_ignored();
let errors = Lock::new(Vec::new());
par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
- hir_map.visit_item_likes_in_module(hir_map.local_def_id(*module_id), &mut OuterVisitor {
+ let local_def_id = hir_map.local_def_id_from_node_id(*module_id);
+ hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor {
hir_map,
errors: &errors,
});
hir_id: HirId,
walk: F) {
assert!(self.owner_def_index.is_none());
- let owner_def_index = self.hir_map.local_def_id_from_hir_id(hir_id).index;
+ let owner_def_index = self.hir_map.local_def_id(hir_id).index;
self.owner_def_index = Some(owner_def_index);
walk(self);
use crate::util::nodemap::FxHashMap;
use crate::util::common::time;
-use std::io;
use std::result::Result::Err;
use crate::ty::query::Providers;
}
}
- pub fn krate<'hir>(&'hir self) -> &'hir Crate {
+ pub fn krate(&self) -> &Crate {
self.dep_graph.read(DepNode::new_no_params(DepKind::Krate));
&self.krate
}
/// This is used internally in the dependency tracking system.
/// Use the `krate` method to ensure your dependency on the
/// crate is tracked.
- pub fn untracked_krate<'hir>(&'hir self) -> &'hir Crate {
+ pub fn untracked_krate(&self) -> &Crate {
&self.krate
}
}
}
pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
- self.opt_local_def_id_from_hir_id(id).map(|def_id| {
+ self.opt_local_def_id(id).map(|def_id| {
self.def_path(def_id)
})
}
}
#[inline]
- pub fn local_def_id(&self, node: NodeId) -> DefId {
- self.opt_local_def_id(node).unwrap_or_else(|| {
+ pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId {
+ self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| {
let hir_id = self.node_to_hir_id(node);
- bug!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
+ bug!("local_def_id_from_node_id: no entry for `{}`, which has a map of `{:?}`",
node, self.find_entry(hir_id))
})
}
- // FIXME(@ljedrz): replace the `NodeId` variant.
#[inline]
- pub fn local_def_id_from_hir_id(&self, hir_id: HirId) -> DefId {
- self.opt_local_def_id_from_hir_id(hir_id).unwrap_or_else(|| {
- bug!("local_def_id_from_hir_id: no entry for `{:?}`, which has a map of `{:?}`",
+ pub fn local_def_id(&self, hir_id: HirId) -> DefId {
+ self.opt_local_def_id(hir_id).unwrap_or_else(|| {
+ bug!("local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
hir_id, self.find_entry(hir_id))
})
}
- // FIXME(@ljedrz): replace the `NodeId` variant.
#[inline]
- pub fn opt_local_def_id_from_hir_id(&self, hir_id: HirId) -> Option<DefId> {
+ pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<DefId> {
let node_id = self.hir_to_node_id(hir_id);
self.definitions.opt_local_def_id(node_id)
}
#[inline]
- pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
+ pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option<DefId> {
self.definitions.opt_local_def_id(node)
}
self.definitions.as_local_node_id(def_id)
}
- // FIXME(@ljedrz): replace the `NodeId` variant.
#[inline]
pub fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
self.definitions.as_local_hir_id(def_id)
}
pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
- self.local_def_id_from_hir_id(self.body_owner(id))
+ self.local_def_id(self.body_owner(id))
}
/// Given a `HirId`, returns the `BodyId` associated with it,
/// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
/// module parent is in this map.
pub fn get_module_parent(&self, id: HirId) -> DefId {
- self.local_def_id_from_hir_id(self.get_module_parent_node(id))
+ self.local_def_id(self.get_module_parent_node(id))
}
/// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
}
pub fn get_parent_did(&self, id: HirId) -> DefId {
- self.local_def_id_from_hir_id(self.get_parent_item(id))
+ self.local_def_id(self.get_parent_item(id))
}
pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
// If `id` itself is a mod named `m` with parent `p`, then
// returns `Some(id, m, p)`. If `id` has no mod in its parent
// chain, then returns `None`.
- fn find_first_mod_parent<'a>(map: &'a Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
+ fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
loop {
if let Node::Item(item) = map.find(id)? {
if item_is_mod(&item) {
/// Identical to the `PpAnn` implementation for `hir::Crate`,
/// except it avoids creating a dependency on the whole crate.
impl<'hir> print::PpAnn for Map<'hir> {
- fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) -> io::Result<()> {
+ fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) {
match nested {
Nested::Item(id) => state.print_item(self.expect_item(id.id)),
Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
}
impl<'a> print::State<'a> {
- pub fn print_node(&mut self, node: Node<'_>) -> io::Result<()> {
+ pub fn print_node(&mut self, node: Node<'_>) {
match node {
Node::Item(a) => self.print_item(&a),
Node::ForeignItem(a) => self.print_foreign_item(&a),
use syntax::print::pprust::PrintState;
// containing cbox, will be closed by print-block at }
- self.cbox(print::indent_unit)?;
+ self.cbox(print::indent_unit);
// head-ibox, will be closed by print-block after {
- self.ibox(0)?;
+ self.ibox(0);
self.print_block(&a)
}
Node::Lifetime(a) => self.print_lifetime(&a),
// the user-friendly path, otherwise fall back to stringifying DefPath.
crate::ty::tls::with_opt(|tcx| {
if let Some(tcx) = tcx {
- let def_id = map.local_def_id_from_hir_id(id);
+ let def_id = map.local_def_id(id);
tcx.def_path_str(def_id)
} else if let Some(path) = map.def_path_from_hir_id(id) {
path.data.into_iter().map(|elem| {
use crate::hir::def::{Res, DefKind};
use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
+use crate::hir::ptr::P;
use crate::util::nodemap::{NodeMap, FxHashSet};
use crate::mir::mono::Linkage;
use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
use syntax::attr::{InlineAttr, OptimizeAttr};
use syntax::ext::hygiene::SyntaxContext;
-use syntax::ptr::P;
use syntax::symbol::{Symbol, kw};
use syntax::tokenstream::TokenStream;
use syntax::util::parser::ExprPrecedence;
pub mod map;
pub mod pat_util;
pub mod print;
+pub mod ptr;
pub mod upvars;
/// Uniquely identifies a node in the HIR of the current crate. It is
pub span: Span,
}
+// NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
+// it needs to be `Clone` and use plain `Vec<T>` instead of `HirVec<T>`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct InlineAsm {
pub asm: Symbol,
pub asm_str_style: StrStyle,
- pub outputs: HirVec<InlineAsmOutput>,
- pub inputs: HirVec<Symbol>,
- pub clobbers: HirVec<Symbol>,
+ pub outputs: Vec<InlineAsmOutput>,
+ pub inputs: Vec<Symbol>,
+ pub clobbers: Vec<Symbol>,
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect,
/// within the resolution map.
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct TraitRef {
- pub path: Path,
+ pub path: P<Path>,
// Don't hash the ref_id. It is tracked via the thing it is used to access
#[stable_hasher(ignore)]
pub hir_ref_id: HirId,
use syntax::print::pp::{self, Breaks};
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
use syntax::print::pprust::{self, PrintState};
-use syntax::ptr::P;
use syntax::symbol::kw;
use syntax::util::parser::{self, AssocOp, Fixity};
use syntax_pos::{self, BytePos, FileName};
use crate::hir;
use crate::hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd};
use crate::hir::{GenericParam, GenericParamKind, GenericArg};
+use crate::hir::ptr::P;
use std::borrow::Cow;
use std::cell::Cell;
-use std::io::{self, Write, Read};
+use std::io::Read;
use std::vec;
pub enum AnnNode<'a> {
}
pub trait PpAnn {
- fn nested(&self, _state: &mut State<'_>, _nested: Nested) -> io::Result<()> {
- Ok(())
+ fn nested(&self, _state: &mut State<'_>, _nested: Nested) {
}
- fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> {
- Ok(())
+ fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {
}
- fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> {
- Ok(())
+ fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {
}
fn try_fetch_item(&self, _: hir::HirId) -> Option<&hir::Item> {
None
fn try_fetch_item(&self, item: hir::HirId) -> Option<&hir::Item> {
Some(self.item(item))
}
- fn nested(&self, state: &mut State<'_>, nested: Nested) -> io::Result<()> {
+ fn nested(&self, state: &mut State<'_>, nested: Nested) {
match nested {
Nested::Item(id) => state.print_item(self.item(id.id)),
Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
#[allow(non_upper_case_globals)]
pub const indent_unit: usize = 4;
-#[allow(non_upper_case_globals)]
-pub const default_columns: usize = 78;
-
-
/// Requires you to pass an input filename and reader so that
/// it can scan the input text for comments to copy forward.
pub fn print_crate<'a>(cm: &'a SourceMap,
krate: &hir::Crate,
filename: FileName,
input: &mut dyn Read,
- out: Box<dyn Write + 'a>,
+ out: &'a mut String,
ann: &'a dyn PpAnn)
- -> io::Result<()> {
+ {
let mut s = State::new_from_input(cm, sess, filename, input, out, ann);
// When printing the AST, we sometimes need to inject `#[no_std]` here.
// Since you can't compile the HIR, it's not necessary.
- s.print_mod(&krate.module, &krate.attrs)?;
- s.print_remaining_comments()?;
+ s.print_mod(&krate.module, &krate.attrs);
+ s.print_remaining_comments();
s.s.eof()
}
sess: &ParseSess,
filename: FileName,
input: &mut dyn Read,
- out: Box<dyn Write + 'a>,
+ out: &'a mut String,
ann: &'a dyn PpAnn)
-> State<'a> {
let comments = comments::gather_comments(sess, filename, input);
}
pub fn new(cm: &'a SourceMap,
- out: Box<dyn Write + 'a>,
+ out: &'a mut String,
ann: &'a dyn PpAnn,
comments: Option<Vec<comments::Comment>>)
-> State<'a> {
State {
- s: pp::mk_printer(out, default_columns),
+ s: pp::mk_printer(out),
cm: Some(cm),
comments,
cur_cmnt: 0,
}
pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
- where F: FnOnce(&mut State<'_>) -> io::Result<()>
+ where F: FnOnce(&mut State<'_>)
{
- let mut wr = Vec::new();
+ let mut wr = String::new();
{
let mut printer = State {
- s: pp::mk_printer(Box::new(&mut wr), default_columns),
+ s: pp::mk_printer(&mut wr),
cm: None,
comments: None,
cur_cmnt: 0,
boxes: Vec::new(),
ann,
};
- f(&mut printer).unwrap();
- printer.s.eof().unwrap();
+ f(&mut printer);
+ printer.s.eof();
}
- String::from_utf8(wr).unwrap()
+ wr
}
pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility, w: S) -> String {
to_string(NO_ANN, |s| {
- s.print_visibility(vis)?;
+ s.print_visibility(vis);
s.s.word(w)
})
}
impl<'a> State<'a> {
- pub fn cbox(&mut self, u: usize) -> io::Result<()> {
+ pub fn cbox(&mut self, u: usize) {
self.boxes.push(pp::Breaks::Consistent);
- self.s.cbox(u)
+ self.s.cbox(u);
}
- pub fn nbsp(&mut self) -> io::Result<()> {
+ pub fn nbsp(&mut self) {
self.s.word(" ")
}
- pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
- self.s.word(w)?;
+ pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) {
+ self.s.word(w);
self.nbsp()
}
- pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
+ pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
let w = w.into();
// outer-box is consistent
- self.cbox(indent_unit)?;
+ self.cbox(indent_unit);
// head-box is inconsistent
- self.ibox(w.len() + 1)?;
+ self.ibox(w.len() + 1);
// keyword that starts the head
if !w.is_empty() {
- self.word_nbsp(w)?;
+ self.word_nbsp(w);
}
- Ok(())
}
- pub fn bopen(&mut self) -> io::Result<()> {
- self.s.word("{")?;
- self.end() // close the head-box
+ pub fn bopen(&mut self) {
+ self.s.word("{");
+ self.end(); // close the head-box
}
- pub fn bclose_(&mut self, span: syntax_pos::Span, indented: usize) -> io::Result<()> {
+ pub fn bclose_(&mut self, span: syntax_pos::Span, indented: usize) {
self.bclose_maybe_open(span, indented, true)
}
span: syntax_pos::Span,
indented: usize,
close_box: bool)
- -> io::Result<()> {
- self.maybe_print_comment(span.hi())?;
- self.break_offset_if_not_bol(1, -(indented as isize))?;
- self.s.word("}")?;
+ {
+ self.maybe_print_comment(span.hi());
+ self.break_offset_if_not_bol(1, -(indented as isize));
+ self.s.word("}");
if close_box {
- self.end()?; // close the outer-box
+ self.end(); // close the outer-box
}
- Ok(())
}
- pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> {
+ pub fn bclose(&mut self, span: syntax_pos::Span) {
self.bclose_(span, indent_unit)
}
}
}
- pub fn space_if_not_bol(&mut self) -> io::Result<()> {
+ pub fn space_if_not_bol(&mut self) {
if !self.is_bol() {
- self.s.space()?;
+ self.s.space();
}
- Ok(())
}
- pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> {
+ pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
if !self.is_bol() {
self.s.break_offset(n, off)
} else {
// break into the previous hardbreak.
self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off));
}
- Ok(())
}
}
// Synthesizes a comment that was not textually present in the original source
// file.
- pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
- self.s.word("/*")?;
- self.s.space()?;
- self.s.word(text)?;
- self.s.space()?;
+ pub fn synth_comment(&mut self, text: String) {
+ self.s.word("/*");
+ self.s.space();
+ self.s.word(text);
+ self.s.space();
self.s.word("*/")
}
elts: &[T],
mut op: F,
mut get_span: G)
- -> io::Result<()>
- where F: FnMut(&mut State<'_>, &T) -> io::Result<()>,
+ where F: FnMut(&mut State<'_>, &T),
G: FnMut(&T) -> syntax_pos::Span
{
- self.rbox(0, b)?;
+ self.rbox(0, b);
let len = elts.len();
let mut i = 0;
for elt in elts {
- self.maybe_print_comment(get_span(elt).hi())?;
- op(self, elt)?;
+ self.maybe_print_comment(get_span(elt).hi());
+ op(self, elt);
i += 1;
if i < len {
- self.s.word(",")?;
- self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()))?;
- self.space_if_not_bol()?;
+ self.s.word(",");
+ self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()));
+ self.space_if_not_bol();
}
}
- self.end()
+ self.end();
}
- pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr]) -> io::Result<()> {
+ pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr]) {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
}
- pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
- self.print_inner_attributes(attrs)?;
+ pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) {
+ self.print_inner_attributes(attrs);
for &item_id in &_mod.item_ids {
- self.ann.nested(self, Nested::Item(item_id))?;
+ self.ann.nested(self, Nested::Item(item_id));
}
- Ok(())
}
pub fn print_foreign_mod(&mut self,
nmod: &hir::ForeignMod,
attrs: &[ast::Attribute])
- -> io::Result<()> {
- self.print_inner_attributes(attrs)?;
+ {
+ self.print_inner_attributes(attrs);
for item in &nmod.items {
- self.print_foreign_item(item)?;
+ self.print_foreign_item(item);
}
- Ok(())
}
- pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
+ pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) {
if !lifetime.is_elided() {
- self.print_lifetime(lifetime)?;
- self.nbsp()?;
+ self.print_lifetime(lifetime);
+ self.nbsp();
}
- Ok(())
}
- pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
- self.maybe_print_comment(ty.span.lo())?;
- self.ibox(0)?;
+ pub fn print_type(&mut self, ty: &hir::Ty) {
+ self.maybe_print_comment(ty.span.lo());
+ self.ibox(0);
match ty.node {
hir::TyKind::Slice(ref ty) => {
- self.s.word("[")?;
- self.print_type(&ty)?;
- self.s.word("]")?;
+ self.s.word("[");
+ self.print_type(&ty);
+ self.s.word("]");
}
hir::TyKind::Ptr(ref mt) => {
- self.s.word("*")?;
+ self.s.word("*");
match mt.mutbl {
- hir::MutMutable => self.word_nbsp("mut")?,
- hir::MutImmutable => self.word_nbsp("const")?,
+ hir::MutMutable => self.word_nbsp("mut"),
+ hir::MutImmutable => self.word_nbsp("const"),
}
- self.print_type(&mt.ty)?;
+ self.print_type(&mt.ty);
}
hir::TyKind::Rptr(ref lifetime, ref mt) => {
- self.s.word("&")?;
- self.print_opt_lifetime(lifetime)?;
- self.print_mt(mt)?;
+ self.s.word("&");
+ self.print_opt_lifetime(lifetime);
+ self.print_mt(mt);
}
hir::TyKind::Never => {
- self.s.word("!")?;
+ self.s.word("!");
},
hir::TyKind::Tup(ref elts) => {
- self.popen()?;
- self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?;
+ self.popen();
+ self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty));
if elts.len() == 1 {
- self.s.word(",")?;
+ self.s.word(",");
}
- self.pclose()?;
+ self.pclose();
}
hir::TyKind::BareFn(ref f) => {
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params,
- &f.arg_names[..])?;
+ &f.arg_names[..]);
}
hir::TyKind::Def(..) => {},
hir::TyKind::Path(ref qpath) => {
- self.print_qpath(qpath, false)?
+ self.print_qpath(qpath, false)
}
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
let mut first = true;
if first {
first = false;
} else {
- self.nbsp()?;
- self.word_space("+")?;
+ self.nbsp();
+ self.word_space("+");
}
- self.print_poly_trait_ref(bound)?;
+ self.print_poly_trait_ref(bound);
}
if !lifetime.is_elided() {
- self.nbsp()?;
- self.word_space("+")?;
- self.print_lifetime(lifetime)?;
+ self.nbsp();
+ self.word_space("+");
+ self.print_lifetime(lifetime);
}
}
hir::TyKind::Array(ref ty, ref length) => {
- self.s.word("[")?;
- self.print_type(&ty)?;
- self.s.word("; ")?;
- self.print_anon_const(length)?;
- self.s.word("]")?;
+ self.s.word("[");
+ self.print_type(&ty);
+ self.s.word("; ");
+ self.print_anon_const(length);
+ self.s.word("]");
}
hir::TyKind::Typeof(ref e) => {
- self.s.word("typeof(")?;
- self.print_anon_const(e)?;
- self.s.word(")")?;
+ self.s.word("typeof(");
+ self.print_anon_const(e);
+ self.s.word(")");
}
hir::TyKind::Infer => {
- self.s.word("_")?;
+ self.s.word("_");
}
hir::TyKind::Err => {
- self.popen()?;
- self.s.word("/*ERROR*/")?;
- self.pclose()?;
+ self.popen();
+ self.s.word("/*ERROR*/");
+ self.pclose();
}
hir::TyKind::CVarArgs(_) => {
- self.s.word("...")?;
+ self.s.word("...");
}
}
self.end()
}
- pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> {
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(item.span.lo())?;
- self.print_outer_attributes(&item.attrs)?;
+ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) {
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(item.span.lo());
+ self.print_outer_attributes(&item.attrs);
match item.node {
hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => {
- self.head("")?;
+ self.head("");
self.print_fn(decl,
hir::FnHeader {
unsafety: hir::Unsafety::Normal,
generics,
&item.vis,
arg_names,
- None)?;
- self.end()?; // end head-ibox
- self.s.word(";")?;
+ None);
+ self.end(); // end head-ibox
+ self.s.word(";");
self.end() // end the outer fn box
}
hir::ForeignItemKind::Static(ref t, m) => {
- self.head(visibility_qualified(&item.vis, "static"))?;
+ self.head(visibility_qualified(&item.vis, "static"));
if m == hir::MutMutable {
- self.word_space("mut")?;
+ self.word_space("mut");
}
- self.print_ident(item.ident)?;
- self.word_space(":")?;
- self.print_type(&t)?;
- self.s.word(";")?;
- self.end()?; // end the head-ibox
+ self.print_ident(item.ident);
+ self.word_space(":");
+ self.print_type(&t);
+ self.s.word(";");
+ self.end(); // end the head-ibox
self.end() // end the outer cbox
}
hir::ForeignItemKind::Type => {
- self.head(visibility_qualified(&item.vis, "type"))?;
- self.print_ident(item.ident)?;
- self.s.word(";")?;
- self.end()?; // end the head-ibox
+ self.head(visibility_qualified(&item.vis, "type"));
+ self.print_ident(item.ident);
+ self.s.word(";");
+ self.end(); // end the head-ibox
self.end() // end the outer cbox
}
}
ty: &hir::Ty,
default: Option<hir::BodyId>,
vis: &hir::Visibility)
- -> io::Result<()> {
- self.s.word(visibility_qualified(vis, ""))?;
- self.word_space("const")?;
- self.print_ident(ident)?;
- self.word_space(":")?;
- self.print_type(ty)?;
+ {
+ self.s.word(visibility_qualified(vis, ""));
+ self.word_space("const");
+ self.print_ident(ident);
+ self.word_space(":");
+ self.print_type(ty);
if let Some(expr) = default {
- self.s.space()?;
- self.word_space("=")?;
- self.ann.nested(self, Nested::Body(expr))?;
+ self.s.space();
+ self.word_space("=");
+ self.ann.nested(self, Nested::Body(expr));
}
self.s.word(";")
}
ident: ast::Ident,
bounds: Option<&hir::GenericBounds>,
ty: Option<&hir::Ty>)
- -> io::Result<()> {
- self.word_space("type")?;
- self.print_ident(ident)?;
+ {
+ self.word_space("type");
+ self.print_ident(ident);
if let Some(bounds) = bounds {
- self.print_bounds(":", bounds)?;
+ self.print_bounds(":", bounds);
}
if let Some(ty) = ty {
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(ty)?;
+ self.s.space();
+ self.word_space("=");
+ self.print_type(ty);
}
self.s.word(";")
}
/// Pretty-print an item
- pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(item.span.lo())?;
- self.print_outer_attributes(&item.attrs)?;
- self.ann.pre(self, AnnNode::Item(item))?;
+ pub fn print_item(&mut self, item: &hir::Item) {
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(item.span.lo());
+ self.print_outer_attributes(&item.attrs);
+ self.ann.pre(self, AnnNode::Item(item));
match item.node {
hir::ItemKind::ExternCrate(orig_name) => {
- self.head(visibility_qualified(&item.vis, "extern crate"))?;
+ self.head(visibility_qualified(&item.vis, "extern crate"));
if let Some(orig_name) = orig_name {
- self.print_name(orig_name)?;
- self.s.space()?;
- self.s.word("as")?;
- self.s.space()?;
+ self.print_name(orig_name);
+ self.s.space();
+ self.s.word("as");
+ self.s.space();
}
- self.print_ident(item.ident)?;
- self.s.word(";")?;
- self.end()?; // end inner head-block
- self.end()?; // end outer head-block
+ self.print_ident(item.ident);
+ self.s.word(";");
+ self.end(); // end inner head-block
+ self.end(); // end outer head-block
}
hir::ItemKind::Use(ref path, kind) => {
- self.head(visibility_qualified(&item.vis, "use"))?;
- self.print_path(path, false)?;
+ self.head(visibility_qualified(&item.vis, "use"));
+ self.print_path(path, false);
match kind {
hir::UseKind::Single => {
if path.segments.last().unwrap().ident != item.ident {
- self.s.space()?;
- self.word_space("as")?;
- self.print_ident(item.ident)?;
+ self.s.space();
+ self.word_space("as");
+ self.print_ident(item.ident);
}
- self.s.word(";")?;
+ self.s.word(";");
}
- hir::UseKind::Glob => self.s.word("::*;")?,
- hir::UseKind::ListStem => self.s.word("::{};")?
+ hir::UseKind::Glob => self.s.word("::*;"),
+ hir::UseKind::ListStem => self.s.word("::{};")
}
- self.end()?; // end inner head-block
- self.end()?; // end outer head-block
+ self.end(); // end inner head-block
+ self.end(); // end outer head-block
}
hir::ItemKind::Static(ref ty, m, expr) => {
- self.head(visibility_qualified(&item.vis, "static"))?;
+ self.head(visibility_qualified(&item.vis, "static"));
if m == hir::MutMutable {
- self.word_space("mut")?;
+ self.word_space("mut");
}
- self.print_ident(item.ident)?;
- self.word_space(":")?;
- self.print_type(&ty)?;
- self.s.space()?;
- self.end()?; // end the head-ibox
+ self.print_ident(item.ident);
+ self.word_space(":");
+ self.print_type(&ty);
+ self.s.space();
+ self.end(); // end the head-ibox
- self.word_space("=")?;
- self.ann.nested(self, Nested::Body(expr))?;
- self.s.word(";")?;
- self.end()?; // end the outer cbox
+ self.word_space("=");
+ self.ann.nested(self, Nested::Body(expr));
+ self.s.word(";");
+ self.end(); // end the outer cbox
}
hir::ItemKind::Const(ref ty, expr) => {
- self.head(visibility_qualified(&item.vis, "const"))?;
- self.print_ident(item.ident)?;
- self.word_space(":")?;
- self.print_type(&ty)?;
- self.s.space()?;
- self.end()?; // end the head-ibox
-
- self.word_space("=")?;
- self.ann.nested(self, Nested::Body(expr))?;
- self.s.word(";")?;
- self.end()?; // end the outer cbox
+ self.head(visibility_qualified(&item.vis, "const"));
+ self.print_ident(item.ident);
+ self.word_space(":");
+ self.print_type(&ty);
+ self.s.space();
+ self.end(); // end the head-ibox
+
+ self.word_space("=");
+ self.ann.nested(self, Nested::Body(expr));
+ self.s.word(";");
+ self.end(); // end the outer cbox
}
hir::ItemKind::Fn(ref decl, header, ref param_names, body) => {
- self.head("")?;
+ self.head("");
self.print_fn(decl,
header,
Some(item.ident.name),
param_names,
&item.vis,
&[],
- Some(body))?;
- self.s.word(" ")?;
- self.end()?; // need to close a box
- self.end()?; // need to close a box
- self.ann.nested(self, Nested::Body(body))?;
+ Some(body));
+ self.s.word(" ");
+ self.end(); // need to close a box
+ self.end(); // need to close a box
+ self.ann.nested(self, Nested::Body(body));
}
hir::ItemKind::Mod(ref _mod) => {
- self.head(visibility_qualified(&item.vis, "mod"))?;
- self.print_ident(item.ident)?;
- self.nbsp()?;
- self.bopen()?;
- self.print_mod(_mod, &item.attrs)?;
- self.bclose(item.span)?;
+ self.head(visibility_qualified(&item.vis, "mod"));
+ self.print_ident(item.ident);
+ self.nbsp();
+ self.bopen();
+ self.print_mod(_mod, &item.attrs);
+ self.bclose(item.span);
}
hir::ItemKind::ForeignMod(ref nmod) => {
- self.head("extern")?;
- self.word_nbsp(nmod.abi.to_string())?;
- self.bopen()?;
- self.print_foreign_mod(nmod, &item.attrs)?;
- self.bclose(item.span)?;
+ self.head("extern");
+ self.word_nbsp(nmod.abi.to_string());
+ self.bopen();
+ self.print_foreign_mod(nmod, &item.attrs);
+ self.bclose(item.span);
}
hir::ItemKind::GlobalAsm(ref ga) => {
- self.head(visibility_qualified(&item.vis, "global asm"))?;
- self.s.word(ga.asm.as_str().to_string())?;
- self.end()?
+ self.head(visibility_qualified(&item.vis, "global asm"));
+ self.s.word(ga.asm.as_str().to_string());
+ self.end()
}
hir::ItemKind::Ty(ref ty, ref generics) => {
- self.head(visibility_qualified(&item.vis, "type"))?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
- self.end()?; // end the inner ibox
-
- self.print_where_clause(&generics.where_clause)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(&ty)?;
- self.s.word(";")?;
- self.end()?; // end the outer ibox
+ self.head(visibility_qualified(&item.vis, "type"));
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
+ self.end(); // end the inner ibox
+
+ self.print_where_clause(&generics.where_clause);
+ self.s.space();
+ self.word_space("=");
+ self.print_type(&ty);
+ self.s.word(";");
+ self.end(); // end the outer ibox
}
hir::ItemKind::Existential(ref exist) => {
- self.head(visibility_qualified(&item.vis, "existential type"))?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&exist.generics.params)?;
- self.end()?; // end the inner ibox
+ self.head(visibility_qualified(&item.vis, "existential type"));
+ self.print_ident(item.ident);
+ self.print_generic_params(&exist.generics.params);
+ self.end(); // end the inner ibox
- self.print_where_clause(&exist.generics.where_clause)?;
- self.s.space()?;
+ self.print_where_clause(&exist.generics.where_clause);
+ self.s.space();
let mut real_bounds = Vec::with_capacity(exist.bounds.len());
for b in exist.bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
- self.s.space()?;
- self.word_space("for ?")?;
- self.print_trait_ref(&ptr.trait_ref)?;
+ self.s.space();
+ self.word_space("for ?");
+ self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b);
}
}
- self.print_bounds(":", real_bounds)?;
- self.s.word(";")?;
- self.end()?; // end the outer ibox
+ self.print_bounds(":", real_bounds);
+ self.s.word(";");
+ self.end(); // end the outer ibox
}
hir::ItemKind::Enum(ref enum_definition, ref params) => {
self.print_enum_def(enum_definition, params, item.ident.name, item.span,
- &item.vis)?;
+ &item.vis);
}
hir::ItemKind::Struct(ref struct_def, ref generics) => {
- self.head(visibility_qualified(&item.vis, "struct"))?;
- self.print_struct(struct_def, generics, item.ident.name, item.span, true)?;
+ self.head(visibility_qualified(&item.vis, "struct"));
+ self.print_struct(struct_def, generics, item.ident.name, item.span, true);
}
hir::ItemKind::Union(ref struct_def, ref generics) => {
- self.head(visibility_qualified(&item.vis, "union"))?;
- self.print_struct(struct_def, generics, item.ident.name, item.span, true)?;
+ self.head(visibility_qualified(&item.vis, "union"));
+ self.print_struct(struct_def, generics, item.ident.name, item.span, true);
}
hir::ItemKind::Impl(unsafety,
polarity,
ref opt_trait,
ref ty,
ref impl_items) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_defaultness(defaultness)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("impl")?;
+ self.head("");
+ self.print_visibility(&item.vis);
+ self.print_defaultness(defaultness);
+ self.print_unsafety(unsafety);
+ self.word_nbsp("impl");
if !generics.params.is_empty() {
- self.print_generic_params(&generics.params)?;
- self.s.space()?;
+ self.print_generic_params(&generics.params);
+ self.s.space();
}
if let hir::ImplPolarity::Negative = polarity {
- self.s.word("!")?;
+ self.s.word("!");
}
if let Some(ref t) = opt_trait {
- self.print_trait_ref(t)?;
- self.s.space()?;
- self.word_space("for")?;
+ self.print_trait_ref(t);
+ self.s.space();
+ self.word_space("for");
}
- self.print_type(&ty)?;
- self.print_where_clause(&generics.where_clause)?;
+ self.print_type(&ty);
+ self.print_where_clause(&generics.where_clause);
- self.s.space()?;
- self.bopen()?;
- self.print_inner_attributes(&item.attrs)?;
+ self.s.space();
+ self.bopen();
+ self.print_inner_attributes(&item.attrs);
for impl_item in impl_items {
- self.ann.nested(self, Nested::ImplItem(impl_item.id))?;
+ self.ann.nested(self, Nested::ImplItem(impl_item.id));
}
- self.bclose(item.span)?;
+ self.bclose(item.span);
}
hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_is_auto(is_auto)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("trait")?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
+ self.head("");
+ self.print_visibility(&item.vis);
+ self.print_is_auto(is_auto);
+ self.print_unsafety(unsafety);
+ self.word_nbsp("trait");
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
- self.s.space()?;
- self.word_space("for ?")?;
- self.print_trait_ref(&ptr.trait_ref)?;
+ self.s.space();
+ self.word_space("for ?");
+ self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b);
}
}
- self.print_bounds(":", real_bounds)?;
- self.print_where_clause(&generics.where_clause)?;
- self.s.word(" ")?;
- self.bopen()?;
+ self.print_bounds(":", real_bounds);
+ self.print_where_clause(&generics.where_clause);
+ self.s.word(" ");
+ self.bopen();
for trait_item in trait_items {
- self.ann.nested(self, Nested::TraitItem(trait_item.id))?;
+ self.ann.nested(self, Nested::TraitItem(trait_item.id));
}
- self.bclose(item.span)?;
+ self.bclose(item.span);
}
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.word_nbsp("trait")?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
+ self.head("");
+ self.print_visibility(&item.vis);
+ self.word_nbsp("trait");
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
- self.s.space()?;
- self.word_space("for ?")?;
- self.print_trait_ref(&ptr.trait_ref)?;
+ self.s.space();
+ self.word_space("for ?");
+ self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b);
}
}
- self.nbsp()?;
- self.print_bounds("=", real_bounds)?;
- self.print_where_clause(&generics.where_clause)?;
- self.s.word(";")?;
+ self.nbsp();
+ self.print_bounds("=", real_bounds);
+ self.print_where_clause(&generics.where_clause);
+ self.s.word(";");
}
}
self.ann.post(self, AnnNode::Item(item))
}
- pub fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
+ pub fn print_trait_ref(&mut self, t: &hir::TraitRef) {
self.print_path(&t.path, false)
}
fn print_formal_generic_params(
&mut self,
generic_params: &[hir::GenericParam]
- ) -> io::Result<()> {
+ ) {
if !generic_params.is_empty() {
- self.s.word("for")?;
- self.print_generic_params(generic_params)?;
- self.nbsp()?;
+ self.s.word("for");
+ self.print_generic_params(generic_params);
+ self.nbsp();
}
- Ok(())
}
- fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> {
- self.print_formal_generic_params(&t.bound_generic_params)?;
+ fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) {
+ self.print_formal_generic_params(&t.bound_generic_params);
self.print_trait_ref(&t.trait_ref)
}
name: ast::Name,
span: syntax_pos::Span,
visibility: &hir::Visibility)
- -> io::Result<()> {
- self.head(visibility_qualified(visibility, "enum"))?;
- self.print_name(name)?;
- self.print_generic_params(&generics.params)?;
- self.print_where_clause(&generics.where_clause)?;
- self.s.space()?;
+ {
+ self.head(visibility_qualified(visibility, "enum"));
+ self.print_name(name);
+ self.print_generic_params(&generics.params);
+ self.print_where_clause(&generics.where_clause);
+ self.s.space();
self.print_variants(&enum_definition.variants, span)
}
pub fn print_variants(&mut self,
variants: &[hir::Variant],
span: syntax_pos::Span)
- -> io::Result<()> {
- self.bopen()?;
+ {
+ self.bopen();
for v in variants {
- self.space_if_not_bol()?;
- self.maybe_print_comment(v.span.lo())?;
- self.print_outer_attributes(&v.node.attrs)?;
- self.ibox(indent_unit)?;
- self.print_variant(v)?;
- self.s.word(",")?;
- self.end()?;
- self.maybe_print_trailing_comment(v.span, None)?;
+ self.space_if_not_bol();
+ self.maybe_print_comment(v.span.lo());
+ self.print_outer_attributes(&v.node.attrs);
+ self.ibox(indent_unit);
+ self.print_variant(v);
+ self.s.word(",");
+ self.end();
+ self.maybe_print_trailing_comment(v.span, None);
}
self.bclose(span)
}
- pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
+ pub fn print_visibility(&mut self, vis: &hir::Visibility) {
match vis.node {
- hir::VisibilityKind::Public => self.word_nbsp("pub")?,
- hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
- hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
+ hir::VisibilityKind::Public => self.word_nbsp("pub"),
+ hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"),
+ hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"),
hir::VisibilityKind::Restricted { ref path, .. } => {
- self.s.word("pub(")?;
+ self.s.word("pub(");
if path.segments.len() == 1 &&
path.segments[0].ident.name == kw::Super {
// Special case: `super` can print like `pub(super)`.
- self.s.word("super")?;
+ self.s.word("super");
} else {
// Everything else requires `in` at present.
- self.word_nbsp("in")?;
- self.print_path(path, false)?;
+ self.word_nbsp("in");
+ self.print_path(path, false);
}
- self.word_nbsp(")")?;
+ self.word_nbsp(")");
}
hir::VisibilityKind::Inherited => ()
}
-
- Ok(())
}
- pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
+ pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) {
match defaultness {
- hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
+ hir::Defaultness::Default { .. } => self.word_nbsp("default"),
hir::Defaultness::Final => (),
}
- Ok(())
}
pub fn print_struct(&mut self,
name: ast::Name,
span: syntax_pos::Span,
print_finalizer: bool)
- -> io::Result<()> {
- self.print_name(name)?;
- self.print_generic_params(&generics.params)?;
+ {
+ self.print_name(name);
+ self.print_generic_params(&generics.params);
match struct_def {
hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
if let hir::VariantData::Tuple(..) = struct_def {
- self.popen()?;
+ self.popen();
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
- s.maybe_print_comment(field.span.lo())?;
- s.print_outer_attributes(&field.attrs)?;
- s.print_visibility(&field.vis)?;
+ s.maybe_print_comment(field.span.lo());
+ s.print_outer_attributes(&field.attrs);
+ s.print_visibility(&field.vis);
s.print_type(&field.ty)
- })?;
- self.pclose()?;
+ });
+ self.pclose();
}
- self.print_where_clause(&generics.where_clause)?;
+ self.print_where_clause(&generics.where_clause);
if print_finalizer {
- self.s.word(";")?;
+ self.s.word(";");
}
- self.end()?;
+ self.end();
self.end() // close the outer-box
}
hir::VariantData::Struct(..) => {
- self.print_where_clause(&generics.where_clause)?;
- self.nbsp()?;
- self.bopen()?;
- self.hardbreak_if_not_bol()?;
+ self.print_where_clause(&generics.where_clause);
+ self.nbsp();
+ self.bopen();
+ self.hardbreak_if_not_bol();
for field in struct_def.fields() {
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(field.span.lo())?;
- self.print_outer_attributes(&field.attrs)?;
- self.print_visibility(&field.vis)?;
- self.print_ident(field.ident)?;
- self.word_nbsp(":")?;
- self.print_type(&field.ty)?;
- self.s.word(",")?;
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(field.span.lo());
+ self.print_outer_attributes(&field.attrs);
+ self.print_visibility(&field.vis);
+ self.print_ident(field.ident);
+ self.word_nbsp(":");
+ self.print_type(&field.ty);
+ self.s.word(",");
}
self.bclose(span)
}
}
- pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
- self.head("")?;
+ pub fn print_variant(&mut self, v: &hir::Variant) {
+ self.head("");
let generics = hir::Generics::empty();
- self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false)?;
+ self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false);
if let Some(ref d) = v.node.disr_expr {
- self.s.space()?;
- self.word_space("=")?;
- self.print_anon_const(d)?;
+ self.s.space();
+ self.word_space("=");
+ self.print_anon_const(d);
}
- Ok(())
}
pub fn print_method_sig(&mut self,
ident: ast::Ident,
vis: &hir::Visibility,
arg_names: &[ast::Ident],
body_id: Option<hir::BodyId>)
- -> io::Result<()> {
+ {
self.print_fn(&m.decl,
m.header,
Some(ident.name),
body_id)
}
- pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
- self.ann.pre(self, AnnNode::SubItem(ti.hir_id))?;
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(ti.span.lo())?;
- self.print_outer_attributes(&ti.attrs)?;
+ pub fn print_trait_item(&mut self, ti: &hir::TraitItem) {
+ self.ann.pre(self, AnnNode::SubItem(ti.hir_id));
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(ti.span.lo());
+ self.print_outer_attributes(&ti.attrs);
match ti.node {
hir::TraitItemKind::Const(ref ty, default) => {
let vis = Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited };
- self.print_associated_const(ti.ident, &ty, default, &vis)?;
+ self.print_associated_const(ti.ident, &ty, default, &vis);
}
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
let vis = Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited };
- self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None)?;
- self.s.word(";")?;
+ self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None);
+ self.s.word(";");
}
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
let vis = Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited };
- self.head("")?;
- self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body))?;
- self.nbsp()?;
- self.end()?; // need to close a box
- self.end()?; // need to close a box
- self.ann.nested(self, Nested::Body(body))?;
+ self.head("");
+ self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body));
+ self.nbsp();
+ self.end(); // need to close a box
+ self.end(); // need to close a box
+ self.ann.nested(self, Nested::Body(body));
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
self.print_associated_type(ti.ident,
Some(bounds),
- default.as_ref().map(|ty| &**ty))?;
+ default.as_ref().map(|ty| &**ty));
}
}
self.ann.post(self, AnnNode::SubItem(ti.hir_id))
}
- pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
- self.ann.pre(self, AnnNode::SubItem(ii.hir_id))?;
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(ii.span.lo())?;
- self.print_outer_attributes(&ii.attrs)?;
- self.print_defaultness(ii.defaultness)?;
+ pub fn print_impl_item(&mut self, ii: &hir::ImplItem) {
+ self.ann.pre(self, AnnNode::SubItem(ii.hir_id));
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(ii.span.lo());
+ self.print_outer_attributes(&ii.attrs);
+ self.print_defaultness(ii.defaultness);
match ii.node {
hir::ImplItemKind::Const(ref ty, expr) => {
- self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis)?;
+ self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis);
}
hir::ImplItemKind::Method(ref sig, body) => {
- self.head("")?;
- self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body))?;
- self.nbsp()?;
- self.end()?; // need to close a box
- self.end()?; // need to close a box
- self.ann.nested(self, Nested::Body(body))?;
+ self.head("");
+ self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body));
+ self.nbsp();
+ self.end(); // need to close a box
+ self.end(); // need to close a box
+ self.ann.nested(self, Nested::Body(body));
}
hir::ImplItemKind::Type(ref ty) => {
- self.print_associated_type(ii.ident, None, Some(ty))?;
+ self.print_associated_type(ii.ident, None, Some(ty));
}
hir::ImplItemKind::Existential(ref bounds) => {
- self.word_space("existential")?;
- self.print_associated_type(ii.ident, Some(bounds), None)?;
+ self.word_space("existential");
+ self.print_associated_type(ii.ident, Some(bounds), None);
}
}
self.ann.post(self, AnnNode::SubItem(ii.hir_id))
pub fn print_local(
&mut self,
init: Option<&hir::Expr>,
- decl: impl Fn(&mut Self) -> io::Result<()>
- ) -> io::Result<()> {
- self.space_if_not_bol()?;
- self.ibox(indent_unit)?;
- self.word_nbsp("let")?;
+ decl: impl Fn(&mut Self)
+ ) {
+ self.space_if_not_bol();
+ self.ibox(indent_unit);
+ self.word_nbsp("let");
- self.ibox(indent_unit)?;
- decl(self)?;
- self.end()?;
+ self.ibox(indent_unit);
+ decl(self);
+ self.end();
if let Some(ref init) = init {
- self.nbsp()?;
- self.word_space("=")?;
- self.print_expr(&init)?;
+ self.nbsp();
+ self.word_space("=");
+ self.print_expr(&init);
}
self.end()
}
- pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
- self.maybe_print_comment(st.span.lo())?;
+ pub fn print_stmt(&mut self, st: &hir::Stmt) {
+ self.maybe_print_comment(st.span.lo());
match st.node {
hir::StmtKind::Local(ref loc) => {
- self.print_local(loc.init.deref(), |this| this.print_local_decl(&loc))?;
+ self.print_local(loc.init.deref(), |this| this.print_local_decl(&loc));
}
hir::StmtKind::Item(item) => {
- self.ann.nested(self, Nested::Item(item))?
+ self.ann.nested(self, Nested::Item(item))
}
hir::StmtKind::Expr(ref expr) => {
- self.space_if_not_bol()?;
- self.print_expr(&expr)?;
+ self.space_if_not_bol();
+ self.print_expr(&expr);
}
hir::StmtKind::Semi(ref expr) => {
- self.space_if_not_bol()?;
- self.print_expr(&expr)?;
- self.s.word(";")?;
+ self.space_if_not_bol();
+ self.print_expr(&expr);
+ self.s.word(";");
}
}
if stmt_ends_with_semi(&st.node) {
- self.s.word(";")?;
+ self.s.word(";");
}
self.maybe_print_trailing_comment(st.span, None)
}
- pub fn print_block(&mut self, blk: &hir::Block) -> io::Result<()> {
+ pub fn print_block(&mut self, blk: &hir::Block) {
self.print_block_with_attrs(blk, &[])
}
- pub fn print_block_unclosed(&mut self, blk: &hir::Block) -> io::Result<()> {
+ pub fn print_block_unclosed(&mut self, blk: &hir::Block) {
self.print_block_unclosed_indent(blk, indent_unit)
}
pub fn print_block_unclosed_indent(&mut self,
blk: &hir::Block,
indented: usize)
- -> io::Result<()> {
+ {
self.print_block_maybe_unclosed(blk, indented, &[], false)
}
pub fn print_block_with_attrs(&mut self,
blk: &hir::Block,
attrs: &[ast::Attribute])
- -> io::Result<()> {
+ {
self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
}
indented: usize,
attrs: &[ast::Attribute],
close_box: bool)
- -> io::Result<()> {
+ {
match blk.rules {
- hir::UnsafeBlock(..) => self.word_space("unsafe")?,
- hir::PushUnsafeBlock(..) => self.word_space("push_unsafe")?,
- hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?,
+ hir::UnsafeBlock(..) => self.word_space("unsafe"),
+ hir::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
+ hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
hir::DefaultBlock => (),
}
- self.maybe_print_comment(blk.span.lo())?;
- self.ann.pre(self, AnnNode::Block(blk))?;
- self.bopen()?;
+ self.maybe_print_comment(blk.span.lo());
+ self.ann.pre(self, AnnNode::Block(blk));
+ self.bopen();
- self.print_inner_attributes(attrs)?;
+ self.print_inner_attributes(attrs);
for st in &blk.stmts {
- self.print_stmt(st)?;
+ self.print_stmt(st);
}
if let Some(ref expr) = blk.expr {
- self.space_if_not_bol()?;
- self.print_expr(&expr)?;
- self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?;
+ self.space_if_not_bol();
+ self.print_expr(&expr);
+ self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
}
- self.bclose_maybe_open(blk.span, indented, close_box)?;
+ self.bclose_maybe_open(blk.span, indented, close_box);
self.ann.post(self, AnnNode::Block(blk))
}
- pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> {
+ pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
self.ann.nested(self, Nested::Body(constant.body))
}
- fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
- self.popen()?;
- self.commasep_exprs(Inconsistent, args)?;
+ fn print_call_post(&mut self, args: &[hir::Expr]) {
+ self.popen();
+ self.commasep_exprs(Inconsistent, args);
self.pclose()
}
- pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) -> io::Result<()> {
+ pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) {
let needs_par = expr.precedence().order() < prec;
if needs_par {
- self.popen()?;
+ self.popen();
}
- self.print_expr(expr)?;
+ self.print_expr(expr);
if needs_par {
- self.pclose()?;
+ self.pclose();
}
- Ok(())
}
/// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
/// `if cond { ... }`.
- pub fn print_expr_as_cond(&mut self, expr: &hir::Expr) -> io::Result<()> {
+ pub fn print_expr_as_cond(&mut self, expr: &hir::Expr) {
let needs_par = match expr.node {
// These cases need parens due to the parse error observed in #26461: `if return {}`
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
};
if needs_par {
- self.popen()?;
+ self.popen();
}
- self.print_expr(expr)?;
+ self.print_expr(expr);
if needs_par {
- self.pclose()?;
+ self.pclose();
}
- Ok(())
}
- fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> {
- self.ibox(indent_unit)?;
- self.s.word("[")?;
- self.commasep_exprs(Inconsistent, exprs)?;
- self.s.word("]")?;
+ fn print_expr_vec(&mut self, exprs: &[hir::Expr]) {
+ self.ibox(indent_unit);
+ self.s.word("[");
+ self.commasep_exprs(Inconsistent, exprs);
+ self.s.word("]");
self.end()
}
- fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::AnonConst) -> io::Result<()> {
- self.ibox(indent_unit)?;
- self.s.word("[")?;
- self.print_expr(element)?;
- self.word_space(";")?;
- self.print_anon_const(count)?;
- self.s.word("]")?;
+ fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::AnonConst) {
+ self.ibox(indent_unit);
+ self.s.word("[");
+ self.print_expr(element);
+ self.word_space(";");
+ self.print_anon_const(count);
+ self.s.word("]");
self.end()
}
qpath: &hir::QPath,
fields: &[hir::Field],
wth: &Option<P<hir::Expr>>)
- -> io::Result<()> {
- self.print_qpath(qpath, true)?;
- self.s.word("{")?;
+ {
+ self.print_qpath(qpath, true);
+ self.s.word("{");
self.commasep_cmnt(Consistent,
&fields[..],
|s, field| {
- s.ibox(indent_unit)?;
+ s.ibox(indent_unit);
if !field.is_shorthand {
- s.print_ident(field.ident)?;
- s.word_space(":")?;
+ s.print_ident(field.ident);
+ s.word_space(":");
}
- s.print_expr(&field.expr)?;
+ s.print_expr(&field.expr);
s.end()
},
- |f| f.span)?;
+ |f| f.span);
match *wth {
Some(ref expr) => {
- self.ibox(indent_unit)?;
+ self.ibox(indent_unit);
if !fields.is_empty() {
- self.s.word(",")?;
- self.s.space()?;
+ self.s.word(",");
+ self.s.space();
}
- self.s.word("..")?;
- self.print_expr(&expr)?;
- self.end()?;
+ self.s.word("..");
+ self.print_expr(&expr);
+ self.end();
}
_ => if !fields.is_empty() {
- self.s.word(",")?
+ self.s.word(",")
},
}
- self.s.word("}")?;
- Ok(())
+ self.s.word("}");
}
- fn print_expr_tup(&mut self, exprs: &[hir::Expr]) -> io::Result<()> {
- self.popen()?;
- self.commasep_exprs(Inconsistent, exprs)?;
+ fn print_expr_tup(&mut self, exprs: &[hir::Expr]) {
+ self.popen();
+ self.commasep_exprs(Inconsistent, exprs);
if exprs.len() == 1 {
- self.s.word(",")?;
+ self.s.word(",");
}
self.pclose()
}
- fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) -> io::Result<()> {
+ fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) {
let prec =
match func.node {
hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
_ => parser::PREC_POSTFIX,
};
- self.print_expr_maybe_paren(func, prec)?;
+ self.print_expr_maybe_paren(func, prec);
self.print_call_post(args)
}
fn print_expr_method_call(&mut self,
segment: &hir::PathSegment,
args: &[hir::Expr])
- -> io::Result<()> {
+ {
let base_args = &args[1..];
- self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
- self.s.word(".")?;
- self.print_ident(segment.ident)?;
+ self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
+ self.s.word(".");
+ self.print_ident(segment.ident);
let generic_args = segment.generic_args();
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
- self.print_generic_args(generic_args, segment.infer_args, true)?;
+ self.print_generic_args(generic_args, segment.infer_args, true);
}
self.print_call_post(base_args)
op: hir::BinOp,
lhs: &hir::Expr,
rhs: &hir::Expr)
- -> io::Result<()> {
+ {
let assoc_op = bin_op_to_assoc_op(op.node);
let prec = assoc_op.precedence() as i8;
let fixity = assoc_op.fixity();
_ => left_prec,
};
- self.print_expr_maybe_paren(lhs, left_prec)?;
- self.s.space()?;
- self.word_space(op.node.as_str())?;
+ self.print_expr_maybe_paren(lhs, left_prec);
+ self.s.space();
+ self.word_space(op.node.as_str());
self.print_expr_maybe_paren(rhs, right_prec)
}
- fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> {
- self.s.word(op.as_str())?;
+ fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) {
+ self.s.word(op.as_str());
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
}
fn print_expr_addr_of(&mut self,
mutability: hir::Mutability,
expr: &hir::Expr)
- -> io::Result<()> {
- self.s.word("&")?;
- self.print_mutability(mutability)?;
+ {
+ self.s.word("&");
+ self.print_mutability(mutability);
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
}
- fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> {
- self.maybe_print_comment(lit.span.lo())?;
+ fn print_literal(&mut self, lit: &hir::Lit) {
+ self.maybe_print_comment(lit.span.lo());
self.writer().word(pprust::literal_to_string(lit.node.to_lit_token()))
}
- pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
- self.maybe_print_comment(expr.span.lo())?;
- self.print_outer_attributes(&expr.attrs)?;
- self.ibox(indent_unit)?;
- self.ann.pre(self, AnnNode::Expr(expr))?;
+ pub fn print_expr(&mut self, expr: &hir::Expr) {
+ self.maybe_print_comment(expr.span.lo());
+ self.print_outer_attributes(&expr.attrs);
+ self.ibox(indent_unit);
+ self.ann.pre(self, AnnNode::Expr(expr));
match expr.node {
hir::ExprKind::Box(ref expr) => {
- self.word_space("box")?;
- self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)?;
+ self.word_space("box");
+ self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
}
hir::ExprKind::Array(ref exprs) => {
- self.print_expr_vec(exprs)?;
+ self.print_expr_vec(exprs);
}
hir::ExprKind::Repeat(ref element, ref count) => {
- self.print_expr_repeat(&element, count)?;
+ self.print_expr_repeat(&element, count);
}
hir::ExprKind::Struct(ref qpath, ref fields, ref wth) => {
- self.print_expr_struct(qpath, &fields[..], wth)?;
+ self.print_expr_struct(qpath, &fields[..], wth);
}
hir::ExprKind::Tup(ref exprs) => {
- self.print_expr_tup(exprs)?;
+ self.print_expr_tup(exprs);
}
hir::ExprKind::Call(ref func, ref args) => {
- self.print_expr_call(&func, args)?;
+ self.print_expr_call(&func, args);
}
hir::ExprKind::MethodCall(ref segment, _, ref args) => {
- self.print_expr_method_call(segment, args)?;
+ self.print_expr_method_call(segment, args);
}
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
- self.print_expr_binary(op, &lhs, &rhs)?;
+ self.print_expr_binary(op, &lhs, &rhs);
}
hir::ExprKind::Unary(op, ref expr) => {
- self.print_expr_unary(op, &expr)?;
+ self.print_expr_unary(op, &expr);
}
hir::ExprKind::AddrOf(m, ref expr) => {
- self.print_expr_addr_of(m, &expr)?;
+ self.print_expr_addr_of(m, &expr);
}
hir::ExprKind::Lit(ref lit) => {
- self.print_literal(&lit)?;
+ self.print_literal(&lit);
}
hir::ExprKind::Cast(ref expr, ref ty) => {
let prec = AssocOp::As.precedence() as i8;
- self.print_expr_maybe_paren(&expr, prec)?;
- self.s.space()?;
- self.word_space("as")?;
- self.print_type(&ty)?;
+ self.print_expr_maybe_paren(&expr, prec);
+ self.s.space();
+ self.word_space("as");
+ self.print_type(&ty);
}
hir::ExprKind::Type(ref expr, ref ty) => {
let prec = AssocOp::Colon.precedence() as i8;
- self.print_expr_maybe_paren(&expr, prec)?;
- self.word_space(":")?;
- self.print_type(&ty)?;
+ self.print_expr_maybe_paren(&expr, prec);
+ self.word_space(":");
+ self.print_type(&ty);
}
hir::ExprKind::DropTemps(ref init) => {
// Print `{`:
- self.cbox(indent_unit)?;
- self.ibox(0)?;
- self.bopen()?;
+ self.cbox(indent_unit);
+ self.ibox(0);
+ self.bopen();
// Print `let _t = $init;`:
let temp = ast::Ident::from_str("_t");
- self.print_local(Some(init), |this| this.print_ident(temp))?;
- self.s.word(";")?;
+ self.print_local(Some(init), |this| this.print_ident(temp));
+ self.s.word(";");
// Print `_t`:
- self.space_if_not_bol()?;
- self.print_ident(temp)?;
+ self.space_if_not_bol();
+ self.print_ident(temp);
// Print `}`:
- self.bclose_maybe_open(expr.span, indent_unit, true)?;
+ self.bclose_maybe_open(expr.span, indent_unit, true);
}
hir::ExprKind::While(ref test, ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
- self.head("while")?;
- self.print_expr_as_cond(&test)?;
- self.s.space()?;
- self.print_block(&blk)?;
+ self.head("while");
+ self.print_expr_as_cond(&test);
+ self.s.space();
+ self.print_block(&blk);
}
hir::ExprKind::Loop(ref blk, opt_label, _) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
- self.head("loop")?;
- self.s.space()?;
- self.print_block(&blk)?;
+ self.head("loop");
+ self.s.space();
+ self.print_block(&blk);
}
hir::ExprKind::Match(ref expr, ref arms, _) => {
- self.cbox(indent_unit)?;
- self.ibox(4)?;
- self.word_nbsp("match")?;
- self.print_expr_as_cond(&expr)?;
- self.s.space()?;
- self.bopen()?;
+ self.cbox(indent_unit);
+ self.ibox(4);
+ self.word_nbsp("match");
+ self.print_expr_as_cond(&expr);
+ self.s.space();
+ self.bopen();
for arm in arms {
- self.print_arm(arm)?;
+ self.print_arm(arm);
}
- self.bclose_(expr.span, indent_unit)?;
+ self.bclose_(expr.span, indent_unit);
}
hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => {
- self.print_capture_clause(capture_clause)?;
+ self.print_capture_clause(capture_clause);
- self.print_closure_args(&decl, body)?;
- self.s.space()?;
+ self.print_closure_args(&decl, body);
+ self.s.space();
// this is a bare expression
- self.ann.nested(self, Nested::Body(body))?;
- self.end()?; // need to close a box
+ self.ann.nested(self, Nested::Body(body));
+ self.end(); // need to close a box
// a box will be closed by print_expr, but we didn't want an overall
// wrapper so we closed the corresponding opening. so create an
// empty box to satisfy the close.
- self.ibox(0)?;
+ self.ibox(0);
}
hir::ExprKind::Block(ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
// containing cbox, will be closed by print-block at }
- self.cbox(indent_unit)?;
+ self.cbox(indent_unit);
// head-box, will be closed by print-block after {
- self.ibox(0)?;
- self.print_block(&blk)?;
+ self.ibox(0);
+ self.print_block(&blk);
}
hir::ExprKind::Assign(ref lhs, ref rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
- self.print_expr_maybe_paren(&lhs, prec + 1)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_expr_maybe_paren(&rhs, prec)?;
+ self.print_expr_maybe_paren(&lhs, prec + 1);
+ self.s.space();
+ self.word_space("=");
+ self.print_expr_maybe_paren(&rhs, prec);
}
hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
- self.print_expr_maybe_paren(&lhs, prec + 1)?;
- self.s.space()?;
- self.s.word(op.node.as_str())?;
- self.word_space("=")?;
- self.print_expr_maybe_paren(&rhs, prec)?;
+ self.print_expr_maybe_paren(&lhs, prec + 1);
+ self.s.space();
+ self.s.word(op.node.as_str());
+ self.word_space("=");
+ self.print_expr_maybe_paren(&rhs, prec);
}
hir::ExprKind::Field(ref expr, ident) => {
- self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
- self.s.word(".")?;
- self.print_ident(ident)?;
+ self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+ self.s.word(".");
+ self.print_ident(ident);
}
hir::ExprKind::Index(ref expr, ref index) => {
- self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
- self.s.word("[")?;
- self.print_expr(&index)?;
- self.s.word("]")?;
+ self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX);
+ self.s.word("[");
+ self.print_expr(&index);
+ self.s.word("]");
}
hir::ExprKind::Path(ref qpath) => {
- self.print_qpath(qpath, true)?
+ self.print_qpath(qpath, true)
}
hir::ExprKind::Break(destination, ref opt_expr) => {
- self.s.word("break")?;
- self.s.space()?;
+ self.s.word("break");
+ self.s.space();
if let Some(label) = destination.label {
- self.print_ident(label.ident)?;
- self.s.space()?;
+ self.print_ident(label.ident);
+ self.s.space();
}
if let Some(ref expr) = *opt_expr {
- self.print_expr_maybe_paren(expr, parser::PREC_JUMP)?;
- self.s.space()?;
+ self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+ self.s.space();
}
}
hir::ExprKind::Continue(destination) => {
- self.s.word("continue")?;
- self.s.space()?;
+ self.s.word("continue");
+ self.s.space();
if let Some(label) = destination.label {
- self.print_ident(label.ident)?;
- self.s.space()?
+ self.print_ident(label.ident);
+ self.s.space()
}
}
hir::ExprKind::Ret(ref result) => {
- self.s.word("return")?;
+ self.s.word("return");
if let Some(ref expr) = *result {
- self.s.word(" ")?;
- self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
+ self.s.word(" ");
+ self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
}
}
hir::ExprKind::InlineAsm(ref a, ref outputs, ref inputs) => {
- self.s.word("asm!")?;
- self.popen()?;
- self.print_string(&a.asm.as_str(), a.asm_str_style)?;
- self.word_space(":")?;
+ self.s.word("asm!");
+ self.popen();
+ self.print_string(&a.asm.as_str(), a.asm_str_style);
+ self.word_space(":");
let mut out_idx = 0;
self.commasep(Inconsistent, &a.outputs, |s, out| {
match ch.next() {
Some('=') if out.is_rw => {
s.print_string(&format!("+{}", ch.as_str()),
- ast::StrStyle::Cooked)?
+ ast::StrStyle::Cooked)
}
- _ => s.print_string(&constraint, ast::StrStyle::Cooked)?,
+ _ => s.print_string(&constraint, ast::StrStyle::Cooked),
}
- s.popen()?;
- s.print_expr(&outputs[out_idx])?;
- s.pclose()?;
+ s.popen();
+ s.print_expr(&outputs[out_idx]);
+ s.pclose();
out_idx += 1;
- Ok(())
- })?;
- self.s.space()?;
- self.word_space(":")?;
+ });
+ self.s.space();
+ self.word_space(":");
let mut in_idx = 0;
self.commasep(Inconsistent, &a.inputs, |s, co| {
- s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
- s.popen()?;
- s.print_expr(&inputs[in_idx])?;
- s.pclose()?;
+ s.print_string(&co.as_str(), ast::StrStyle::Cooked);
+ s.popen();
+ s.print_expr(&inputs[in_idx]);
+ s.pclose();
in_idx += 1;
- Ok(())
- })?;
- self.s.space()?;
- self.word_space(":")?;
+ });
+ self.s.space();
+ self.word_space(":");
self.commasep(Inconsistent, &a.clobbers, |s, co| {
- s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
- Ok(())
- })?;
+ s.print_string(&co.as_str(), ast::StrStyle::Cooked);
+ });
let mut options = vec![];
if a.volatile {
}
if !options.is_empty() {
- self.s.space()?;
- self.word_space(":")?;
+ self.s.space();
+ self.word_space(":");
self.commasep(Inconsistent, &options, |s, &co| {
- s.print_string(co, ast::StrStyle::Cooked)?;
- Ok(())
- })?;
+ s.print_string(co, ast::StrStyle::Cooked);
+ });
}
- self.pclose()?;
+ self.pclose();
}
hir::ExprKind::Yield(ref expr, _) => {
- self.word_space("yield")?;
- self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
+ self.word_space("yield");
+ self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
}
hir::ExprKind::Err => {
- self.popen()?;
- self.s.word("/*ERROR*/")?;
- self.pclose()?;
+ self.popen();
+ self.s.word("/*ERROR*/");
+ self.pclose();
}
}
- self.ann.post(self, AnnNode::Expr(expr))?;
+ self.ann.post(self, AnnNode::Expr(expr));
self.end()
}
- pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> {
- self.print_pat(&loc.pat)?;
+ pub fn print_local_decl(&mut self, loc: &hir::Local) {
+ self.print_pat(&loc.pat);
if let Some(ref ty) = loc.ty {
- self.word_space(":")?;
- self.print_type(&ty)?;
+ self.word_space(":");
+ self.print_type(&ty);
}
- Ok(())
}
- pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
+ pub fn print_usize(&mut self, i: usize) {
self.s.word(i.to_string())
}
- pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
+ pub fn print_ident(&mut self, ident: ast::Ident) {
if ident.is_raw_guess() {
- self.s.word(format!("r#{}", ident.name))?;
+ self.s.word(format!("r#{}", ident.name));
} else {
- self.s.word(ident.as_str().to_string())?;
+ self.s.word(ident.as_str().to_string());
}
self.ann.post(self, AnnNode::Name(&ident.name))
}
- pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
+ pub fn print_name(&mut self, name: ast::Name) {
self.print_ident(ast::Ident::with_empty_ctxt(name))
}
- pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> {
- self.print_local_decl(loc)?;
- self.s.space()?;
- self.word_space("in")?;
+ pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) {
+ self.print_local_decl(loc);
+ self.s.space();
+ self.word_space("in");
self.print_expr(coll)
}
pub fn print_path(&mut self,
path: &hir::Path,
colons_before_params: bool)
- -> io::Result<()> {
- self.maybe_print_comment(path.span.lo())?;
+ {
+ self.maybe_print_comment(path.span.lo());
for (i, segment) in path.segments.iter().enumerate() {
if i > 0 {
- self.s.word("::")?
+ self.s.word("::")
}
if segment.ident.name != kw::PathRoot {
- self.print_ident(segment.ident)?;
+ self.print_ident(segment.ident);
self.print_generic_args(segment.generic_args(), segment.infer_args,
- colons_before_params)?;
+ colons_before_params);
}
}
-
- Ok(())
}
- pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> {
+ pub fn print_path_segment(&mut self, segment: &hir::PathSegment) {
if segment.ident.name != kw::PathRoot {
- self.print_ident(segment.ident)?;
- self.print_generic_args(segment.generic_args(), segment.infer_args, false)?;
+ self.print_ident(segment.ident);
+ self.print_generic_args(segment.generic_args(), segment.infer_args, false);
}
- Ok(())
}
pub fn print_qpath(&mut self,
qpath: &hir::QPath,
colons_before_params: bool)
- -> io::Result<()> {
+ {
match *qpath {
hir::QPath::Resolved(None, ref path) => {
self.print_path(path, colons_before_params)
}
hir::QPath::Resolved(Some(ref qself), ref path) => {
- self.s.word("<")?;
- self.print_type(qself)?;
- self.s.space()?;
- self.word_space("as")?;
+ self.s.word("<");
+ self.print_type(qself);
+ self.s.space();
+ self.word_space("as");
for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
if i > 0 {
- self.s.word("::")?
+ self.s.word("::")
}
if segment.ident.name != kw::PathRoot {
- self.print_ident(segment.ident)?;
+ self.print_ident(segment.ident);
self.print_generic_args(segment.generic_args(),
segment.infer_args,
- colons_before_params)?;
+ colons_before_params);
}
}
- self.s.word(">")?;
- self.s.word("::")?;
+ self.s.word(">");
+ self.s.word("::");
let item_segment = path.segments.last().unwrap();
- self.print_ident(item_segment.ident)?;
+ self.print_ident(item_segment.ident);
self.print_generic_args(item_segment.generic_args(),
item_segment.infer_args,
colons_before_params)
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
- self.s.word("<")?;
- self.print_type(qself)?;
- self.s.word(">")?;
- self.s.word("::")?;
- self.print_ident(item_segment.ident)?;
+ self.s.word("<");
+ self.print_type(qself);
+ self.s.word(">");
+ self.s.word("::");
+ self.print_ident(item_segment.ident);
self.print_generic_args(item_segment.generic_args(),
item_segment.infer_args,
colons_before_params)
generic_args: &hir::GenericArgs,
infer_args: bool,
colons_before_params: bool)
- -> io::Result<()> {
+ {
if generic_args.parenthesized {
- self.s.word("(")?;
- self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty))?;
- self.s.word(")")?;
+ self.s.word("(");
+ self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty));
+ self.s.word(")");
- self.space_if_not_bol()?;
- self.word_space("->")?;
- self.print_type(generic_args.bindings[0].ty())?;
+ self.space_if_not_bol();
+ self.word_space("->");
+ self.print_type(generic_args.bindings[0].ty());
} else {
let start = if colons_before_params { "::<" } else { "<" };
let empty = Cell::new(true);
});
if nonelided_generic_args {
- start_or_comma(self)?;
+ start_or_comma(self);
self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| {
match generic_arg {
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
- GenericArg::Lifetime(_) => Ok(()),
+ GenericArg::Lifetime(_) => {},
GenericArg::Type(ty) => s.print_type(ty),
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
}
- })?;
+ });
}
// FIXME(eddyb): this would leak into error messages (e.g.,
// "non-exhaustive patterns: `Some::<..>(_)` not covered").
if infer_args && false {
- start_or_comma(self)?;
- self.s.word("..")?;
+ start_or_comma(self);
+ self.s.word("..");
}
for binding in generic_args.bindings.iter() {
- start_or_comma(self)?;
- self.print_ident(binding.ident)?;
- self.s.space()?;
+ start_or_comma(self);
+ self.print_ident(binding.ident);
+ self.s.space();
match generic_args.bindings[0].kind {
hir::TypeBindingKind::Equality { ref ty } => {
- self.word_space("=")?;
- self.print_type(ty)?;
+ self.word_space("=");
+ self.print_type(ty);
}
hir::TypeBindingKind::Constraint { ref bounds } => {
- self.print_bounds(":", bounds)?;
+ self.print_bounds(":", bounds);
}
}
}
if !empty.get() {
- self.s.word(">")?
+ self.s.word(">")
}
}
-
- Ok(())
}
- pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
- self.maybe_print_comment(pat.span.lo())?;
- self.ann.pre(self, AnnNode::Pat(pat))?;
+ pub fn print_pat(&mut self, pat: &hir::Pat) {
+ self.maybe_print_comment(pat.span.lo());
+ self.ann.pre(self, AnnNode::Pat(pat));
// Pat isn't normalized, but the beauty of it
// is that it doesn't matter
match pat.node {
- PatKind::Wild => self.s.word("_")?,
+ PatKind::Wild => self.s.word("_"),
PatKind::Binding(binding_mode, _, ident, ref sub) => {
match binding_mode {
hir::BindingAnnotation::Ref => {
- self.word_nbsp("ref")?;
- self.print_mutability(hir::MutImmutable)?;
+ self.word_nbsp("ref");
+ self.print_mutability(hir::MutImmutable);
}
hir::BindingAnnotation::RefMut => {
- self.word_nbsp("ref")?;
- self.print_mutability(hir::MutMutable)?;
+ self.word_nbsp("ref");
+ self.print_mutability(hir::MutMutable);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
- self.word_nbsp("mut")?;
+ self.word_nbsp("mut");
}
}
- self.print_ident(ident)?;
+ self.print_ident(ident);
if let Some(ref p) = *sub {
- self.s.word("@")?;
- self.print_pat(&p)?;
+ self.s.word("@");
+ self.print_pat(&p);
}
}
PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
- self.print_qpath(qpath, true)?;
- self.popen()?;
+ self.print_qpath(qpath, true);
+ self.popen();
if let Some(ddpos) = ddpos {
- self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
+ self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p));
if ddpos != 0 {
- self.word_space(",")?;
+ self.word_space(",");
}
- self.s.word("..")?;
+ self.s.word("..");
if ddpos != elts.len() {
- self.s.word(",")?;
- self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
+ self.s.word(",");
+ self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p));
}
} else {
- self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
+ self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p));
}
- self.pclose()?;
+ self.pclose();
}
PatKind::Path(ref qpath) => {
- self.print_qpath(qpath, true)?;
+ self.print_qpath(qpath, true);
}
PatKind::Struct(ref qpath, ref fields, etc) => {
- self.print_qpath(qpath, true)?;
- self.nbsp()?;
- self.word_space("{")?;
+ self.print_qpath(qpath, true);
+ self.nbsp();
+ self.word_space("{");
self.commasep_cmnt(Consistent,
&fields[..],
|s, f| {
- s.cbox(indent_unit)?;
+ s.cbox(indent_unit);
if !f.node.is_shorthand {
- s.print_ident(f.node.ident)?;
- s.word_nbsp(":")?;
+ s.print_ident(f.node.ident);
+ s.word_nbsp(":");
}
- s.print_pat(&f.node.pat)?;
+ s.print_pat(&f.node.pat);
s.end()
},
- |f| f.node.pat.span)?;
+ |f| f.node.pat.span);
if etc {
if !fields.is_empty() {
- self.word_space(",")?;
+ self.word_space(",");
}
- self.s.word("..")?;
+ self.s.word("..");
}
- self.s.space()?;
- self.s.word("}")?;
+ self.s.space();
+ self.s.word("}");
}
PatKind::Tuple(ref elts, ddpos) => {
- self.popen()?;
+ self.popen();
if let Some(ddpos) = ddpos {
- self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
+ self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p));
if ddpos != 0 {
- self.word_space(",")?;
+ self.word_space(",");
}
- self.s.word("..")?;
+ self.s.word("..");
if ddpos != elts.len() {
- self.s.word(",")?;
- self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
+ self.s.word(",");
+ self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p));
}
} else {
- self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
+ self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p));
if elts.len() == 1 {
- self.s.word(",")?;
+ self.s.word(",");
}
}
- self.pclose()?;
+ self.pclose();
}
PatKind::Box(ref inner) => {
let is_range_inner = match inner.node {
PatKind::Range(..) => true,
_ => false,
};
- self.s.word("box ")?;
+ self.s.word("box ");
if is_range_inner {
- self.popen()?;
+ self.popen();
}
- self.print_pat(&inner)?;
+ self.print_pat(&inner);
if is_range_inner {
- self.pclose()?;
+ self.pclose();
}
}
PatKind::Ref(ref inner, mutbl) => {
PatKind::Range(..) => true,
_ => false,
};
- self.s.word("&")?;
+ self.s.word("&");
if mutbl == hir::MutMutable {
- self.s.word("mut ")?;
+ self.s.word("mut ");
}
if is_range_inner {
- self.popen()?;
+ self.popen();
}
- self.print_pat(&inner)?;
+ self.print_pat(&inner);
if is_range_inner {
- self.pclose()?;
+ self.pclose();
}
}
- PatKind::Lit(ref e) => self.print_expr(&e)?,
+ PatKind::Lit(ref e) => self.print_expr(&e),
PatKind::Range(ref begin, ref end, ref end_kind) => {
- self.print_expr(&begin)?;
- self.s.space()?;
+ self.print_expr(&begin);
+ self.s.space();
match *end_kind {
- RangeEnd::Included => self.s.word("...")?,
- RangeEnd::Excluded => self.s.word("..")?,
+ RangeEnd::Included => self.s.word("..."),
+ RangeEnd::Excluded => self.s.word(".."),
}
- self.print_expr(&end)?;
+ self.print_expr(&end);
}
PatKind::Slice(ref before, ref slice, ref after) => {
- self.s.word("[")?;
- self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?;
+ self.s.word("[");
+ self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p));
if let Some(ref p) = *slice {
if !before.is_empty() {
- self.word_space(",")?;
+ self.word_space(",");
}
if let PatKind::Wild = p.node {
// Print nothing
} else {
- self.print_pat(&p)?;
+ self.print_pat(&p);
}
- self.s.word("..")?;
+ self.s.word("..");
if !after.is_empty() {
- self.word_space(",")?;
+ self.word_space(",");
}
}
- self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?;
- self.s.word("]")?;
+ self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p));
+ self.s.word("]");
}
}
self.ann.post(self, AnnNode::Pat(pat))
}
- pub fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
+ pub fn print_arm(&mut self, arm: &hir::Arm) {
// I have no idea why this check is necessary, but here it
// is :(
if arm.attrs.is_empty() {
- self.s.space()?;
+ self.s.space();
}
- self.cbox(indent_unit)?;
- self.ibox(0)?;
- self.print_outer_attributes(&arm.attrs)?;
+ self.cbox(indent_unit);
+ self.ibox(0);
+ self.print_outer_attributes(&arm.attrs);
let mut first = true;
for p in &arm.pats {
if first {
first = false;
} else {
- self.s.space()?;
- self.word_space("|")?;
+ self.s.space();
+ self.word_space("|");
}
- self.print_pat(&p)?;
+ self.print_pat(&p);
}
- self.s.space()?;
+ self.s.space();
if let Some(ref g) = arm.guard {
match g {
hir::Guard::If(e) => {
- self.word_space("if")?;
- self.print_expr(&e)?;
- self.s.space()?;
+ self.word_space("if");
+ self.print_expr(&e);
+ self.s.space();
}
}
}
- self.word_space("=>")?;
+ self.word_space("=>");
match arm.body.node {
hir::ExprKind::Block(ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
// the block will close the pattern's ibox
- self.print_block_unclosed_indent(&blk, indent_unit)?;
+ self.print_block_unclosed_indent(&blk, indent_unit);
// If it is a user-provided unsafe block, print a comma after it
if let hir::UnsafeBlock(hir::UserProvided) = blk.rules {
- self.s.word(",")?;
+ self.s.word(",");
}
}
_ => {
- self.end()?; // close the ibox for the pattern
- self.print_expr(&arm.body)?;
- self.s.word(",")?;
+ self.end(); // close the ibox for the pattern
+ self.print_expr(&arm.body);
+ self.s.word(",");
}
}
self.end() // close enclosing cbox
vis: &hir::Visibility,
arg_names: &[ast::Ident],
body_id: Option<hir::BodyId>)
- -> io::Result<()> {
- self.print_fn_header_info(header, vis)?;
+ {
+ self.print_fn_header_info(header, vis);
if let Some(name) = name {
- self.nbsp()?;
- self.print_name(name)?;
+ self.nbsp();
+ self.print_name(name);
}
- self.print_generic_params(&generics.params)?;
+ self.print_generic_params(&generics.params);
- self.popen()?;
+ self.popen();
let mut i = 0;
// Make sure we aren't supplied *both* `arg_names` and `body_id`.
assert!(arg_names.is_empty() || body_id.is_none());
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
- s.ibox(indent_unit)?;
+ s.ibox(indent_unit);
if let Some(arg_name) = arg_names.get(i) {
- s.s.word(arg_name.as_str().to_string())?;
- s.s.word(":")?;
- s.s.space()?;
+ s.s.word(arg_name.as_str().to_string());
+ s.s.word(":");
+ s.s.space();
} else if let Some(body_id) = body_id {
- s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
- s.s.word(":")?;
- s.s.space()?;
+ s.ann.nested(s, Nested::BodyArgPat(body_id, i));
+ s.s.word(":");
+ s.s.space();
}
i += 1;
- s.print_type(ty)?;
+ s.print_type(ty);
s.end()
- })?;
+ });
if decl.c_variadic {
- self.s.word(", ...")?;
+ self.s.word(", ...");
}
- self.pclose()?;
+ self.pclose();
- self.print_fn_output(decl)?;
+ self.print_fn_output(decl);
self.print_where_clause(&generics.where_clause)
}
- fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> {
- self.s.word("|")?;
+ fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) {
+ self.s.word("|");
let mut i = 0;
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
- s.ibox(indent_unit)?;
+ s.ibox(indent_unit);
- s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
+ s.ann.nested(s, Nested::BodyArgPat(body_id, i));
i += 1;
if let hir::TyKind::Infer = ty.node {
// Print nothing
} else {
- s.s.word(":")?;
- s.s.space()?;
- s.print_type(ty)?;
+ s.s.word(":");
+ s.s.space();
+ s.print_type(ty);
}
- s.end()
- })?;
- self.s.word("|")?;
+ s.end();
+ });
+ self.s.word("|");
if let hir::DefaultReturn(..) = decl.output {
- return Ok(());
+ return;
}
- self.space_if_not_bol()?;
- self.word_space("->")?;
+ self.space_if_not_bol();
+ self.word_space("->");
match decl.output {
hir::Return(ref ty) => {
- self.print_type(&ty)?;
+ self.print_type(&ty);
self.maybe_print_comment(ty.span.lo())
}
hir::DefaultReturn(..) => unreachable!(),
}
}
- pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> {
+ pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) {
match capture_clause {
hir::CaptureByValue => self.word_space("move"),
- hir::CaptureByRef => Ok(()),
+ hir::CaptureByRef => {},
}
}
&mut self,
prefix: &'static str,
bounds: impl IntoIterator<Item = &'b hir::GenericBound>,
- ) -> io::Result<()> {
+ ) {
let mut first = true;
for bound in bounds {
if first {
- self.s.word(prefix)?;
+ self.s.word(prefix);
}
if !(first && prefix.is_empty()) {
- self.nbsp()?;
+ self.nbsp();
}
if first {
first = false;
} else {
- self.word_space("+")?;
+ self.word_space("+");
}
match bound {
GenericBound::Trait(tref, modifier) => {
if modifier == &TraitBoundModifier::Maybe {
- self.s.word("?")?;
+ self.s.word("?");
}
- self.print_poly_trait_ref(tref)?;
+ self.print_poly_trait_ref(tref);
}
GenericBound::Outlives(lt) => {
- self.print_lifetime(lt)?;
+ self.print_lifetime(lt);
}
}
}
- Ok(())
}
- pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) -> io::Result<()> {
+ pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) {
if !generic_params.is_empty() {
- self.s.word("<")?;
+ self.s.word("<");
self.commasep(Inconsistent, generic_params, |s, param| {
s.print_generic_param(param)
- })?;
+ });
- self.s.word(">")?;
+ self.s.word(">");
}
- Ok(())
}
- pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
+ pub fn print_generic_param(&mut self, param: &GenericParam) {
if let GenericParamKind::Const { .. } = param.kind {
- self.word_space("const")?;
+ self.word_space("const");
}
- self.print_ident(param.name.ident())?;
+ self.print_ident(param.name.ident());
match param.kind {
GenericParamKind::Lifetime { .. } => {
for bound in ¶m.bounds {
match bound {
GenericBound::Outlives(lt) => {
- self.s.word(sep)?;
- self.print_lifetime(lt)?;
+ self.s.word(sep);
+ self.print_lifetime(lt);
sep = "+";
}
_ => bug!(),
}
}
- Ok(())
}
GenericParamKind::Type { ref default, .. } => {
- self.print_bounds(":", ¶m.bounds)?;
+ self.print_bounds(":", ¶m.bounds);
match default {
Some(default) => {
- self.s.space()?;
- self.word_space("=")?;
+ self.s.space();
+ self.word_space("=");
self.print_type(&default)
}
- _ => Ok(()),
+ _ => {}
}
}
GenericParamKind::Const { ref ty } => {
- self.word_space(":")?;
+ self.word_space(":");
self.print_type(ty)
}
}
}
- pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
+ pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) {
self.print_ident(lifetime.name.ident())
}
- pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
+ pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) {
if where_clause.predicates.is_empty() {
- return Ok(());
+ return;
}
- self.s.space()?;
- self.word_space("where")?;
+ self.s.space();
+ self.word_space("where");
for (i, predicate) in where_clause.predicates.iter().enumerate() {
if i != 0 {
- self.word_space(",")?;
+ self.word_space(",");
}
match predicate {
ref bounds,
..
}) => {
- self.print_formal_generic_params(bound_generic_params)?;
- self.print_type(&bounded_ty)?;
- self.print_bounds(":", bounds)?;
+ self.print_formal_generic_params(bound_generic_params);
+ self.print_type(&bounded_ty);
+ self.print_bounds(":", bounds);
}
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
- self.print_lifetime(lifetime)?;
- self.s.word(":")?;
+ self.print_lifetime(lifetime);
+ self.s.word(":");
for (i, bound) in bounds.iter().enumerate() {
match bound {
GenericBound::Outlives(lt) => {
- self.print_lifetime(lt)?;
+ self.print_lifetime(lt);
}
_ => bug!(),
}
if i != 0 {
- self.s.word(":")?;
+ self.s.word(":");
}
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
- self.print_type(lhs_ty)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(rhs_ty)?;
+ self.print_type(lhs_ty);
+ self.s.space();
+ self.word_space("=");
+ self.print_type(rhs_ty);
}
}
}
-
- Ok(())
}
- pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> {
+ pub fn print_mutability(&mut self, mutbl: hir::Mutability) {
match mutbl {
hir::MutMutable => self.word_nbsp("mut"),
- hir::MutImmutable => Ok(()),
+ hir::MutImmutable => {},
}
}
- pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
- self.print_mutability(mt.mutbl)?;
+ pub fn print_mt(&mut self, mt: &hir::MutTy) {
+ self.print_mutability(mt.mutbl);
self.print_type(&mt.ty)
}
- pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
+ pub fn print_fn_output(&mut self, decl: &hir::FnDecl) {
if let hir::DefaultReturn(..) = decl.output {
- return Ok(());
+ return;
}
- self.space_if_not_bol()?;
- self.ibox(indent_unit)?;
- self.word_space("->")?;
+ self.space_if_not_bol();
+ self.ibox(indent_unit);
+ self.word_space("->");
match decl.output {
hir::DefaultReturn(..) => unreachable!(),
- hir::Return(ref ty) => self.print_type(&ty)?,
+ hir::Return(ref ty) => self.print_type(&ty),
}
- self.end()?;
+ self.end();
match decl.output {
hir::Return(ref output) => self.maybe_print_comment(output.span.lo()),
- _ => Ok(()),
+ _ => {},
}
}
name: Option<ast::Name>,
generic_params: &[hir::GenericParam],
arg_names: &[ast::Ident])
- -> io::Result<()> {
- self.ibox(indent_unit)?;
+ {
+ self.ibox(indent_unit);
if !generic_params.is_empty() {
- self.s.word("for")?;
- self.print_generic_params(generic_params)?;
+ self.s.word("for");
+ self.print_generic_params(generic_params);
}
let generics = hir::Generics {
params: hir::HirVec::new(),
&Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited },
arg_names,
- None)?;
- self.end()
+ None);
+ self.end();
}
pub fn maybe_print_trailing_comment(&mut self,
span: syntax_pos::Span,
next_pos: Option<BytePos>)
- -> io::Result<()> {
+ {
let cm = match self.cm {
Some(cm) => cm,
- _ => return Ok(()),
+ _ => return,
};
if let Some(ref cmnt) = self.next_comment() {
if (*cmnt).style != comments::Trailing {
- return Ok(());
+ return;
}
let span_line = cm.lookup_char_pos(span.hi());
let comment_line = cm.lookup_char_pos((*cmnt).pos);
}
if span.hi() < (*cmnt).pos && (*cmnt).pos < next &&
span_line.line == comment_line.line {
- self.print_comment(cmnt)?;
+ self.print_comment(cmnt);
}
}
- Ok(())
}
- pub fn print_remaining_comments(&mut self) -> io::Result<()> {
+ pub fn print_remaining_comments(&mut self) {
// If there aren't any remaining comments, then we need to manually
// make sure there is a line break at the end.
if self.next_comment().is_none() {
- self.s.hardbreak()?;
+ self.s.hardbreak();
}
while let Some(ref cmnt) = self.next_comment() {
- self.print_comment(cmnt)?
+ self.print_comment(cmnt)
}
- Ok(())
}
pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
opt_abi: Option<Abi>)
- -> io::Result<()> {
+ {
match opt_abi {
- Some(Abi::Rust) => Ok(()),
+ Some(Abi::Rust) => {},
Some(abi) => {
- self.word_nbsp("extern")?;
+ self.word_nbsp("extern");
self.word_nbsp(abi.to_string())
}
- None => Ok(()),
+ None => {},
}
}
- pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) -> io::Result<()> {
+ pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) {
match opt_abi {
Some(abi) => {
- self.word_nbsp("extern")?;
+ self.word_nbsp("extern");
self.word_nbsp(abi.to_string())
}
- None => Ok(()),
+ None => {},
}
}
pub fn print_fn_header_info(&mut self,
header: hir::FnHeader,
vis: &hir::Visibility)
- -> io::Result<()> {
- self.s.word(visibility_qualified(vis, ""))?;
+ {
+ self.s.word(visibility_qualified(vis, ""));
match header.constness {
hir::Constness::NotConst => {}
- hir::Constness::Const => self.word_nbsp("const")?,
+ hir::Constness::Const => self.word_nbsp("const"),
}
match header.asyncness {
hir::IsAsync::NotAsync => {}
- hir::IsAsync::Async => self.word_nbsp("async")?,
+ hir::IsAsync::Async => self.word_nbsp("async"),
}
- self.print_unsafety(header.unsafety)?;
+ self.print_unsafety(header.unsafety);
if header.abi != Abi::Rust {
- self.word_nbsp("extern")?;
- self.word_nbsp(header.abi.to_string())?;
+ self.word_nbsp("extern");
+ self.word_nbsp(header.abi.to_string());
}
self.s.word("fn")
}
- pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> {
+ pub fn print_unsafety(&mut self, s: hir::Unsafety) {
match s {
- hir::Unsafety::Normal => Ok(()),
+ hir::Unsafety::Normal => {}
hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
}
}
- pub fn print_is_auto(&mut self, s: hir::IsAuto) -> io::Result<()> {
+ pub fn print_is_auto(&mut self, s: hir::IsAuto) {
match s {
hir::IsAuto::Yes => self.word_nbsp("auto"),
- hir::IsAuto::No => Ok(()),
+ hir::IsAuto::No => {},
}
}
}
--- /dev/null
+// HACK(eddyb) this is a copy of `syntax::ptr`, minus the mutation (the HIR is
+// frozen anyway). The only reason for doing this instead of replacing `P<T>`
+// with `Box<T>` in HIR, is that `&Box<[T]>` doesn't implement `IntoIterator`.
+
+use std::fmt::{self, Display, Debug};
+use std::iter::FromIterator;
+use std::ops::Deref;
+use std::{slice, vec};
+
+use serialize::{Encodable, Decodable, Encoder, Decoder};
+
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+ HashStable};
+/// An owned smart pointer.
+#[derive(Hash, PartialEq, Eq)]
+pub struct P<T: ?Sized> {
+ ptr: Box<T>
+}
+
+/// Construct a `P<T>` from a `T` value.
+#[allow(non_snake_case)]
+pub fn P<T: 'static>(value: T) -> P<T> {
+ P {
+ ptr: box value
+ }
+}
+
+impl<T: 'static> P<T> {
+ // HACK(eddyb) used by HIR lowering in a few places still.
+ // NOTE: do not make this more public than `pub(super)`.
+ pub(super) fn into_inner(self) -> T {
+ *self.ptr
+ }
+}
+
+impl<T: ?Sized> Deref for P<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &self.ptr
+ }
+}
+
+impl<T: ?Sized + Debug> Debug for P<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Debug::fmt(&self.ptr, f)
+ }
+}
+
+impl<T: Display> Display for P<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Display::fmt(&**self, f)
+ }
+}
+
+impl<T: 'static + Decodable> Decodable for P<T> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
+ Decodable::decode(d).map(P)
+ }
+}
+
+impl<T: Encodable> Encodable for P<T> {
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ (**self).encode(s)
+ }
+}
+
+impl<T> P<[T]> {
+ pub const fn new() -> P<[T]> {
+ // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>`
+ // (as trait methods, `default` in this case, can't be `const fn` yet).
+ P {
+ ptr: unsafe {
+ use std::ptr::NonNull;
+ std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>)
+ },
+ }
+ }
+
+ #[inline(never)]
+ pub fn from_vec(v: Vec<T>) -> P<[T]> {
+ P { ptr: v.into_boxed_slice() }
+ }
+
+ // HACK(eddyb) used by HIR lowering in a few places still.
+ // NOTE: do not make this more public than `pub(super)`,
+ // and do not make this into an `IntoIterator` impl.
+ pub(super) fn into_iter(self) -> vec::IntoIter<T> {
+ self.ptr.into_vec().into_iter()
+ }
+}
+
+
+impl<T> Default for P<[T]> {
+ /// Creates an empty `P<[T]>`.
+ fn default() -> P<[T]> {
+ P::new()
+ }
+}
+
+impl<T> From<Vec<T>> for P<[T]> {
+ fn from(v: Vec<T>) -> Self {
+ P::from_vec(v)
+ }
+}
+
+impl<T> FromIterator<T> for P<[T]> {
+ fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> P<[T]> {
+ P::from_vec(iter.into_iter().collect())
+ }
+}
+
+impl<'a, T> IntoIterator for &'a P<[T]> {
+ type Item = &'a T;
+ type IntoIter = slice::Iter<'a, T>;
+ fn into_iter(self) -> Self::IntoIter {
+ self.ptr.into_iter()
+ }
+}
+
+impl<T: Encodable> Encodable for P<[T]> {
+ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ Encodable::encode(&**self, s)
+ }
+}
+
+impl<T: Decodable> Decodable for P<[T]> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
+ Ok(P::from_vec(Decodable::decode(d)?))
+ }
+}
+
+impl<CTX, T> HashStable<CTX> for P<T>
+ where T: ?Sized + HashStable<CTX>
+{
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut CTX,
+ hasher: &mut StableHasher<W>) {
+ (**self).hash_stable(hcx, hasher);
+ }
+}
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if let hir::ExprKind::Closure(..) = expr.node {
- let closure_def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
+ let closure_def_id = self.tcx.hir().local_def_id(expr.hir_id);
if let Some(upvars) = self.tcx.upvars(closure_def_id) {
// Every capture of a closure expression is a local in scope,
// that is moved/copied/borrowed into the closure value, and
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
+use crate::infer::region_constraints::MemberConstraint;
use crate::mir::interpret::ConstValue;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_macros::HashStable;
#[derive(Clone, Debug, HashStable)]
pub struct QueryResponse<'tcx, R> {
pub var_values: CanonicalVarValues<'tcx>,
- pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
+ pub region_constraints: QueryRegionConstraints<'tcx>,
pub certainty: Certainty,
pub value: R,
}
+#[derive(Clone, Debug, Default, HashStable)]
+pub struct QueryRegionConstraints<'tcx> {
+ pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
+ pub member_constraints: Vec<MemberConstraint<'tcx>>,
+}
+
+impl QueryRegionConstraints<'_> {
+ /// Represents an empty (trivially true) set of region
+ /// constraints.
+ pub fn is_empty(&self) -> bool {
+ self.outlives.is_empty() && self.member_constraints.is_empty()
+ }
+}
+
pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
pub type CanonicalizedQueryResponse<'tcx, T> =
}
}
-pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
+pub type QueryOutlivesConstraint<'tcx> =
+ ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// Creates a substitution S for the canonical value with fresh
} where R: Lift<'tcx>
}
+BraceStructTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
+ outlives, member_constraints
+ }
+}
+
+BraceStructLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
+ type Lifted = QueryRegionConstraints<'tcx>;
+ outlives, member_constraints
+ }
+}
+
impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
type Output = Kind<'tcx>;
use crate::infer::canonical::substitute::substitute_value;
use crate::infer::canonical::{
Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty,
- OriginalQueryValues, QueryRegionConstraint, QueryResponse,
+ OriginalQueryValues, QueryRegionConstraints, QueryOutlivesConstraint, QueryResponse,
};
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxtBuilder;
{
self.canonicalize_response(&QueryResponse {
var_values: inference_vars,
- region_constraints: vec![],
+ region_constraints: QueryRegionConstraints::default(),
certainty: Certainty::Proven, // Ambiguities are OK!
value: answer,
})
let region_obligations = self.take_registered_region_obligations();
let region_constraints = self.with_region_constraints(|region_constraints| {
- make_query_outlives(
+ make_query_region_constraints(
tcx,
region_obligations
.iter()
mut obligations,
} = self.query_response_substitution(cause, param_env, original_values, query_response)?;
- obligations.extend(self.query_region_constraints_into_obligations(
+ obligations.extend(self.query_outlives_constraints_into_obligations(
cause,
param_env,
- &query_response.value.region_constraints,
+ &query_response.value.region_constraints.outlives,
&result_subst,
));
/// that come out of these queries, which it wants to convert into
/// MIR-based constraints and solve. Therefore, it is most
/// convenient for the NLL Type Checker to **directly consume**
- /// the `QueryRegionConstraint` values that arise from doing a
+ /// the `QueryOutlivesConstraint` values that arise from doing a
/// query. This is contrast to other parts of the compiler, which
- /// would prefer for those `QueryRegionConstraint` to be converted
+ /// would prefer for those `QueryOutlivesConstraint` to be converted
/// into the older infcx-style constraints (e.g., calls to
/// `sub_regions` or `register_region_obligation`).
///
/// result. If any errors arise, they are propagated back as an
/// `Err` result.
/// - In the case of a successful substitution, we will append
- /// `QueryRegionConstraint` values onto the
+ /// `QueryOutlivesConstraint` values onto the
/// `output_query_region_constraints` vector for the solver to
/// use (if an error arises, some values may also be pushed, but
/// they should be ignored).
param_env: ty::ParamEnv<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
- output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
+ output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> InferResult<'tcx, R>
where
R: Debug + TypeFoldable<'tcx>,
let result_subst =
self.query_response_substitution_guess(cause, original_values, query_response);
- // Compute `QueryRegionConstraint` values that unify each of
+ // Compute `QueryOutlivesConstraint` values that unify each of
// the original values `v_o` that was canonicalized into a
// variable...
let mut obligations = vec![];
// To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
if v_o != v_r {
output_query_region_constraints
+ .outlives
.push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)));
output_query_region_constraints
+ .outlives
.push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)));
}
}
}
// ...also include the other query region constraints from the query.
- output_query_region_constraints.extend(
- query_response.value.region_constraints.iter().filter_map(|r_c| {
+ output_query_region_constraints.outlives.extend(
+ query_response.value.region_constraints.outlives.iter().filter_map(|r_c| {
let r_c = substitute_value(self.tcx, &result_subst, r_c);
// Screen out `'a: 'a` cases -- we skip the binder here but
- // only care the inner values to one another, so they are still at
+ // only compare the inner values to one another, so they are still at
// consistent binding levels.
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
if k1 != r2.into() {
})
);
+ // ...also include the query member constraints.
+ output_query_region_constraints.member_constraints.extend(
+ query_response.value.region_constraints.member_constraints.iter().map(|p_c| {
+ substitute_value(self.tcx, &result_subst, p_c)
+ })
+ );
+
let user_result: R =
query_response.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
/// Converts the region constraints resulting from a query into an
/// iterator of obligations.
- fn query_region_constraints_into_obligations<'a>(
+ fn query_outlives_constraints_into_obligations<'a>(
&'a self,
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
+ unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
result_subst: &'a CanonicalVarValues<'tcx>,
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
unsubstituted_region_constraints
/// Given the region obligations and constraints scraped from the infcx,
/// creates query region constraints.
-pub fn make_query_outlives<'tcx>(
+pub fn make_query_region_constraints<'tcx>(
tcx: TyCtxt<'tcx>,
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>,
region_constraints: &RegionConstraintData<'tcx>,
-) -> Vec<QueryRegionConstraint<'tcx>> {
+) -> QueryRegionConstraints<'tcx> {
let RegionConstraintData {
constraints,
verifys,
givens,
+ member_constraints,
} = region_constraints;
assert!(verifys.is_empty());
)
.collect();
- outlives
+ QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
}
use crate::hir;
use crate::hir::def_id::DefId;
use crate::hir::Node;
+use crate::infer::opaque_types;
use crate::middle::region;
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::error::TypeError;
);
}
}
+
+ RegionResolutionError::MemberConstraintFailure {
+ opaque_type_def_id,
+ hidden_ty,
+ member_region,
+ span: _,
+ choice_regions: _,
+ } => {
+ let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
+ opaque_types::unexpected_hidden_region_diagnostic(
+ self.tcx,
+ Some(region_scope_tree),
+ opaque_type_def_id,
+ hidden_ty,
+ member_region,
+ ).emit();
+ }
}
}
}
let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
RegionResolutionError::GenericBoundFailure(..) => true,
RegionResolutionError::ConcreteFailure(..)
- | RegionResolutionError::SubSupConflict(..) => false,
+ | RegionResolutionError::SubSupConflict(..)
+ | RegionResolutionError::MemberConstraintFailure { .. } => false,
};
let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
+ RegionResolutionError::MemberConstraintFailure { span, .. } => span,
});
errors
}
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
- debug!(
- "EarlyBound self.infcx.tcx.hir().local_def_id(id)={:?} \
- def_id={:?}",
- id,
- def_id
- );
+ debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
self.found_type = Some(arg);
return; // we can stop visiting now
"FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
debruijn_index
);
- debug!("self.infcx.tcx.hir().local_def_id(id)={:?}", id);
- debug!("def_id={:?}", def_id);
+ debug!("LateBound id={:?} def_id={:?}", id, def_id);
if debruijn_index == self.current_index && id == def_id {
self.found_type = Some(arg);
return; // we can stop visiting now
}
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
- debug!(
- "EarlyBound self.infcx.tcx.hir().local_def_id(id)={:?} \
- def_id={:?}",
- id,
- def_id
- );
+ debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
self.found_it = true;
return; // we can stop visiting now
//! Lexical region resolution.
+use crate::hir::def_id::DefId;
use crate::infer::region_constraints::Constraint;
use crate::infer::region_constraints::GenericKind;
+use crate::infer::region_constraints::MemberConstraint;
use crate::infer::region_constraints::RegionConstraintData;
use crate::infer::region_constraints::VarInfos;
use crate::infer::region_constraints::VerifyBound;
use crate::infer::RegionVariableOrigin;
use crate::infer::SubregionOrigin;
use crate::middle::free_region::RegionRelations;
+use crate::ty::fold::TypeFoldable;
+use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
+use crate::ty::{ReLateBound, RePlaceholder, ReScope, ReVar};
+use crate::ty::{Region, RegionVid};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::implementation::{
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use smallvec::SmallVec;
use std::fmt;
-use std::u32;
-use crate::ty::fold::TypeFoldable;
-use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
-use crate::ty::{ReLateBound, ReScope, RePlaceholder, ReVar};
-use crate::ty::{Region, RegionVid};
+use syntax_pos::Span;
mod graphviz;
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
debug!("RegionConstraintData: resolve_regions()");
let mut errors = vec![];
- let mut resolver = LexicalResolver {
- region_rels,
- var_infos,
- data,
- };
+ let mut resolver = LexicalResolver { region_rels, var_infos, data };
let values = resolver.infer_variable_values(&mut errors);
(values, errors)
}
SubregionOrigin<'tcx>,
Region<'tcx>,
),
+
+ /// Indicates a failure of a `MemberConstraint`. These arise during
+ /// impl trait processing explicitly -- basically, the impl trait's hidden type
+ /// included some region that it was not supposed to.
+ MemberConstraintFailure {
+ span: Span,
+ opaque_type_def_id: DefId,
+ hidden_ty: Ty<'tcx>,
+ member_region: Region<'tcx>,
+ choice_regions: Vec<Region<'tcx>>,
+ },
}
struct RegionAndOrigin<'tcx> {
let graph = self.construct_graph();
self.expand_givens(&graph);
- self.expansion(&mut var_data);
+ loop {
+ self.expansion(&mut var_data);
+ if !self.enforce_member_constraints(&graph, &mut var_data) {
+ break;
+ }
+ }
self.collect_errors(&mut var_data, errors);
self.collect_var_errors(&var_data, &graph, errors);
var_data
fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
LexicalRegionResolutions {
error_region: tcx.lifetimes.re_static,
- values: IndexVec::from_elem_n(VarValue::Value(tcx.lifetimes.re_empty), self.num_vars())
+ values: IndexVec::from_elem_n(VarValue::Value(tcx.lifetimes.re_empty), self.num_vars()),
}
}
}
}
+ /// Enforce all member constraints and return true if anything
+ /// changed. See `enforce_member_constraint` for more details.
+ fn enforce_member_constraints(
+ &self,
+ graph: &RegionGraph<'tcx>,
+ var_values: &mut LexicalRegionResolutions<'tcx>,
+ ) -> bool {
+ // Note: we don't use the `any` combinator because we don't
+ // want to stop at the first constraint that makes a change.
+ let mut any_changed = false;
+ for member_constraint in &self.data.member_constraints {
+ if self.enforce_member_constraint(graph, member_constraint, var_values) {
+ any_changed = true;
+ }
+ }
+ any_changed
+ }
+
+ /// Enforce a constraint like
+ ///
+ /// ```
+ /// 'r member of ['c...]
+ /// ```
+ ///
+ /// We look for all choice regions from the list `'c...` that:
+ ///
+ /// (a) are greater than the current value of `'r` (which is a lower bound)
+ ///
+ /// and
+ ///
+ /// (b) are compatible with the upper bounds of `'r` that we can
+ /// find by traversing the graph.
+ ///
+ /// From that list, we look for a *minimal* option `'c_min`. If we
+ /// find one, then we can enforce that `'r: 'c_min`.
+ fn enforce_member_constraint(
+ &self,
+ graph: &RegionGraph<'tcx>,
+ member_constraint: &MemberConstraint<'tcx>,
+ var_values: &mut LexicalRegionResolutions<'tcx>,
+ ) -> bool {
+ debug!("enforce_member_constraint(member_constraint={:#?})", member_constraint);
+
+ // The constraint is some inference variable (`vid`) which
+ // must be equal to one of the options.
+ let member_vid = match member_constraint.member_region {
+ ty::ReVar(vid) => *vid,
+ _ => return false,
+ };
+
+ // The current value of `vid` is a lower bound LB -- i.e., we
+ // know that `LB <= vid` must be true.
+ let member_lower_bound: ty::Region<'tcx> = match var_values.value(member_vid) {
+ VarValue::ErrorValue => return false,
+ VarValue::Value(r) => r,
+ };
+
+ // Find all the "upper bounds" -- that is, each region `b` such that
+ // `r0 <= b` must hold.
+ let (member_upper_bounds, _) = self.collect_concrete_regions(
+ graph,
+ member_vid,
+ OUTGOING,
+ None,
+ );
+
+ // Get an iterator over the *available choice* -- that is,
+ // each choice region `c` where `lb <= c` and `c <= ub` for all the
+ // upper bounds `ub`.
+ debug!("enforce_member_constraint: upper_bounds={:#?}", member_upper_bounds);
+ let mut options = member_constraint.choice_regions.iter().filter(|option| {
+ self.sub_concrete_regions(member_lower_bound, option)
+ && member_upper_bounds
+ .iter()
+ .all(|upper_bound| self.sub_concrete_regions(option, upper_bound.region))
+ });
+
+ // If there is more than one option, we only make a choice if
+ // there is a single *least* choice -- i.e., some available
+ // region that is `<=` all the others.
+ let mut least_choice: ty::Region<'tcx> = match options.next() {
+ Some(&r) => r,
+ None => return false,
+ };
+ debug!("enforce_member_constraint: least_choice={:?}", least_choice);
+ for &option in options {
+ debug!("enforce_member_constraint: option={:?}", option);
+ if !self.sub_concrete_regions(least_choice, option) {
+ if self.sub_concrete_regions(option, least_choice) {
+ debug!("enforce_member_constraint: new least choice");
+ least_choice = option;
+ } else {
+ debug!("enforce_member_constraint: no least choice");
+ return false;
+ }
+ }
+ }
+
+ debug!("enforce_member_constraint: final least choice = {:?}", least_choice);
+ if least_choice != member_lower_bound {
+ *var_values.value_mut(member_vid) = VarValue::Value(least_choice);
+ true
+ } else {
+ false
+ }
+ }
+
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
self.iterate_until_fixed_point("Expansion", |constraint| {
debug!("expansion: constraint={:?}", constraint);
let b_data = var_values.value_mut(b_vid);
let retain = match *b_data {
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
- _ => true
+ _ => true,
};
(a_region, b_vid, b_data, retain)
}
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
// These constraints are checked after expansion
// is done, in `collect_errors`.
- return (false, false)
+ return (false, false);
}
};
match *a_region {
// Check if this relationship is implied by a given.
- ty::ReEarlyBound(_) | ty::ReFree(_) => if self.data.givens.contains(&(a_region, b_vid))
- {
- debug!("given");
- return false;
- },
+ ty::ReEarlyBound(_) | ty::ReFree(_) => {
+ if self.data.givens.contains(&(a_region, b_vid)) {
+ debug!("given");
+ return false;
+ }
+ }
_ => {}
}
-
match *b_data {
VarValue::Value(cur_region) => {
// Identical scopes can show up quite often, if the fixed point
}
}
- debug!(
- "Expanding value of {:?} from {:?} to {:?}",
- b_vid, cur_region, lub
- );
+ debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
*b_data = VarValue::Value(lub);
return true;
}
}
+ /// True if `a <= b`, but not defined over inference variables.
+ fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
+ self.lub_concrete_regions(a, b) == b
+ }
+
+ /// Returns the smallest region `c` such that `a <= c` and `b <= c`.
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
let tcx = self.tcx();
// at least as big as fr.scope". So, we can
// reasonably compare free regions and scopes:
let fr_scope = match (a, b) {
- (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => self.region_rels
- .region_scope_tree
- .early_free_scope(self.tcx(), br),
- (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => self.region_rels
- .region_scope_tree
- .free_scope(self.tcx(), fr),
+ (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
+ self.region_rels.region_scope_tree.early_free_scope(self.tcx(), br)
+ }
+ (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
+ self.region_rels.region_scope_tree.free_scope(self.tcx(), fr)
+ }
_ => bug!(),
};
- let r_id = self.region_rels
- .region_scope_tree
- .nearest_common_ancestor(fr_scope, s_id);
+ let r_id =
+ self.region_rels.region_scope_tree.nearest_common_ancestor(fr_scope, s_id);
if r_id == fr_scope {
// if the free region's scope `fr.scope` is bigger than
// the scope region `s_id`, then the LUB is the free
// The region corresponding to an outer block is a
// subtype of the region corresponding to an inner
// block.
- let lub = self.region_rels
- .region_scope_tree
- .nearest_common_ancestor(a_id, b_id);
+ let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id);
tcx.mk_region(ReScope(lub))
}
// For these types, we cannot define any additional
// relationship:
- (&RePlaceholder(..), _) | (_, &RePlaceholder(..)) => if a == b {
- a
- } else {
- tcx.lifetimes.re_static
- },
+ (&RePlaceholder(..), _) | (_, &RePlaceholder(..)) => {
+ if a == b {
+ a
+ } else {
+ tcx.lifetimes.re_static
+ }
+ }
}
}
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
for (constraint, origin) in &self.data.constraints {
- debug!(
- "collect_errors: constraint={:?} origin={:?}",
- constraint, origin
- );
+ debug!("collect_errors: constraint={:?} origin={:?}", constraint, origin);
match *constraint {
Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
// Expansion will ensure that these constraints hold. Ignore.
}
}
+ // Check that all member constraints are satisfied.
+ for member_constraint in &self.data.member_constraints {
+ let member_region = var_data.normalize(self.tcx(), member_constraint.member_region);
+ let choice_regions = member_constraint
+ .choice_regions
+ .iter()
+ .map(|&choice_region| var_data.normalize(self.tcx(), choice_region));
+ if !choice_regions.clone().any(|choice_region| member_region == choice_region) {
+ let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
+ errors.push(RegionResolutionError::MemberConstraintFailure {
+ span,
+ opaque_type_def_id: member_constraint.opaque_type_def_id,
+ hidden_ty: member_constraint.hidden_ty,
+ member_region,
+ choice_regions: choice_regions.collect(),
+ });
+ }
+ }
+
for verify in &self.data.verifys {
debug!("collect_errors: verify={:?}", verify);
let sub = var_data.normalize(self.tcx(), verify.region);
// idea is to report errors that derive from independent
// regions of the graph, but not those that derive from
// overlapping locations.
- let mut dup_vec = vec![u32::MAX; self.num_vars()];
+ let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
for (node_vid, value) in var_data.values.iter_enumerated() {
match *value {
VarValue::Value(_) => { /* Inference successful */ }
VarValue::ErrorValue => {
- /* Inference impossible: this value contains
- inconsistent constraints.
-
- I think that in this case we should report an
- error now -- unlike the case above, we can't
- wait to see whether the user needs the result
- of this variable. The reason is that the mere
- existence of this variable implies that the
- region graph is inconsistent, whether or not it
- is used.
-
- For example, we may have created a region
- variable that is the GLB of two other regions
- which do not have a GLB. Even if that variable
- is not used, it implies that those two regions
- *should* have a GLB.
-
- At least I think this is true. It may be that
- the mere existence of a conflict in a region variable
- that is not used is not a problem, so if this rule
- starts to create problems we'll have to revisit
- this portion of the code and think hard about it. =) */
+ // Inference impossible: this value contains
+ // inconsistent constraints.
+ //
+ // I think that in this case we should report an
+ // error now -- unlike the case above, we can't
+ // wait to see whether the user needs the result
+ // of this variable. The reason is that the mere
+ // existence of this variable implies that the
+ // region graph is inconsistent, whether or not it
+ // is used.
+ //
+ // For example, we may have created a region
+ // variable that is the GLB of two other regions
+ // which do not have a GLB. Even if that variable
+ // is not used, it implies that those two regions
+ // *should* have a GLB.
+ //
+ // At least I think this is true. It may be that
+ // the mere existence of a conflict in a region
+ // variable that is not used is not a problem, so
+ // if this rule starts to create problems we'll
+ // have to revisit this portion of the code and
+ // think hard about it. =) -- nikomatsakis
self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
}
}
fn collect_error_for_expanding_node(
&self,
graph: &RegionGraph<'tcx>,
- dup_vec: &mut [u32],
+ dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
node_idx: RegionVid,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
// Errors in expanding nodes result from a lower-bound that is
// not contained by an upper-bound.
let (mut lower_bounds, lower_dup) =
- self.collect_concrete_regions(graph, node_idx, INCOMING, dup_vec);
+ self.collect_concrete_regions(graph, node_idx, INCOMING, Some(dup_vec));
let (mut upper_bounds, upper_dup) =
- self.collect_concrete_regions(graph, node_idx, OUTGOING, dup_vec);
+ self.collect_concrete_regions(graph, node_idx, OUTGOING, Some(dup_vec));
if lower_dup || upper_dup {
return;
};
for upper_bound in &upper_bounds {
- if !self.region_rels
- .is_subregion_of(effective_lower_bound, upper_bound.region)
- {
+ if !self.region_rels.is_subregion_of(effective_lower_bound, upper_bound.region) {
let origin = self.var_infos[node_idx].origin.clone();
debug!(
"region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
graph: &RegionGraph<'tcx>,
orig_node_idx: RegionVid,
dir: Direction,
- dup_vec: &mut [u32],
+ mut dup_vec: Option<&mut IndexVec<RegionVid, Option<RegionVid>>>,
) -> (Vec<RegionAndOrigin<'tcx>>, bool) {
struct WalkState<'tcx> {
set: FxHashSet<RegionVid>,
let node_idx = state.stack.pop().unwrap();
// check whether we've visited this node on some previous walk
- if dup_vec[node_idx.index() as usize] == u32::MAX {
- dup_vec[node_idx.index() as usize] = orig_node_idx.index() as u32;
- } else if dup_vec[node_idx.index() as usize] != orig_node_idx.index() as u32 {
- state.dup_found = true;
- }
+ if let Some(dup_vec) = &mut dup_vec {
+ if dup_vec[node_idx].is_none() {
+ dup_vec[node_idx] = Some(orig_node_idx);
+ } else if dup_vec[node_idx] != Some(orig_node_idx) {
+ state.dup_found = true;
+ }
- debug!(
- "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
- orig_node_idx, node_idx
- );
+ debug!(
+ "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
+ orig_node_idx, node_idx
+ );
+ }
process_edges(&self.data, &mut state, graph, node_idx, dir);
}
- let WalkState {
- result, dup_found, ..
- } = state;
+ let WalkState { result, dup_found, .. } = state;
return (result, dup_found);
fn process_edges<'tcx>(
for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
match edge.data {
Constraint::VarSubVar(from_vid, to_vid) => {
- let opp_vid = if from_vid == source_vid {
- to_vid
- } else {
- from_vid
- };
+ let opp_vid = if from_vid == source_vid { to_vid } else { from_vid };
if state.set.insert(opp_vid) {
state.stack.push(opp_vid);
}
}
fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
- where F: FnMut(&Constraint<'tcx>) -> (bool, bool),
+ where
+ F: FnMut(&Constraint<'tcx>) -> (bool, bool),
{
let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
let mut iteration = 0;
&& self.bound_is_met(b, var_values, generic_ty, min)
}
- VerifyBound::OutlivedBy(r) =>
- self.region_rels.is_subregion_of(
- min,
- var_values.normalize(self.tcx(), r),
- ),
+ VerifyBound::OutlivedBy(r) => {
+ self.region_rels.is_subregion_of(min, var_values.normalize(self.tcx(), r))
+ }
- VerifyBound::AnyBound(bs) => bs.iter()
- .any(|b| self.bound_is_met(b, var_values, generic_ty, min)),
+ VerifyBound::AnyBound(bs) => {
+ bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
+ }
- VerifyBound::AllBounds(bs) => bs.iter()
- .all(|b| self.bound_is_met(b, var_values, generic_ty, min)),
+ VerifyBound::AllBounds(bs) => {
+ bs.iter().all(|b| self.bound_is_met(b, var_values, generic_ty, min))
+ }
}
}
}
use crate::util::nodemap::FxHashMap;
use errors::DiagnosticBuilder;
+use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unify as ut;
use std::cell::{Cell, Ref, RefCell, RefMut};
use std::collections::BTreeMap;
.make_subregion(origin, a, b);
}
+ /// Require that the region `r` be equal to one of the regions in
+ /// the set `regions`.
+ pub fn member_constraint(
+ &self,
+ opaque_type_def_id: DefId,
+ definition_span: Span,
+ hidden_ty: Ty<'tcx>,
+ region: ty::Region<'tcx>,
+ in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
+ ) {
+ debug!("member_constraint({:?} <: {:?})", region, in_regions);
+ self.borrow_region_constraints()
+ .member_constraint(opaque_type_def_id, definition_span, hidden_ty, region, in_regions);
+ }
+
pub fn subtype_predicate(
&self,
cause: &ObligationCause<'tcx>,
// Even if the type may have no inference variables, during
// type-checking closure types are in local tables only.
if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
- if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
+ if !(param_env, ty).has_local_value() {
return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span);
}
}
// been fully instantiated and hence the set of scopes we have
// doesn't matter -- just to be sure, put an empty vector
// in there.
- let old_a_scopes = ::std::mem::replace(pair.vid_scopes(self), vec![]);
+ let old_a_scopes = ::std::mem::take(pair.vid_scopes(self));
// Relate the generalized kind to the original one.
let result = pair.relate_generalized_ty(self, generalized_ty);
-use rustc_data_structures::fx::FxHashMap;
-use syntax_pos::Span;
-
-use crate::hir::def_id::DefId;
use crate::hir;
+use crate::hir::def_id::DefId;
use crate::hir::Node;
-use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::outlives::free_region_map::FreeRegionRelations;
+use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
+use crate::middle::region;
use crate::traits::{self, PredicateObligation};
-use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind};
use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
+use crate::ty::subst::{InternalSubsts, Kind, SubstsRef, UnpackedKind};
+use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt};
use crate::util::nodemap::DefIdMap;
+use errors::DiagnosticBuilder;
+use rustc::session::config::nightly_options;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use syntax_pos::Span;
pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
/// then `substs` would be `['a, T]`.
pub substs: SubstsRef<'tcx>,
+ /// The span of this particular definition of the opaque type. So
+ /// for example:
+ ///
+ /// ```
+ /// existential type Foo;
+ /// fn bar() -> Foo {
+ /// ^^^ This is the span we are looking for!
+ /// ```
+ ///
+ /// In cases where the fn returns `(impl Trait, impl Trait)` or
+ /// other such combinations, the result is currently
+ /// over-approximated, but better than nothing.
+ pub definition_span: Span,
+
/// The type variable that represents the value of the abstract type
/// that we require. In other words, after we compile this function,
/// we will be created a constraint like:
/// - `param_env` -- the in-scope parameter environment to be used for
/// obligations
/// - `value` -- the value within which we are instantiating opaque types
+ /// - `value_span` -- the span where the value came from, used in error reporting
pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self,
parent_def_id: DefId,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
value: &T,
+ value_span: Span,
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
- debug!("instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
- param_env={:?})",
- value, parent_def_id, body_id, param_env,
+ debug!(
+ "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
+ param_env={:?})",
+ value, parent_def_id, body_id, param_env,
);
let mut instantiator = Instantiator {
infcx: self,
parent_def_id,
body_id,
param_env,
+ value_span,
opaque_types: Default::default(),
obligations: vec![],
};
let value = instantiator.instantiate_opaque_types_in_map(value);
- InferOk {
- value: (value, instantiator.opaque_types),
- obligations: instantiator.obligations,
- }
+ InferOk { value: (value, instantiator.opaque_types), obligations: instantiator.obligations }
}
/// Given the map `opaque_types` containing the existential `impl
///
/// # The Solution
///
- /// We make use of the constraint that we *do* have in the `<=`
- /// relation. To do that, we find the "minimum" of all the
- /// arguments that appear in the substs: that is, some region
- /// which is less than all the others. In the case of `Foo1<'a>`,
- /// that would be `'a` (it's the only choice, after all). Then we
- /// apply that as a least bound to the variables (e.g., `'a <=
- /// '0`).
+ /// We generally prefer to make `<=` constraints, since they
+ /// integrate best into the region solver. To do that, we find the
+ /// "minimum" of all the arguments that appear in the substs: that
+ /// is, some region which is less than all the others. In the case
+ /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
+ /// all). Then we apply that as a least bound to the variables
+ /// (e.g., `'a <= '0`).
///
/// In some cases, there is no minimum. Consider this example:
///
/// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
/// ```
///
- /// Here we would report an error, because `'a` and `'b` have no
- /// relation to one another.
+ /// Here we would report a more complex "in constraint", like `'r
+ /// in ['a, 'b, 'static]` (where `'r` is some regon appearing in
+ /// the hidden type).
+ ///
+ /// # Constrain regions, not the hidden concrete type
+ ///
+ /// Note that generating constraints on each region `Rc` is *not*
+ /// the same as generating an outlives constraint on `Tc` iself.
+ /// For example, if we had a function like this:
+ ///
+ /// ```rust
+ /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
+ /// (x, y)
+ /// }
+ ///
+ /// // Equivalent to:
+ /// existential type FooReturn<'a, T>: Foo<'a>;
+ /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
+ /// ```
+ ///
+ /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
+ /// is an inference variable). If we generated a constraint that
+ /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
+ /// but this is not necessary, because the existential type we
+ /// create will be allowed to reference `T`. So we only generate a
+ /// constraint that `'0: 'a`.
///
/// # The `free_region_relations` parameter
///
}
}
+ /// See `constrain_opaque_types` for documentation.
pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
&self,
def_id: DefId,
debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
- let abstract_type_generics = tcx.generics_of(def_id);
+ let opaque_type_generics = tcx.generics_of(def_id);
let span = tcx.def_span(def_id);
// If there are required region bounds, we can use them.
if opaque_defn.has_required_region_bounds {
let predicates_of = tcx.predicates_of(def_id);
- debug!(
- "constrain_opaque_type: predicates: {:#?}",
- predicates_of,
- );
+ debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
debug!("constrain_opaque_type: bounds={:#?}", bounds);
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
- let required_region_bounds = tcx.required_region_bounds(
- opaque_type,
- bounds.predicates,
- );
+ let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates);
debug_assert!(!required_region_bounds.is_empty());
- for region in required_region_bounds {
- concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor {
- infcx: self,
- least_region: region,
- span,
+ for required_region in required_region_bounds {
+ concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+ tcx: self.tcx,
+ op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
});
}
return;
// `['a]` for the first impl trait and `'b` for the
// second.
let mut least_region = None;
- for param in &abstract_type_generics.params {
+ for param in &opaque_type_generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {}
- _ => continue
+ _ => continue,
}
+
// Get the value supplied for this region from the substs.
let subst_arg = opaque_defn.substs.region_at(param.index as usize);
least_region = Some(subst_arg);
} else {
// There are two regions (`lr` and
- // `subst_arg`) which are not relatable. We can't
- // find a best choice.
- let context_name = match opaque_defn.origin {
- hir::ExistTyOrigin::ExistentialType => "existential type",
- hir::ExistTyOrigin::ReturnImplTrait => "impl Trait",
- hir::ExistTyOrigin::AsyncFn => "async fn",
- };
- let msg = format!("ambiguous lifetime bound in `{}`", context_name);
- let mut err = self.tcx
- .sess
- .struct_span_err(span, &msg);
-
- let lr_name = lr.to_string();
- let subst_arg_name = subst_arg.to_string();
- let label_owned;
- let label = match (&*lr_name, &*subst_arg_name) {
- ("'_", "'_") => "the elided lifetimes here do not outlive one another",
- _ => {
- label_owned = format!(
- "neither `{}` nor `{}` outlives the other",
- lr_name,
- subst_arg_name,
- );
- &label_owned
- }
- };
- err.span_label(span, label);
-
- if let hir::ExistTyOrigin::AsyncFn = opaque_defn.origin {
- err.note("multiple unrelated lifetimes are not allowed in \
- `async fn`.");
- err.note("if you're using argument-position elided lifetimes, consider \
- switching to a single named lifetime.");
- }
- err.emit();
-
- least_region = Some(self.tcx.mk_region(ty::ReEmpty));
- break;
+ // `subst_arg`) which are not relatable. We
+ // can't find a best choice. Therefore,
+ // instead of creating a single bound like
+ // `'r: 'a` (which is our preferred choice),
+ // we will create a "in bound" like `'r in
+ // ['a, 'b, 'c]`, where `'a..'c` are the
+ // regions that appear in the impl trait.
+ return self.generate_member_constraint(
+ concrete_ty,
+ opaque_type_generics,
+ opaque_defn,
+ def_id,
+ lr,
+ subst_arg,
+ );
}
}
}
let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
debug!("constrain_opaque_types: least_region={:?}", least_region);
- concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor {
- infcx: self,
- least_region,
- span,
+ concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+ tcx: self.tcx,
+ op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
});
}
+ /// As a fallback, we sometimes generate an "in constraint". For
+ /// a case like `impl Foo<'a, 'b>`, where `'a` and `'b` cannot be
+ /// related, we would generate a constraint `'r in ['a, 'b,
+ /// 'static]` for each region `'r` that appears in the hidden type
+ /// (i.e., it must be equal to `'a`, `'b`, or `'static`).
+ ///
+ /// `conflict1` and `conflict2` are the two region bounds that we
+ /// detected which were unrelated. They are used for diagnostics.
+ fn generate_member_constraint(
+ &self,
+ concrete_ty: Ty<'tcx>,
+ opaque_type_generics: &ty::Generics,
+ opaque_defn: &OpaqueTypeDecl<'tcx>,
+ opaque_type_def_id: DefId,
+ conflict1: ty::Region<'tcx>,
+ conflict2: ty::Region<'tcx>,
+ ) {
+ // For now, enforce a feature gate outside of async functions.
+ if self.member_constraint_feature_gate(
+ opaque_defn,
+ opaque_type_def_id,
+ conflict1,
+ conflict2,
+ ) {
+ return;
+ }
+
+ // Create the set of choice regions: each region in the hidden
+ // type can be equal to any of the region parameters of the
+ // opaque type definition.
+ let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
+ opaque_type_generics
+ .params
+ .iter()
+ .filter(|param| match param.kind {
+ GenericParamDefKind::Lifetime => true,
+ GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => false,
+ })
+ .map(|param| opaque_defn.substs.region_at(param.index as usize))
+ .chain(std::iter::once(self.tcx.lifetimes.re_static))
+ .collect(),
+ );
+
+ concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+ tcx: self.tcx,
+ op: |r| self.member_constraint(
+ opaque_type_def_id,
+ opaque_defn.definition_span,
+ concrete_ty,
+ r,
+ &choice_regions,
+ ),
+ });
+ }
+
+ /// Member constraints are presently feature-gated except for
+ /// async-await. We expect to lift this once we've had a bit more
+ /// time.
+ fn member_constraint_feature_gate(
+ &self,
+ opaque_defn: &OpaqueTypeDecl<'tcx>,
+ opaque_type_def_id: DefId,
+ conflict1: ty::Region<'tcx>,
+ conflict2: ty::Region<'tcx>,
+ ) -> bool {
+ // If we have `#![feature(member_constraints)]`, no problems.
+ if self.tcx.features().member_constraints {
+ return false;
+ }
+
+ let span = self.tcx.def_span(opaque_type_def_id);
+
+ // Without a feature-gate, we only generate member-constraints for async-await.
+ let context_name = match opaque_defn.origin {
+ // No feature-gate required for `async fn`.
+ hir::ExistTyOrigin::AsyncFn => return false,
+
+ // Otherwise, generate the label we'll use in the error message.
+ hir::ExistTyOrigin::ExistentialType => "existential type",
+ hir::ExistTyOrigin::ReturnImplTrait => "impl Trait",
+ };
+ let msg = format!("ambiguous lifetime bound in `{}`", context_name);
+ let mut err = self.tcx.sess.struct_span_err(span, &msg);
+
+ let conflict1_name = conflict1.to_string();
+ let conflict2_name = conflict2.to_string();
+ let label_owned;
+ let label = match (&*conflict1_name, &*conflict2_name) {
+ ("'_", "'_") => "the elided lifetimes here do not outlive one another",
+ _ => {
+ label_owned = format!(
+ "neither `{}` nor `{}` outlives the other",
+ conflict1_name, conflict2_name,
+ );
+ &label_owned
+ }
+ };
+ err.span_label(span, label);
+
+ if nightly_options::is_nightly_build() {
+ help!(err,
+ "add #![feature(member_constraints)] to the crate attributes \
+ to enable");
+ }
+
+ err.emit();
+ true
+ }
+
/// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an abstract type
// Convert the type from the function into a type valid outside
// the function, by replacing invalid regions with 'static,
// after producing an error for each of them.
- let definition_ty =
- instantiated_ty.fold_with(&mut ReverseMapper::new(
- self.tcx,
- self.is_tainted_by_errors(),
- def_id,
- map,
- instantiated_ty,
- ));
- debug!(
- "infer_opaque_definition_from_instantiation: definition_ty={:?}",
- definition_ty
- );
+ let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
+ self.tcx,
+ self.is_tainted_by_errors(),
+ def_id,
+ map,
+ instantiated_ty,
+ ));
+ debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
definition_ty
}
}
+pub fn unexpected_hidden_region_diagnostic(
+ tcx: TyCtxt<'tcx>,
+ region_scope_tree: Option<®ion::ScopeTree>,
+ opaque_type_def_id: DefId,
+ hidden_ty: Ty<'tcx>,
+ hidden_region: ty::Region<'tcx>,
+) -> DiagnosticBuilder<'tcx> {
+ let span = tcx.def_span(opaque_type_def_id);
+ let mut err = struct_span_err!(
+ tcx.sess,
+ span,
+ E0700,
+ "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
+ );
+
+ // Explain the region we are capturing.
+ if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty = hidden_region {
+ // Assuming regionck succeeded (*), we ought to always be
+ // capturing *some* region from the fn header, and hence it
+ // ought to be free. So under normal circumstances, we will go
+ // down this path which gives a decent human readable
+ // explanation.
+ //
+ // (*) if not, the `tainted_by_errors` flag would be set to
+ // true in any case, so we wouldn't be here at all.
+ tcx.note_and_explain_free_region(
+ &mut err,
+ &format!("hidden type `{}` captures ", hidden_ty),
+ hidden_region,
+ "",
+ );
+ } else {
+ // Ugh. This is a painful case: the hidden region is not one
+ // that we can easily summarize or explain. This can happen
+ // in a case like
+ // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
+ //
+ // ```
+ // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
+ // if condition() { a } else { b }
+ // }
+ // ```
+ //
+ // Here the captured lifetime is the intersection of `'a` and
+ // `'b`, which we can't quite express.
+
+ if let Some(region_scope_tree) = region_scope_tree {
+ // If the `region_scope_tree` is available, this is being
+ // invoked from the "region inferencer error". We can at
+ // least report a really cryptic error for now.
+ tcx.note_and_explain_region(
+ region_scope_tree,
+ &mut err,
+ &format!("hidden type `{}` captures ", hidden_ty),
+ hidden_region,
+ "",
+ );
+ } else {
+ // If the `region_scope_tree` is *unavailable*, this is
+ // being invoked by the code that comes *after* region
+ // inferencing. This is a bug, as the region inferencer
+ // ought to have noticed the failed constraint and invoked
+ // error reporting, which in turn should have prevented us
+ // from getting trying to infer the hidden type
+ // completely.
+ tcx.sess.delay_span_bug(
+ span,
+ &format!(
+ "hidden type captures unexpected lifetime `{:?}` \
+ but no region inference failure",
+ hidden_region,
+ ),
+ );
+ }
+ }
+
+ err
+}
+
// Visitor that requires that (almost) all regions in the type visited outlive
// `least_region`. We cannot use `push_outlives_components` because regions in
// closure signatures are not included in their outlives components. We need to
//
// We ignore any type parameters because impl trait values are assumed to
// capture all the in-scope type parameters.
-struct OpaqueTypeOutlivesVisitor<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
- least_region: ty::Region<'tcx>,
- span: Span,
+struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+ OP: FnMut(ty::Region<'tcx>),
+{
+ tcx: TyCtxt<'tcx>,
+ op: OP,
}
-impl<'tcx> TypeVisitor<'tcx> for OpaqueTypeOutlivesVisitor<'_, 'tcx> {
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+ OP: FnMut(ty::Region<'tcx>),
+{
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
t.skip_binder().visit_with(self);
false // keep visiting
// ignore bound regions, keep visiting
ty::ReLateBound(_, _) => false,
_ => {
- self.infcx.sub_regions(infer::CallReturn(self.span), self.least_region, r);
+ (self.op)(r);
false
}
}
ty::Closure(def_id, ref substs) => {
// Skip lifetime parameters of the enclosing item(s)
- for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
+ for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
upvar_ty.visit_with(self);
}
- substs.closure_sig_ty(def_id, self.infcx.tcx).visit_with(self);
+ substs.closure_sig_ty(def_id, self.tcx).visit_with(self);
}
ty::Generator(def_id, ref substs, _) => {
// Skip lifetime parameters of the enclosing item(s)
// Also skip the witness type, because that has no free regions.
- for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
+ for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
upvar_ty.visit_with(self);
}
- substs.return_ty(def_id, self.infcx.tcx).visit_with(self);
- substs.yield_ty(def_id, self.infcx.tcx).visit_with(self);
+ substs.return_ty(def_id, self.tcx).visit_with(self);
+ substs.yield_ty(def_id, self.tcx).visit_with(self);
}
_ => {
ty.super_visit_with(self);
None => {
if !self.map_missing_regions_to_empty && !self.tainted_by_errors {
if let Some(hidden_ty) = self.hidden_ty.take() {
- let span = self.tcx.def_span(self.opaque_type_def_id);
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0700,
- "hidden type for `impl Trait` captures lifetime that \
- does not appear in bounds",
- );
-
- // Assuming regionck succeeded, then we must
- // be capturing *some* region from the fn
- // header, and hence it must be free, so it's
- // ok to invoke this fn (which doesn't accept
- // all regions, and would ICE if an
- // inappropriate region is given). We check
- // `is_tainted_by_errors` by errors above, so
- // we don't get in here unless regionck
- // succeeded. (Note also that if regionck
- // failed, then the regions we are attempting
- // to map here may well be giving errors
- // *because* the constraints were not
- // satisfiable.)
- self.tcx.note_and_explain_free_region(
- &mut err,
- &format!("hidden type `{}` captures ", hidden_ty),
+ unexpected_hidden_region_diagnostic(
+ self.tcx,
+ None,
+ self.opaque_type_def_id,
+ hidden_ty,
r,
- ""
- );
-
- err.emit();
+ ).emit();
}
}
self.tcx.lifetimes.re_empty
- },
+ }
}
}
// during codegen.
let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
- |(index, &kind)| {
+ let substs =
+ self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
if index < generics.parent_count {
// Accommodate missing regions in the parent kinds...
self.fold_kind_mapping_missing_regions_to_empty(kind)
// ...but not elsewhere.
self.fold_kind_normally(kind)
}
- },
- ));
+ }));
self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs })
}
ty::Generator(def_id, substs, movability) => {
let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
- |(index, &kind)| {
+ let substs =
+ self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
if index < generics.parent_count {
// Accommodate missing regions in the parent kinds...
self.fold_kind_mapping_missing_regions_to_empty(kind)
// ...but not elsewhere.
self.fold_kind_normally(kind)
}
- },
- ));
+ }));
self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability)
}
parent_def_id: DefId,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
+ value_span: Span,
opaque_types: OpaqueTypeMap<'tcx>,
obligations: Vec<PredicateObligation<'tcx>>,
}
let def_scope_default = || {
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
parent_def_id == tcx.hir()
- .local_def_id_from_hir_id(opaque_parent_hir_id)
+ .local_def_id(opaque_parent_hir_id)
};
- let (in_definition_scope, origin) =
- match tcx.hir().find(opaque_hir_id)
- {
+ let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
Some(Node::Item(item)) => match item.node {
// Anonymous `impl Trait`
hir::ItemKind::Existential(hir::ExistTy {
let infcx = self.infcx;
let tcx = infcx.tcx;
- debug!(
- "instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})",
- def_id, substs
- );
+ debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
// Use the same type variable if the exact same opaque type appears more
// than once in the return type (e.g., if it's passed to a type alias).
return opaque_defn.concrete_ty;
}
let span = tcx.def_span(def_id);
- let ty_var = infcx.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::TypeInference,
- span,
- });
+ let ty_var = infcx
+ .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
let predicates_of = tcx.predicates_of(def_id);
- debug!(
- "instantiate_opaque_types: predicates={:#?}",
- predicates_of,
- );
+ debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
let bounds = predicates_of.instantiate(tcx, substs);
debug!("instantiate_opaque_types: bounds={:?}", bounds);
let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone());
- debug!(
- "instantiate_opaque_types: required_region_bounds={:?}",
- required_region_bounds
- );
+ debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
// Make sure that we are in fact defining the *entire* type
// (e.g., `existential type Foo<T: Bound>: Bar;` needs to be
// defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
- debug!(
- "instantiate_opaque_types: param_env={:#?}",
- self.param_env,
- );
- debug!(
- "instantiate_opaque_types: generics={:#?}",
- tcx.generics_of(def_id),
- );
+ debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
+ debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
+
+ // Ideally, we'd get the span where *this specific `ty` came
+ // from*, but right now we just use the span from the overall
+ // value being folded. In simple cases like `-> impl Foo`,
+ // these are the same span, but not in cases like `-> (impl
+ // Foo, impl Bar)`.
+ let definition_span = self.value_span;
self.opaque_types.insert(
def_id,
OpaqueTypeDecl {
substs,
+ definition_span,
concrete_ty: ty_var,
has_required_region_bounds: !required_region_bounds.is_empty(),
origin,
// Require that the predicate holds for the concrete type.
debug!("instantiate_opaque_types: predicate={:?}", predicate);
- self.obligations
- .push(traits::Obligation::new(cause, self.param_env, predicate));
+ self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
}
ty_var
);
// Named existential types can be defined by any siblings or children of siblings.
- let scope = tcx.hir()
- .get_defining_scope(opaque_hir_id)
- .expect("could not get defining scope");
+ let scope = tcx.hir().get_defining_scope(opaque_hir_id).expect("could not get defining scope");
// We walk up the node tree until we hit the root or the scope of the opaque type.
while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
hir_id = tcx.hir().get_parent_item(hir_id);
}
impl<'tcx> FreeRegionMap<'tcx> {
+ pub fn elements(&self) -> impl Iterator<Item=&Region<'tcx>> {
+ self.relation.elements()
+ }
+
pub fn is_empty(&self) -> bool {
self.relation.is_empty()
}
/// Trait queries just want to pass back type obligations "as is"
pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> {
- ::std::mem::replace(&mut *self.region_obligations.borrow_mut(), vec![])
+ ::std::mem::take(&mut *self.region_obligations.borrow_mut())
}
/// Process the region obligations that must be proven (during
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unify as ut;
+use crate::hir::def_id::DefId;
use crate::ty::ReStatic;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{ReLateBound, ReVar};
use crate::ty::{Region, RegionVid};
+use syntax_pos::Span;
use std::collections::BTreeMap;
use std::{cmp, fmt, mem};
/// be a region variable (or neither, as it happens).
pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
+ /// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that
+ /// `R0` must be equal to one of the regions `R1..Rn`. These occur
+ /// with `impl Trait` quite frequently.
+ pub member_constraints: Vec<MemberConstraint<'tcx>>,
+
/// A "verify" is something that we need to verify after inference
/// is done, but which does not directly affect inference in any
/// way.
}
}
+/// Requires that `region` must be equal to one of the regions in `choice_regions`.
+/// We often denote this using the syntax:
+///
+/// ```
+/// R0 member of [O1..On]
+/// ```
+#[derive(Debug, Clone, HashStable)]
+pub struct MemberConstraint<'tcx> {
+ /// The `DefId` of the opaque type causing this constraint: used for error reporting.
+ pub opaque_type_def_id: DefId,
+
+ /// The span where the hidden type was instantiated.
+ pub definition_span: Span,
+
+ /// The hidden type in which `member_region` appears: used for error reporting.
+ pub hidden_ty: Ty<'tcx>,
+
+ /// The region `R0`.
+ pub member_region: Region<'tcx>,
+
+ /// The options `O1..On`.
+ pub choice_regions: Lrc<Vec<Region<'tcx>>>,
+}
+
+BraceStructTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for MemberConstraint<'tcx> {
+ opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
+ }
+}
+
+BraceStructLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for MemberConstraint<'a> {
+ type Lifted = MemberConstraint<'tcx>;
+ opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
+ }
+}
+
/// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or
/// associated type) must outlive the region `R`. `T` is known to
/// outlive `RS`. Therefore, verify that `R <= RS[i]` for some
*any_unifications = false;
}
- mem::replace(data, RegionConstraintData::default())
+ mem::take(data)
}
pub fn data(&self) -> &RegionConstraintData<'tcx> {
}
}
+ pub fn member_constraint(
+ &mut self,
+ opaque_type_def_id: DefId,
+ definition_span: Span,
+ hidden_ty: Ty<'tcx>,
+ member_region: ty::Region<'tcx>,
+ choice_regions: &Lrc<Vec<ty::Region<'tcx>>>,
+ ) {
+ debug!("member_constraint({:?} in {:#?})", member_region, choice_regions);
+
+ if choice_regions.iter().any(|&r| r == member_region) {
+ return;
+ }
+
+ self.data.member_constraints.push(MemberConstraint {
+ opaque_type_def_id,
+ definition_span,
+ hidden_ty,
+ member_region,
+ choice_regions: choice_regions.clone()
+ });
+
+ }
+
pub fn make_subregion(
&mut self,
origin: SubregionOrigin<'tcx>,
pub fn is_empty(&self) -> bool {
let RegionConstraintData {
constraints,
+ member_constraints,
verifys,
givens,
} = self;
- constraints.is_empty() && verifys.is_empty() && givens.is_empty()
+ constraints.is_empty() &&
+ member_constraints.is_empty() &&
+ verifys.is_empty() &&
+ givens.is_empty()
}
}
///
/// Note that this function does not return care whether
/// `vid` has been unified with something else or not.
- pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
+ pub fn var_diverges(&self, vid: ty::TyVid) -> bool {
self.values.get(vid.index as usize).diverging
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(arbitrary_self_types)]
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(const_fn)]
+#![feature(const_transmute)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(inner_deref)]
#![feature(crate_visibility_modifier)]
#![feature(proc_macro_hygiene)]
#![feature(log_syntax)]
+#![feature(mem_take)]
#![recursion_limit="512"]
{
let old_param_env = self.context.param_env;
self.context.param_env = self.context.tcx.param_env(
- self.context.tcx.hir().local_def_id_from_hir_id(id)
+ self.context.tcx.hir().local_def_id(id)
);
f(self);
self.context.param_env = old_param_env;
lints: &'a mut [LateLintPassObject],
}
+#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))]
impl LintPass for LateLintPassObjects<'_> {
fn name(&self) -> &'static str {
panic!()
time(tcx.sess, "module lints", || {
// Run per-module lints
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
- tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
+ tcx.ensure().lint_mod(tcx.hir().local_def_id_from_node_id(module));
});
});
});
lints: &'a mut [EarlyLintPassObject],
}
+#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))]
impl LintPass for EarlyLintPassObjects<'_> {
fn name(&self) -> &'static str {
panic!()
};
use errors::Applicability;
use rustc_data_structures::fx::FxHashMap;
-use syntax::ast::Ident;
+use syntax::ast::{Ident, Item, ItemKind};
use syntax::symbol::{sym, Symbol};
+use syntax_pos::ExpnInfo;
-declare_lint! {
- pub DEFAULT_HASH_TYPES,
+declare_tool_lint! {
+ pub rustc::DEFAULT_HASH_TYPES,
Allow,
"forbid HashMap and HashSet and suggest the FxHash* variants"
}
impl DefaultHashTypes {
// we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself
- #[allow(internal)]
+ #[cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
pub fn new() -> Self {
let mut map = FxHashMap::default();
map.insert(sym::HashMap, sym::FxHashMap);
impl EarlyLintPass for DefaultHashTypes {
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
if let Some(replace) = self.map.get(&ident.name) {
- let msg = format!(
- "Prefer {} over {}, it has better performance",
- replace, ident
- );
+ let msg = format!("Prefer {} over {}, it has better performance", replace, ident);
let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
db.span_suggestion(
ident.span,
replace.to_string(),
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
);
- db.note(&format!(
- "a `use rustc_data_structures::fx::{}` may be necessary",
- replace
- ))
- .emit();
+ db.note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace))
+ .emit();
}
}
}
-declare_lint! {
- pub USAGE_OF_TY_TYKIND,
+declare_tool_lint! {
+ pub rustc::USAGE_OF_TY_TYKIND,
Allow,
"usage of `ty::TyKind` outside of the `ty::sty` module"
}
-declare_lint! {
- pub TY_PASS_BY_REFERENCE,
+declare_tool_lint! {
+ pub rustc::TY_PASS_BY_REFERENCE,
Allow,
"passing `Ty` or `TyCtxt` by reference"
}
-declare_lint! {
- pub USAGE_OF_QUALIFIED_TY,
+declare_tool_lint! {
+ pub rustc::USAGE_OF_QUALIFIED_TY,
Allow,
"using `ty::{Ty,TyCtxt}` instead of importing it"
}
}
}
}
- TyKind::Rptr(
- _,
- MutTy {
- ty: inner_ty,
- mutbl: Mutability::MutImmutable,
- },
- ) => {
+ TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::MutImmutable }) => {
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
if cx.tcx.impl_trait_ref(impl_did).is_some() {
return;
String::new()
}
+
+declare_tool_lint! {
+ pub rustc::LINT_PASS_IMPL_WITHOUT_MACRO,
+ Allow,
+ "`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros"
+}
+
+declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
+
+impl EarlyLintPass for LintPassImpl {
+ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+ if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node {
+ if let Some(last) = lint_pass.path.segments.last() {
+ if last.ident.name == sym::LintPass {
+ match &lint_pass.path.span.ctxt().outer_expn_info() {
+ Some(info) if is_lint_pass_expansion(info) => {}
+ _ => {
+ cx.struct_span_lint(
+ LINT_PASS_IMPL_WITHOUT_MACRO,
+ lint_pass.path.span,
+ "implementing `LintPass` by hand",
+ )
+ .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
+ .emit();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
+ if expn_info.format.name() == sym::impl_lint_pass {
+ true
+ } else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
+ info.format.name() == sym::declare_lint_pass
+ } else {
+ false
+ }
+}
attrs.iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some())
}
-fn lint_levels<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx LintLevelMap {
+fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
assert_eq!(cnum, LOCAL_CRATE);
let mut builder = LintLevelMapBuilder {
levels: LintLevelSets::builder(tcx.sess),
fn crates_untracked(&self) -> Vec<CrateNum>;
// utility functions
- fn encode_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>) -> EncodedMetadata;
+ fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
fn metadata_encoding_version(&self) -> &[u8];
}
// explored. For example, if it's a live Node::Item that is a
// function, then we should explore its block to check for codes that
// may need to be marked as live.
-fn should_explore<'tcx>(tcx: TyCtxt<'tcx>, hir_id: hir::HirId) -> bool {
+fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
match tcx.hir().find(hir_id) {
Some(Node::Item(..)) |
Some(Node::ImplItem(..)) |
Node::Item(item) => {
match item.node {
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let def = self.tcx.adt_def(def_id);
self.repr_has_repr_c = def.repr.c();
return true;
}
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
let cg_attrs = tcx.codegen_fn_attrs(def_id);
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
}
fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
- let field_type = self.tcx.type_of(self.tcx.hir().local_def_id_from_hir_id(field.hir_id));
+ let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id));
!field.is_positional()
&& !self.symbol_is_live(field.hir_id)
&& !field_type.is_phantom_data()
// This is done to handle the case where, for example, the static
// method of a private type is used, but the type itself is never
// called directly.
- let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = self.tcx.hir().local_def_id(id);
let inherent_impls = self.tcx.inherent_impls(def_id);
for &impl_did in inherent_impls.iter() {
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
}
}
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_crate(tcx: TyCtxt<'_>) {
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
let krate = tcx.hir().krate();
let live_symbols = find_live(tcx, access_levels, krate);
Dynamic,
}
-pub fn calculate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn calculate(tcx: TyCtxt<'_>) {
let sess = &tcx.sess;
let fmts = sess.crate_types.borrow().iter().map(|&ty| {
let linkage = calculate_type(tcx, ty);
sess.dependency_formats.set(fmts);
}
-fn calculate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: config::CrateType) -> DependencyList {
+fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
let sess = &tcx.sess;
if !sess.opts.output_types.should_codegen() {
}
}
-fn attempt_static<'tcx>(tcx: TyCtxt<'tcx>) -> Option<DependencyList> {
+fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
let sess = &tcx.sess;
let crates = cstore::used_crates(tcx, RequireStatic);
if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
// After the linkage for a crate has been determined we need to verify that
// there's only going to be one allocator in the output.
-fn verify_ok<'tcx>(tcx: TyCtxt<'tcx>, list: &[Linkage]) {
+fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
let sess = &tcx.sess;
if list.len() == 0 {
return
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx Item) {
- let def_id = self.map.local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.map.local_def_id(item.hir_id);
let def_key = self.map.def_key(def_id);
let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
find_item(item, self, at_root);
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> {
if let Some((hir_id, _)) = visitor.start_fn {
- Some((tcx.hir().local_def_id_from_hir_id(hir_id), EntryFnType::Start))
+ Some((tcx.hir().local_def_id(hir_id), EntryFnType::Start))
} else if let Some((hir_id, _)) = visitor.attr_main_fn {
- Some((tcx.hir().local_def_id_from_hir_id(hir_id), EntryFnType::Main))
+ Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
} else if let Some((hir_id, _)) = visitor.main_fn {
- Some((tcx.hir().local_def_id_from_hir_id(hir_id), EntryFnType::Main))
+ Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
} else {
// No main function
let mut err = struct_err!(tcx.sess, E0601,
use crate::hir::def::{CtorOf, Res, DefKind};
use crate::hir::def_id::DefId;
+use crate::hir::ptr::P;
use crate::infer::InferCtxt;
use crate::middle::mem_categorization as mc;
use crate::middle::region;
use crate::hir::{self, PatKind};
use std::rc::Rc;
-use syntax::ptr::P;
use syntax_pos::Span;
use crate::util::nodemap::ItemLocalSet;
fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) {
debug!("walk_captures({:?})", closure_expr);
- let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id);
+ let closure_def_id = self.tcx().hir().local_def_id(closure_expr.hir_id);
if let Some(upvars) = self.tcx().upvars(closure_def_id) {
for (&var_id, upvar) in upvars.iter() {
let upvar_id = ty::UpvarId {
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir;
-fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
&mut ItemVisitor { tcx }.as_deep_visitor()
match self.item_refs.get(&*value.as_str()).cloned() {
// Known lang item with attribute on correct target.
Some((item_index, expected_target)) if actual_target == expected_target => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
self.collect_item(item_index, def_id);
},
// Known lang item with attribute on incorrect target.
}
}
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LibFeatures {
+pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
let mut collector = LibFeatureCollector::new(tcx);
intravisit::walk_crate(&mut collector, tcx.hir().krate());
collector.lib_features
use crate::hir::def::*;
use crate::hir::Node;
+use crate::hir::ptr::P;
use crate::ty::{self, TyCtxt};
use crate::ty::query::Providers;
use crate::lint;
use std::io;
use std::rc::Rc;
use syntax::ast;
-use syntax::ptr::P;
use syntax::symbol::{kw, sym};
use syntax_pos::Span;
fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
}
-fn check_mod_liveness<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
&mut IrMaps::new(tcx, module_def_id).as_deep_visitor(),
debug!("visit_fn");
// swap in a new set of IR maps for this function body:
- let def_id = ir.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = ir.tcx.hir().local_def_id(id);
let mut fn_maps = IrMaps::new(ir.tcx, def_id);
// Don't run unused pass for #[derive()]
// in better error messages than just pointing at the closure
// construction site.
let mut call_caps = Vec::new();
- let closure_def_id = ir.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
+ let closure_def_id = ir.tcx.hir().local_def_id(expr.hir_id);
if let Some(upvars) = ir.tcx.upvars(closure_def_id) {
let parent_upvars = ir.tcx.upvars(ir.body_owner);
call_caps.extend(upvars.iter().filter_map(|(&var_id, upvar)| {
) -> bool {
self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span))
.or_else(|| {
- self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| {
- ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span)
- })
+ if (param_env, ty).has_local_value() {
+ None
+ } else {
+ Some(ty.is_copy_modulo_regions(self.tcx, param_env, span))
+ }
})
.unwrap_or(true)
}
match item.node {
hir::ItemKind::Impl(..) |
hir::ItemKind::Fn(..) => {
- let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
generics.requires_monomorphization(tcx)
}
_ => false,
}
}
-fn method_might_be_inlined<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn method_might_be_inlined(
+ tcx: TyCtxt<'_>,
impl_item: &hir::ImplItem,
impl_src: DefId,
) -> bool {
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
- let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(impl_item.hir_id));
+ let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.hir_id));
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
return true
}
} else {
false
};
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
let is_extern = codegen_attrs.contains_extern_indicator();
let std_internal = codegen_attrs.flags.contains(
Node::Item(item) => {
match item.node {
hir::ItemKind::Fn(.., body) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
if item_might_be_inlined(self.tcx,
&item,
self.tcx.codegen_fn_attrs(def_id)) {
// Anything which has custom linkage gets thrown on the worklist no
// matter where it is in the crate, along with "special std symbols"
// which are currently akin to allocator symbols.
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
if codegen_attrs.contains_extern_indicator() ||
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
#[derive(Clone, HashStable)]
pub struct ReachableSet(pub Lrc<HirIdSet>);
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> ReachableSet {
+fn reachable_set(tcx: TyCtxt<'_>, crate_num: CrateNum) -> ReachableSet {
debug_assert!(crate_num == LOCAL_CRATE);
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
&format!("free_scope: {:?} not recognized by the \
region scope tree for {:?} / {:?}",
param_owner,
- self.root_parent.map(|id| tcx.hir().local_def_id_from_hir_id(id)),
+ self.root_parent.map(|id| tcx.hir().local_def_id(id)),
self.root_body.map(|hir_id| DefId::local(hir_id.owner))));
}
let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
let outer_cx = self.cx;
- let outer_ts = mem::replace(&mut self.terminating_scopes, FxHashSet::default());
+ let outer_ts = mem::take(&mut self.terminating_scopes);
self.terminating_scopes.insert(body.value.hir_id.local_id);
if let Some(root_id) = self.cx.root_id {
}
}
-fn region_scope_tree<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ScopeTree {
+fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
let closure_base_def_id = tcx.closure_base_def_id(def_id);
if closure_base_def_id != def_id {
return tcx.region_scope_tree(closure_base_def_id);
use crate::hir::def::{Res, DefKind};
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use crate::hir::map::Map;
+use crate::hir::ptr::P;
use crate::hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, Node, ParamName};
use crate::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
use rustc_macros::HashStable;
use std::borrow::Cow;
use std::cell::Cell;
-use std::mem::replace;
+use std::mem::{replace, take};
use syntax::ast;
use syntax::attr;
-use syntax::ptr::P;
use syntax::symbol::{kw, sym};
use syntax_pos::Span;
fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam) -> (ParamName, Region) {
let i = *index;
*index += 1;
- let def_id = hir_map.local_def_id_from_hir_id(param.hir_id);
+ let def_id = hir_map.local_def_id(param.hir_id);
let origin = LifetimeDefOrigin::from_param(param);
debug!("Region::early: index={} def_id={:?}", i, def_id);
(param.name.modern(), Region::EarlyBound(i, def_id, origin))
fn late(hir_map: &Map<'_>, param: &GenericParam) -> (ParamName, Region) {
let depth = ty::INNERMOST;
- let def_id = hir_map.local_def_id_from_hir_id(param.hir_id);
+ let def_id = hir_map.local_def_id(param.hir_id);
let origin = LifetimeDefOrigin::from_param(param);
debug!(
"Region::late: param={:?} depth={:?} def_id={:?} origin={:?}",
/// entire crate. You should not read the result of this query
/// directly, but rather use `named_region_map`, `is_late_bound_map`,
/// etc.
-fn resolve_lifetimes<'tcx>(tcx: TyCtxt<'tcx>, for_krate: CrateNum) -> &'tcx ResolveLifetimes {
+fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> &ResolveLifetimes {
assert_eq!(for_krate, LOCAL_CRATE);
let named_region_map = krate(tcx);
tcx.arena.alloc(rl)
}
-fn krate<'tcx>(tcx: TyCtxt<'tcx>) -> NamedRegionMap {
+fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
let krate = tcx.hir().krate();
let mut map = NamedRegionMap {
defs: Default::default(),
fn visit_nested_body(&mut self, body: hir::BodyId) {
// Each body has their own set of labels, save labels.
- let saved = replace(&mut self.labels_in_fn, vec![]);
+ let saved = take(&mut self.labels_in_fn);
let body = self.tcx.hir().body(body);
extract_labels(self, body);
self.with(
add_bounds(&mut set, ¶m.bounds);
- let param_def_id = tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ let param_def_id = tcx.hir().local_def_id(param.hir_id);
for predicate in &generics.where_clause.predicates {
// Look for `type: ...` where clauses.
let data = match *predicate {
.enumerate()
.find(|&(_, (_, lt_name, _))| lt_name == name)
.map_or(Set1::Many, |(i, (id, _, origin))| {
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
Set1::One(Region::EarlyBound(i as u32, def_id, origin))
})
}
lifetime_uses,
..
} = self;
- let labels_in_fn = replace(&mut self.labels_in_fn, vec![]);
- let xcrate_object_lifetime_defaults =
- replace(&mut self.xcrate_object_lifetime_defaults, DefIdMap::default());
+ let labels_in_fn = take(&mut self.labels_in_fn);
+ let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults);
let mut this = LifetimeContext {
tcx: *tcx,
map: map,
node: hir::ImplItemKind::Method(..),
..
}) => {
- let scope = self.tcx.hir().local_def_id_from_hir_id(fn_id);
+ let scope = self.tcx.hir().local_def_id(fn_id);
def = Region::Free(scope, def.id().unwrap());
}
_ => {}
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
- let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(
+ let impl_def_id = self.tcx.hir().local_def_id(
self.tcx.hir().get_parent_item(ii.hir_id));
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
self.check_missing_stability(ii.hir_id, ii.span, "item");
/// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors.
-fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }.as_deep_visitor());
}
// Deprecated attributes apply in-crate and cross-crate.
if let Some(id) = id {
if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) {
- let parent_def_id = self.hir().local_def_id_from_hir_id(
+ let parent_def_id = self.hir().local_def_id(
self.hir().get_parent_item(id));
let skip = self.lookup_deprecation_entry(parent_def_id)
.map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
// compiler-generated `extern crate` items have a dummy span.
if item.span.is_dummy() { return }
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let cnum = match self.tcx.extern_mod_stmt_cnum(def_id) {
Some(cnum) => cnum,
None => return,
// There's no good place to insert stability check for non-Copy unions,
// so semi-randomly perform it here in stability.rs
hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let adt_def = self.tcx.adt_def(def_id);
let ty = self.tcx.type_of(def_id);
/// Given the list of enabled features that were not language features (i.e., that
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
-pub fn check_unused_or_stable_features<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
if tcx.stability().staged_api[&LOCAL_CRATE] {
// don't lint about unused features. We should reenable this one day!
}
-fn unnecessary_stable_feature_lint<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn unnecessary_stable_feature_lint(
+ tcx: TyCtxt<'_>,
span: Span,
feature: Symbol,
since: Symbol,
}
}
+CloneTypeFoldableImpls! {
+ ErrorHandled,
+}
+
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
/// up with a Rust-level backtrace of where the error occured.
/// Thsese should always be constructed by calling `.into()` on
/// a `InterpError`. In `librustc_mir::interpret`, we have the `err!`
-/// macro for this
+/// macro for this.
#[derive(Debug, Clone)]
pub struct InterpErrorInfo<'tcx> {
pub kind: InterpError<'tcx, u64>,
}
}
- #[inline]
- pub fn is_null_ptr(self, cx: &impl HasDataLayout) -> bool {
- match self {
- Scalar::Raw { data, size } => {
- assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
- data == 0
- },
- Scalar::Ptr(_) => false,
- }
- }
-
#[inline]
pub fn from_bool(b: bool) -> Self {
Scalar::Raw { data: b as u128, size: 1 }
}
impl<'tcx> graph::WithPredecessors for Body<'tcx> {
- fn predecessors<'graph>(
- &'graph self,
+ fn predecessors(
+ &self,
node: Self::Node,
- ) -> <Self as GraphPredecessors<'graph>>::Iter {
+ ) -> <Self as GraphPredecessors<'_>>::Iter {
self.predecessors_for(node).clone().into_iter()
}
}
impl<'tcx> graph::WithSuccessors for Body<'tcx> {
- fn successors<'graph>(
- &'graph self,
+ fn successors(
+ &self,
node: Self::Node,
- ) -> <Self as GraphSuccessors<'graph>>::Iter {
+ ) -> <Self as GraphSuccessors<'_>>::Iter {
self.basic_blocks[node].terminator().successors().cloned()
}
}
tcx.symbol_name(Instance::mono(tcx, def_id))
}
MonoItem::GlobalAsm(hir_id) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
SymbolName {
name: InternedString::intern(&format!("global_asm_{:?}", def_id))
}
"const-evaluating `{}`",
tcx.def_path_str(key.value.instance.def.def_id())
}
- cache_on_disk_if(_, opt_result) {
- // Only store results without errors
- // FIXME: We never store these
- opt_result.map_or(true, |r| r.is_ok())
- }
}
/// Results of evaluating const items or constants embedded in
self.0.contains_key(key)
}
- pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
+ pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<PathBuf>> {
self.0.keys()
}
- pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
+ pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<PathBuf>> {
self.0.values()
}
self.0.get(key)
}
- pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, ExternEntry> {
+ pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
self.0.iter()
}
}
linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
parse_linker_plugin_lto, [TRACKED],
"generate build artifacts that are compatible with linker-based LTO."),
-
+ profile_generate: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+ parse_switch_with_opt_path, [TRACKED],
+ "compile the program with profiling instrumentation"),
+ profile_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+ "use the given `.profdata` file for profile-guided optimization"),
}
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
- pgo_gen: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
- parse_switch_with_opt_path, [TRACKED],
- "Generate PGO profile data, to a given file, or to the default location if it's empty."),
- pgo_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
- "Use PGO profile data from the given profile file."),
disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED],
"Disable the instrumentation pre-inliner, useful for profiling / PGO."),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
}
}
- if debugging_opts.pgo_gen.enabled() && debugging_opts.pgo_use.is_some() {
- early_error(
- error_format,
- "options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
- );
- }
-
let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
);
}
+ if cg.profile_generate.enabled() && cg.profile_use.is_some() {
+ early_error(
+ error_format,
+ "options `-C profile-generate` and `-C profile-use` are exclusive",
+ );
+ }
+
let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::TargetCPUs);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
- opts.debugging_opts.pgo_gen = SwitchWithOptPath::Enabled(None);
+ opts.cg.profile_generate = SwitchWithOptPath::Enabled(None);
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts = reference.clone();
- opts.debugging_opts.pgo_use = Some(PathBuf::from("abc"));
+ opts.cg.profile_use = Some(PathBuf::from("abc"));
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts = reference.clone();
*self.crate_disambiguator.get()
}
- pub fn struct_span_warn<'a, S: Into<MultiSpan>>(
- &'a self,
+ pub fn struct_span_warn<S: Into<MultiSpan>>(
+ &self,
sp: S,
msg: &str,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_warn(sp, msg)
}
- pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(
- &'a self,
+ pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
+ &self,
sp: S,
msg: &str,
code: DiagnosticId,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
- pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_warn(msg)
}
- pub fn struct_span_err<'a, S: Into<MultiSpan>>(
- &'a self,
+ pub fn struct_span_err<S: Into<MultiSpan>>(
+ &self,
sp: S,
msg: &str,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_err(sp, msg)
}
- pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(
- &'a self,
+ pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
+ &self,
sp: S,
msg: &str,
code: DiagnosticId,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_err_with_code(sp, msg, code)
}
// FIXME: This method should be removed (every error should have an associated error code).
- pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_err(msg)
}
- pub fn struct_err_with_code<'a>(
- &'a self,
+ pub fn struct_err_with_code(
+ &self,
msg: &str,
code: DiagnosticId,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_err_with_code(msg, code)
}
- pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(
- &'a self,
+ pub fn struct_span_fatal<S: Into<MultiSpan>>(
+ &self,
sp: S,
msg: &str,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_fatal(sp, msg)
}
- pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(
- &'a self,
+ pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
+ &self,
sp: S,
msg: &str,
code: DiagnosticId,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
}
- pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_fatal(msg)
}
pub fn next_node_id(&self) -> NodeId {
self.reserve_node_ids(1)
}
- pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler {
+ pub fn diagnostic(&self) -> &errors::Handler {
&self.parse_sess.span_diagnostic
}
);
}
- pub fn source_map<'a>(&'a self) -> &'a source_map::SourceMap {
+ pub fn source_map(&self) -> &source_map::SourceMap {
self.parse_sess.source_map()
}
pub fn verbose(&self) -> bool {
// Make sure that any given profiling data actually exists so LLVM can't
// decide to silently skip PGO.
- if let Some(ref path) = sess.opts.debugging_opts.pgo_use {
+ if let Some(ref path) = sess.opts.cg.profile_use {
if !path.exists() {
- sess.err(&format!("File `{}` passed to `-Zpgo-use` does not exist.",
+ sess.err(&format!("File `{}` passed to `-C profile-use` does not exist.",
path.display()));
}
}
// an error to combine the two for now. It always runs into an assertions
// if LLVM is built with assertions, but without assertions it sometimes
// does not crash and will probably generate a corrupted binary.
- if sess.opts.debugging_opts.pgo_gen.enabled() &&
+ if sess.opts.cg.profile_generate.enabled() &&
sess.target.target.options.is_like_msvc &&
sess.panic_strategy() == PanicStrategy::Unwind {
sess.err("Profile-guided optimization does not yet work in conjunction \
/// If there are types that satisfy both impls, invokes `on_overlap`
/// with a suitably-freshened `ImplHeader` with those types
/// substituted. Otherwise, invokes `no_overlap`.
-pub fn overlapping_impls<'tcx, F1, F2, R>(
- tcx: TyCtxt<'tcx>,
+pub fn overlapping_impls<F1, F2, R>(
+ tcx: TyCtxt<'_>,
impl1_def_id: DefId,
impl2_def_id: DefId,
intercrate_mode: IntercrateMode,
///
/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
/// 2. Some local type must appear in `Self`.
-pub fn orphan_check<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn orphan_check(
+ tcx: TyCtxt<'_>,
impl_def_id: DefId,
-) -> Result<(), OrphanCheckErr<'tcx>> {
+) -> Result<(), OrphanCheckErr<'_>> {
debug!("orphan_check({:?})", impl_def_id);
// We only except this routine to be invoked on implementations
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
/// returns the fuzzy category of a given type, or None
/// if the type can be equated to any type.
- fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
+ fn type_category(t: Ty<'_>) -> Option<u32> {
match t.sty {
ty::Bool => Some(0),
ty::Char => Some(1),
}
ty::Predicate::ConstEvaluatable(def_id, substs) => {
- match self.selcx.tcx().lift_to_global(&obligation.param_env) {
- None => {
+ if obligation.param_env.has_local_value() {
ProcessResult::Unchanged
- }
- Some(param_env) => {
- match self.selcx.tcx().lift_to_global(&substs) {
- Some(substs) => {
- let instance = ty::Instance::resolve(
- self.selcx.tcx().global_tcx(),
- param_env,
- def_id,
- substs,
- );
- if let Some(instance) = instance {
- let cid = GlobalId {
- instance,
- promoted: None,
- };
- match self.selcx.tcx().at(obligation.cause.span)
- .const_eval(param_env.and(cid)) {
- Ok(_) => ProcessResult::Changed(vec![]),
- Err(err) => ProcessResult::Error(
- CodeSelectionError(ConstEvalFailure(err)))
- }
- } else {
- ProcessResult::Error(CodeSelectionError(
- ConstEvalFailure(ErrorHandled::TooGeneric)
- ))
- }
- },
- None => {
- pending_obligation.stalled_on = substs.types().collect();
- ProcessResult::Unchanged
+ } else {
+ if !substs.has_local_value() {
+ let instance = ty::Instance::resolve(
+ self.selcx.tcx().global_tcx(),
+ obligation.param_env,
+ def_id,
+ substs,
+ );
+ if let Some(instance) = instance {
+ let cid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ match self.selcx.tcx().at(obligation.cause.span)
+ .const_eval(obligation.param_env.and(cid)) {
+ Ok(_) => ProcessResult::Changed(vec![]),
+ Err(err) => ProcessResult::Error(
+ CodeSelectionError(ConstEvalFailure(err)))
}
+ } else {
+ ProcessResult::Error(CodeSelectionError(
+ ConstEvalFailure(ErrorHandled::TooGeneric)
+ ))
}
+ } else {
+ pending_obligation.stalled_on = substs.types().collect();
+ ProcessResult::Unchanged
}
}
}
Overflow,
}
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for SelectionError<'tcx> {
+ (SelectionError::Unimplemented),
+ (SelectionError::OutputTypeParameterMismatch)(a, b, c),
+ (SelectionError::TraitNotObjectSafe)(a),
+ (SelectionError::ConstEvalFailure)(a),
+ (SelectionError::Overflow),
+ }
+}
+
pub struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>,
pub code: FulfillmentErrorCode<'tcx>
return Err(ErrorReported)
}
};
-
- match tcx.lift_to_global(&predicates) {
- Some(predicates) => Ok(predicates),
- None => {
- // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
- Err(ErrorReported)
- }
+ if predicates.has_local_value() {
+ // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
+ Err(ErrorReported)
+ } else {
+ Ok(predicates)
}
})
}
}
}
-pub(super) fn is_object_safe_provider<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> bool {
+pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
tcx.object_safety_violations(trait_def_id).is_empty()
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.selcx.tcx().global_tcx();
- if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
+ let param_env = self.param_env;
+ if !param_env.has_local_value() {
if substs.needs_infer() || substs.has_placeholders() {
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
}
}
} else {
- if let Some(substs) = self.tcx().lift_to_global(&substs) {
+ if !substs.has_local_value() {
let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
if let Some(instance) = instance {
let cid = GlobalId {
///
/// Based on the "projection mode", this lookup may in fact only examine the
/// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_ty_def<'cx, 'tcx>(
- selcx: &SelectionContext<'cx, 'tcx>,
+fn assoc_ty_def(
+ selcx: &SelectionContext<'_, '_>,
impl_def_id: DefId,
assoc_ty_def_id: DefId,
) -> specialization_graph::NodeItem<ty::AssocItem> {
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.infcx.tcx.global_tcx();
- if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
+ let param_env = self.param_env;
+ if !param_env.has_local_value() {
if substs.needs_infer() || substs.has_placeholders() {
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
}
}
} else {
- if let Some(substs) = self.tcx().lift_to_global(&substs) {
+ if !substs.has_local_value() {
let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
if let Some(instance) = instance {
let cid = GlobalId {
use crate::traits::query::Fallible;
use crate::infer::canonical::query_response;
-use crate::infer::canonical::QueryRegionConstraint;
+use crate::infer::canonical::QueryRegionConstraints;
use std::rc::Rc;
use syntax::source_map::DUMMY_SP;
use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
fn fully_perform(
self,
infcx: &InferCtxt<'_, 'tcx>,
- ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+ ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
if cfg!(debug_assertions) {
info!("fully_perform({:?})", self);
}
fn scrape_region_constraints<'tcx, R>(
infcx: &InferCtxt<'_, 'tcx>,
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
-) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
let mut fulfill_cx = TraitEngine::new(infcx.tcx);
let dummy_body_id = ObligationCause::dummy().body_id;
let region_constraint_data = infcx.take_and_reset_region_constraints();
- let outlives = query_response::make_query_outlives(
+ let region_constraints = query_response::make_query_region_constraints(
infcx.tcx,
region_obligations
.iter()
®ion_constraint_data,
);
- if outlives.is_empty() {
+ if region_constraints.is_empty() {
Ok((value, None))
} else {
- Ok((value, Some(Rc::new(outlives))))
+ Ok((value, Some(Rc::new(region_constraints))))
}
}
use crate::infer::canonical::{
Canonical, Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues,
- QueryRegionConstraint, QueryResponse,
+ QueryRegionConstraints, QueryResponse,
};
use crate::infer::{InferCtxt, InferOk};
use std::fmt;
fn fully_perform(
self,
infcx: &InferCtxt<'_, 'tcx>,
- ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)>;
+ ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
}
/// "Query type ops" are type ops that are implemented using a
fn fully_perform_into(
query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'_, 'tcx>,
- output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
+ output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> Fallible<Self::QueryResponse> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok(result);
fn fully_perform(
self,
infcx: &InferCtxt<'_, 'tcx>,
- ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
- let mut qrc = vec![];
- let r = Q::fully_perform_into(self, infcx, &mut qrc)?;
+ ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
+ let mut region_constraints = QueryRegionConstraints::default();
+ let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
// Promote the final query-region-constraints into a
// (optional) ref-counted vector:
- let opt_qrc = if qrc.is_empty() {
+ let opt_qrc = if region_constraints.is_empty() {
None
} else {
- Some(Rc::new(qrc))
+ Some(Rc::new(region_constraints))
};
Ok((r, opt_qrc))
}
}
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for SelectionCandidate<'tcx> {
+ (SelectionCandidate::BuiltinCandidate) { has_nested },
+ (SelectionCandidate::ParamCandidate)(poly_trait_ref),
+ (SelectionCandidate::ImplCandidate)(def_id),
+ (SelectionCandidate::AutoImplCandidate)(def_id),
+ (SelectionCandidate::ProjectionCandidate),
+ (SelectionCandidate::ClosureCandidate),
+ (SelectionCandidate::GeneratorCandidate),
+ (SelectionCandidate::FnPointerCandidate),
+ (SelectionCandidate::TraitAliasCandidate)(def_id),
+ (SelectionCandidate::ObjectCandidate),
+ (SelectionCandidate::BuiltinObjectCandidate),
+ (SelectionCandidate::BuiltinUnsizeCandidate),
+ }
+}
+
struct SelectionCandidateSet<'tcx> {
// a list of candidates that definitely apply to the current
// obligation (meaning: types unify).
ty::Predicate::ConstEvaluatable(def_id, substs) => {
let tcx = self.tcx();
- match tcx.lift_to_global(&(obligation.param_env, substs)) {
- Some((param_env, substs)) => {
- let instance =
- ty::Instance::resolve(tcx.global_tcx(), param_env, def_id, substs);
- if let Some(instance) = instance {
- let cid = GlobalId {
- instance,
- promoted: None,
- };
- match self.tcx().const_eval(param_env.and(cid)) {
- Ok(_) => Ok(EvaluatedToOk),
- Err(_) => Ok(EvaluatedToErr),
- }
- } else {
- Ok(EvaluatedToErr)
+ if !(obligation.param_env, substs).has_local_value() {
+ let param_env = obligation.param_env;
+ let instance =
+ ty::Instance::resolve(tcx, param_env, def_id, substs);
+ if let Some(instance) = instance {
+ let cid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ match self.tcx().const_eval(param_env.and(cid)) {
+ Ok(_) => Ok(EvaluatedToOk),
+ Err(_) => Ok(EvaluatedToErr),
}
+ } else {
+ Ok(EvaluatedToErr)
}
- None => {
- // Inference variables still left in param_env or substs.
- Ok(EvaluatedToAmbig)
- }
+ } else {
+ // Inference variables still left in param_env or substs.
+ Ok(EvaluatedToAmbig)
}
}
}
}
if self.can_use_global_caches(param_env) {
- if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
+ if !trait_ref.has_local_value() {
debug!(
"insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
trait_ref, result,
if let Err(Overflow) = candidate {
// Don't cache overflow globally; we only produce this
// in certain modes.
- } else if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
- if let Some(candidate) = tcx.lift_to_global(&candidate) {
+ } else if !trait_ref.has_local_value() {
+ if !candidate.has_local_value() {
debug!(
"insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
trait_ref, candidate,
/// Specialization is determined by the sets of types to which the impls apply;
/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
/// to.
-pub(super) fn specializes<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub(super) fn specializes(
+ tcx: TyCtxt<'_>,
(impl1_def_id, impl2_def_id): (DefId, DefId),
) -> bool {
debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
}
// Query provider for `specialization_graph_of`.
-pub(super) fn specialization_graph_provider<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub(super) fn specialization_graph_provider(
+ tcx: TyCtxt<'_>,
trait_id: DefId,
-) -> &'tcx specialization_graph::Graph {
+) -> &specialization_graph::Graph {
let mut sg = specialization_graph::Graph::new();
let mut trait_impls = tcx.all_impls(trait_id);
visited: FxHashSet<DefId>,
}
-pub fn supertrait_def_ids<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> SupertraitDefIds<'tcx> {
+pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
SupertraitDefIds {
tcx,
stack: vec![trait_def_id],
fn variant(&self) -> &Self::Variant;
}
+#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
type Variant = ty::TyKind<'tcx>;
fn variant(&self) -> &Self::Variant {
Ok(decoder.map_encoded_cnum_to_current(cnum))
}
+#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
#[inline]
pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
where
-// ignore-tidy-filelength
-
//! Type context book-keeping.
use crate::arena::Arena;
use std::iter;
use std::sync::mpsc;
use std::sync::Arc;
-use std::marker::PhantomData;
use rustc_target::spec::abi;
use rustc_macros::HashStable;
use syntax::ast;
pub struct AllArenas {
pub interner: SyncDroplessArena,
- pub local_interner: SyncDroplessArena,
}
impl AllArenas {
pub fn new() -> Self {
AllArenas {
interner: SyncDroplessArena::default(),
- local_interner: SyncDroplessArena::default(),
}
}
}
}
/// Intern a type
+ #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
#[inline(never)]
- fn intern_ty(
- local: &CtxtInterners<'tcx>,
- global: &CtxtInterners<'tcx>,
- st: TyKind<'tcx>,
+ fn intern_ty(&self,
+ st: TyKind<'tcx>
) -> Ty<'tcx> {
- let flags = super::flags::FlagComputation::for_sty(&st);
-
- // HACK(eddyb) Depend on flags being accurate to
- // determine that all contents are in the global tcx.
- // See comments on Lift for why we can't use that.
- if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
- local.type_.borrow_mut().intern(st, |st| {
- let ty_struct = TyS {
- sty: st,
- flags: flags.flags,
- outer_exclusive_binder: flags.outer_exclusive_binder,
- };
+ self.type_.borrow_mut().intern(st, |st| {
+ let flags = super::flags::FlagComputation::for_sty(&st);
- // Make sure we don't end up with inference
- // types/regions in the global interner
- if ptr_eq(local, global) {
- bug!("Attempted to intern `{:?}` which contains \
- inference types/regions in the global type context",
- &ty_struct);
- }
-
- // This is safe because all the types the ty_struct can point to
- // already is in the local arena or the global arena
- let ty_struct: TyS<'tcx> = unsafe {
- mem::transmute(ty_struct)
- };
-
- Interned(local.arena.alloc(ty_struct))
- }).0
- } else {
- global.type_.borrow_mut().intern(st, |st| {
- let ty_struct = TyS {
- sty: st,
- flags: flags.flags,
- outer_exclusive_binder: flags.outer_exclusive_binder,
- };
+ let ty_struct = TyS {
+ sty: st,
+ flags: flags.flags,
+ outer_exclusive_binder: flags.outer_exclusive_binder,
+ };
- // This is safe because all the types the ty_struct can point to
- // already is in the global arena
- let ty_struct: TyS<'tcx> = unsafe {
- mem::transmute(ty_struct)
- };
- Interned(global.arena.alloc(ty_struct))
- }).0
- }
+ Interned(self.arena.alloc(ty_struct))
+ }).0
}
}
impl<'tcx> CommonTypes<'tcx> {
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
- let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
+ let mk = |sty| interners.intern_ty(sty);
CommonTypes {
unit: mk(Tuple(List::empty())),
#[derive(Copy, Clone)]
pub struct TyCtxt<'tcx> {
gcx: &'tcx GlobalCtxt<'tcx>,
- interners: &'tcx CtxtInterners<'tcx>,
- dummy: PhantomData<&'tcx ()>,
}
impl<'tcx> Deref for TyCtxt<'tcx> {
pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>,
- global_interners: CtxtInterners<'tcx>,
- local_interners: CtxtInterners<'tcx>,
+ interners: CtxtInterners<'tcx>,
cstore: &'tcx CrateStoreDyn,
pub fn global_tcx(self) -> TyCtxt<'tcx> {
TyCtxt {
gcx: self.gcx,
- interners: &self.gcx.global_interners,
- dummy: PhantomData,
}
}
value.lift_to_tcx(self.global_tcx())
}
- /// Returns `true` if self is the same as self.global_tcx().
- fn is_global(self) -> bool {
- ptr_eq(self.interners, &self.global_interners)
- }
-
/// Creates a type context and call the closure with a `TyCtxt` reference
/// to the context. The closure enforces that the type context and any interned
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
s.fatal(&err);
});
let interners = CtxtInterners::new(&arenas.interner);
- let local_interners = CtxtInterners::new(&arenas.local_interner);
let common = Common {
empty_predicates: ty::GenericPredicates {
parent: None,
sess: s,
cstore,
arena: WorkerLocal::new(|_| Arena::default()),
- global_interners: interners,
- local_interners: local_interners,
+ interners,
dep_graph,
common,
types: common_types,
maybe_unused_trait_imports:
resolutions.maybe_unused_trait_imports
.into_iter()
- .map(|id| hir.local_def_id(id))
+ .map(|id| hir.local_def_id_from_node_id(id))
.collect(),
maybe_unused_extern_crates:
resolutions.maybe_unused_extern_crates
.into_iter()
- .map(|(id, sp)| (hir.local_def_id(id), sp))
+ .map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp))
.collect(),
glob_map: resolutions.glob_map.into_iter().map(|(id, names)| {
- (hir.local_def_id(id), names)
+ (hir.local_def_id_from_node_id(id), names)
}).collect(),
extern_prelude: resolutions.extern_prelude,
hir_map: hir,
{
let tcx = TyCtxt {
gcx: self,
- interners: &self.local_interners,
- dummy: PhantomData,
};
ty::tls::with_related_context(tcx.global_tcx(), |icx| {
let new_icx = ty::tls::ImplicitCtxt {
type Lifted = $lifted;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
+ Some(unsafe { mem::transmute(*self) })
} else {
None
}
return Some(List::empty());
}
if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
+ Some(unsafe { mem::transmute(*self) })
} else {
None
}
use std::fmt;
use std::mem;
- use std::marker::PhantomData;
use syntax_pos;
use crate::ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
let tcx = TyCtxt {
gcx,
- interners: &gcx.global_interners,
- dummy: PhantomData,
};
let icx = ImplicitCtxt {
tcx,
let gcx = &*(gcx as *const GlobalCtxt<'_>);
let tcx = TyCtxt {
gcx,
- interners: &gcx.global_interners,
- dummy: PhantomData,
};
let icx = ImplicitCtxt {
query: None,
})
}
- /// Allows access to the current ImplicitCtxt whose tcx field has the same global
- /// interner and local interner as the tcx argument passed in. This means the closure
- /// is given an ImplicitCtxt with the same 'tcx and 'tcx lifetimes as the TyCtxt passed in.
- /// This will panic if you pass it a TyCtxt which has a different global interner or
- /// a different local interner from the current ImplicitCtxt's tcx field.
- #[inline]
- pub fn with_fully_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
- where
- F: for<'b> FnOnce(&ImplicitCtxt<'b, 'tcx>) -> R,
- {
- with_context(|context| {
- unsafe {
- assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
- assert!(ptr_eq(context.tcx.interners, tcx.interners));
- let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
- f(context)
- }
- })
- }
-
/// Allows access to the TyCtxt in the current ImplicitCtxt.
/// Panics if there is no ImplicitCtxt available
#[inline]
}
}
+#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> {
fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
&self.0.sty
macro_rules! intern_method {
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
$alloc_method:expr,
- $alloc_to_key:expr,
- $keep_in_local_tcx:expr) -> $ty:ty) => {
+ $alloc_to_key:expr) -> $ty:ty) => {
impl<$lt_tcx> TyCtxt<$lt_tcx> {
pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
let key = ($alloc_to_key)(&v);
- // HACK(eddyb) Depend on flags being accurate to
- // determine that all contents are in the global tcx.
- // See comments on Lift for why we can't use that.
- if ($keep_in_local_tcx)(&v) {
- self.interners.$name.borrow_mut().intern_ref(key, || {
- // Make sure we don't end up with inference
- // types/regions in the global tcx.
- if self.is_global() {
- bug!("Attempted to intern `{:?}` which contains \
- inference types/regions in the global type context",
- v);
- }
+ self.interners.$name.borrow_mut().intern_ref(key, || {
+ Interned($alloc_method(&self.interners.arena, v))
- Interned($alloc_method(&self.interners.arena, v))
- }).0
- } else {
- self.global_interners.$name.borrow_mut().intern_ref(key, || {
- Interned($alloc_method(&self.global_interners.arena, v))
- }).0
- }
+ }).0
}
}
}
}
macro_rules! direct_interners {
- ($lt_tcx:tt, $($name:ident: $method:ident($keep_in_local_tcx:expr) -> $ty:ty),+) => {
+ ($lt_tcx:tt, $($name:ident: $method:ident($ty:ty)),+) => {
$(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
$lt_tcx,
$name: $method($ty,
|a: &$lt_tcx SyncDroplessArena, v| -> &$lt_tcx $ty { a.alloc(v) },
- |x| x,
- $keep_in_local_tcx) -> $ty);)+
+ |x| x) -> $ty);)+
}
}
}
direct_interners!('tcx,
- region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
- goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
- const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
+ region: mk_region(RegionKind),
+ goal: mk_goal(GoalKind<'tcx>),
+ const_: mk_const(Const<'tcx>)
);
macro_rules! slice_interners {
$(intern_method!( 'tcx, $field: $method(
&[$ty],
|a, v| List::from_arena(a, v),
- Deref::deref,
- |xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty>);)+
+ Deref::deref) -> List<$ty>);)+
);
}
canonical_var_infos: _intern_canonical_var_infos(
&[CanonicalVarInfo],
|a, v| List::from_arena(a, v),
- Deref::deref,
- |_xs: &[CanonicalVarInfo]| -> bool { false }
+ Deref::deref
) -> List<CanonicalVarInfo>
}
self.mk_fn_ptr(converted_sig)
}
+ #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
#[inline]
pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
- CtxtInterners::intern_ty(&self.interners, &self.global_interners, st)
+ self.interners.intern_ty(st)
}
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
- self.tcx.erase_regions_ty(ty_lifted)
- } else {
+ if ty.has_local_value() {
ty.super_fold_with(self)
+ } else {
+ self.tcx.erase_regions_ty(ty)
}
}
}
}
+ #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
pub fn for_sty(st: &ty::TyKind<'_>) -> FlagComputation {
let mut result = FlagComputation::new();
result.add_sty(st);
} // otherwise, this binder captures nothing
}
+ #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
fn add_sty(&mut self, st: &ty::TyKind<'_>) {
match st {
&ty::Bool |
fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
+ fn has_local_value(&self) -> bool {
+ self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
+ }
fn needs_infer(&self) -> bool {
self.has_type_flags(
TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER
}
}
+// FIXME: Optimize for checking for infer flags
struct HasTypeFlagsVisitor {
flags: ty::TypeFlags,
}
/// crate.
#[inline]
pub fn full(tcx: TyCtxt<'tcx>) -> DefIdForest {
- let crate_id = tcx.hir().local_def_id_from_hir_id(CRATE_HIR_ID);
+ let crate_id = tcx.hir().local_def_id(CRATE_HIR_ID);
DefIdForest::from_id(crate_id)
}
// ignore-tidy-filelength
-#![allow(usage_of_ty_tykind)]
-
pub use self::Variance::*;
pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*;
}
}
+#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
pub struct TyS<'tcx> {
pub sty: TyKind<'tcx>,
pub flags: TypeFlags,
impl<'tcx> TyS<'tcx> {
pub fn is_primitive_ty(&self) -> bool {
match self.sty {
- TyKind::Bool |
- TyKind::Char |
- TyKind::Int(_) |
- TyKind::Uint(_) |
- TyKind::Float(_) |
- TyKind::Infer(InferTy::IntVar(_)) |
- TyKind::Infer(InferTy::FloatVar(_)) |
- TyKind::Infer(InferTy::FreshIntTy(_)) |
- TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
- TyKind::Ref(_, x, _) => x.is_primitive_ty(),
+ Bool |
+ Char |
+ Int(_) |
+ Uint(_) |
+ Float(_) |
+ Infer(InferTy::IntVar(_)) |
+ Infer(InferTy::FloatVar(_)) |
+ Infer(InferTy::FreshIntTy(_)) |
+ Infer(InferTy::FreshFloatTy(_)) => true,
+ Ref(_, x, _) => x.is_primitive_ty(),
_ => false,
}
}
pub fn is_suggestable(&self) -> bool {
match self.sty {
- TyKind::Opaque(..) |
- TyKind::FnDef(..) |
- TyKind::FnPtr(..) |
- TyKind::Dynamic(..) |
- TyKind::Closure(..) |
- TyKind::Infer(..) |
- TyKind::Projection(..) => false,
+ Opaque(..) |
+ FnDef(..) |
+ FnPtr(..) |
+ Dynamic(..) |
+ Closure(..) |
+ Infer(..) |
+ Projection(..) => false,
_ => true,
}
}
parent_vis: &hir::Visibility,
trait_item_ref: &hir::TraitItemRef)
-> AssocItem {
- let def_id = self.hir().local_def_id_from_hir_id(trait_item_ref.id.hir_id);
+ let def_id = self.hir().local_def_id(trait_item_ref.id.hir_id);
let (kind, has_self) = match trait_item_ref.kind {
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
hir::AssocItemKind::Method { has_self } => {
parent_def_id: DefId,
impl_item_ref: &hir::ImplItemRef)
-> AssocItem {
- let def_id = self.hir().local_def_id_from_hir_id(impl_item_ref.id.hir_id);
+ let def_id = self.hir().local_def_id(impl_item_ref.id.hir_id);
let (kind, has_self) = match impl_item_ref.kind {
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
hir::AssocItemKind::Method { has_self } => {
fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> AssocItem {
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
let parent_id = tcx.hir().get_parent_item(id);
- let parent_def_id = tcx.hir().local_def_id_from_hir_id(parent_id);
+ let parent_def_id = tcx.hir().local_def_id(parent_id);
let parent_item = tcx.hir().expect_item(parent_id);
match parent_item.node {
hir::ItemKind::Impl(.., ref impl_item_refs) => {
tcx.arena.alloc_from_iter(
trait_item_refs.iter()
.map(|trait_item_ref| trait_item_ref.id)
- .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
+ .map(|id| tcx.hir().local_def_id(id.hir_id))
)
}
hir::ItemKind::Impl(.., ref impl_item_refs) => {
tcx.arena.alloc_from_iter(
impl_item_refs.iter()
.map(|impl_item_ref| impl_item_ref.id)
- .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
+ .map(|id| tcx.hir().local_def_id(id.hir_id))
)
}
hir::ItemKind::TraitAlias(..) => &[],
let mut query_result_index = EncodedQueryResultIndex::new();
time(tcx.sess, "encode query results", || {
- use crate::ty::query::queries::*;
let enc = &mut encoder;
let qri = &mut query_result_index;
- encode_query_results::<type_of<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<generics_of<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<predicates_of<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<used_trait_imports<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<typeck_tables_of<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<codegen_fulfill_obligation<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<optimized_mir<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<unsafety_check_result<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<borrowck<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<mir_borrowck<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<mir_const_qualif<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<const_is_rvalue_promotable_to_static<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<symbol_name<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<check_match<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<codegen_fn_attrs<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<specialization_graph_of<'_>, _>(tcx, enc, qri)?;
- encode_query_results::<const_eval<'_>, _>(tcx, enc, qri)?;
- // FIXME: Include const_eval_raw?
+ macro_rules! encode_queries {
+ ($($query:ident,)*) => {
+ $(
+ encode_query_results::<ty::query::queries::$query<'_>, _>(
+ tcx,
+ enc,
+ qri
+ )?;
+ )*
+ }
+ }
+
+ rustc_cached_queries!(encode_queries!);
Ok(())
})?;
}
/// Loads a diagnostic emitted during the previous compilation session.
- pub fn load_diagnostics<'tcx>(
+ pub fn load_diagnostics(
&self,
- tcx: TyCtxt<'tcx>,
+ tcx: TyCtxt<'_>,
dep_node_index: SerializedDepNodeIndex,
) -> Vec<Diagnostic> {
let diagnostics: Option<EncodedDiagnostics> = self.load_indexed(
/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
- pub fn try_load_query_result<'tcx, T>(
+ pub fn try_load_query_result<T>(
&self,
- tcx: TyCtxt<'tcx>,
+ tcx: TyCtxt<'_>,
dep_node_index: SerializedDepNodeIndex,
) -> Option<T>
where
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
/// add it to the "We don't have enough information to reconstruct..." group in
/// the match below.
-pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
+pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
use crate::dep_graph::RecoverKey;
// We must avoid ever having to call force_from_dep_node() for a
if let ConstValue::Unevaluated(def_id, substs) = x.val {
// FIXME(eddyb) get the right param_env.
let param_env = ty::ParamEnv::empty();
- if let Some(substs) = tcx.lift_to_global(&substs) {
+ if !substs.has_local_value() {
let instance = ty::Instance::resolve(
tcx.global_tcx(),
param_env,
use std::fmt;
use std::rc::Rc;
+use std::sync::Arc;
impl fmt::Debug for ty::GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
tcx.lift(&self.0).and_then(|a| {
tcx.lift(&self.1).and_then(|b| tcx.lift(&self.2).map(|c| (a, b, c)))
})
- }
+ }
}
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
}
}
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Rc<T> {
+ type Lifted = Rc<T::Lifted>;
+ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&**self).map(Rc::new)
+ }
+}
+
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Arc<T> {
+ type Lifted = Arc<T::Lifted>;
+ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&**self).map(Arc::new)
+ }
+}
+
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
type Lifted = Vec<T::Lifted>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
} where T: TypeFoldable<'tcx>
}
+EnumTypeFoldableImpl! {
+ impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
+ (Ok)(a),
+ (Err)(a),
+ } where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
+}
+
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Rc::new((**self).fold_with(folder))
}
}
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
+ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+ Arc::new((**self).fold_with(folder))
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ (**self).visit_with(visitor)
+ }
+}
+
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let content: T = (**self).fold_with(folder);
//! This module contains `TyKind` and its major components.
+#![cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))]
+
use crate::hir;
use crate::hir::def_id::DefId;
use crate::infer::canonical::Canonical;
}
for &hir_id in tcx.hir().trait_impls(trait_id) {
- add_impl(tcx.hir().local_def_id_from_hir_id(hir_id));
+ add_impl(tcx.hir().local_def_id(hir_id));
}
}
}
}
- print_time_passes_entry_internal(what, dur);
+ print_time_passes_entry(true, what, dur);
TIME_DEPTH.with(|slot| slot.set(old));
return
}
- let old = TIME_DEPTH.with(|slot| {
- let r = slot.get();
- slot.set(r + 1);
- r
- });
-
- print_time_passes_entry_internal(what, dur);
-
- TIME_DEPTH.with(|slot| slot.set(old));
-}
-
-fn print_time_passes_entry_internal(what: &str, dur: Duration) {
let indentation = TIME_DEPTH.with(|slot| slot.get());
let mem_string = match get_resident() {
#![feature(rustc_private)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
pub mod expand;
cmt: &mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>,
borrow_span: Span) {
- pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
+ pub fn borrow_of_local_data(cmt: &mc::cmt_<'_>) -> bool {
match cmt.cat {
// Borrows of static items is allowed
Categorization::StaticItem => false,
pub type LoanDataFlow<'tcx> = DataFlowContext<'tcx, LoanDataFlowOperator>;
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_crate(tcx: TyCtxt<'_>) {
tcx.par_body_owners(|body_owner_def_id| {
tcx.ensure().borrowck(body_owner_def_id);
});
pub move_data: move_data::FlowedMoveData<'tcx>,
}
-fn borrowck<'tcx>(tcx: TyCtxt<'tcx>, owner_def_id: DefId) -> &'tcx BorrowCheckResult {
+fn borrowck(tcx: TyCtxt<'_>, owner_def_id: DefId) -> &BorrowCheckResult {
assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
cfg: &cfg::CFG,
) -> (BorrowckCtxt<'a, 'tcx>, AnalysisData<'tcx>) {
let owner_id = tcx.hir().body_owner(body_id);
- let owner_def_id = tcx.hir().local_def_id_from_hir_id(owner_id);
+ let owner_def_id = tcx.hir().local_def_id(owner_id);
let tables = tcx.typeck_tables_of(owner_def_id);
let region_scope_tree = tcx.region_scope_tree(owner_def_id);
let body = tcx.hir().body(body_id);
use rustc::cfg;
use rustc::cfg::CFGIndex;
use rustc::ty::TyCtxt;
-use std::io;
use std::mem;
use std::usize;
use syntax::print::pprust::PrintState;
changed: bool,
}
-fn get_cfg_indices<'a>(id: hir::ItemLocalId,
- index: &'a FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>)
- -> &'a [CFGIndex] {
+fn get_cfg_indices(id: hir::ItemLocalId,
+ index: &FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>)
+ -> &[CFGIndex] {
index.get(&id).map_or(&[], |v| &v[..])
}
}
impl<'tcx, O: DataFlowOperator> pprust::PpAnn for DataFlowContext<'tcx, O> {
- fn nested(&self, state: &mut pprust::State<'_>, nested: pprust::Nested) -> io::Result<()> {
+ fn nested(&self, state: &mut pprust::State<'_>, nested: pprust::Nested) {
pprust::PpAnn::nested(self.tcx.hir(), state, nested)
}
fn pre(&self,
ps: &mut pprust::State<'_>,
- node: pprust::AnnNode<'_>) -> io::Result<()> {
+ node: pprust::AnnNode<'_>) {
let id = match node {
- pprust::AnnNode::Name(_) => return Ok(()),
+ pprust::AnnNode::Name(_) => return,
pprust::AnnNode::Expr(expr) => expr.hir_id.local_id,
pprust::AnnNode::Block(blk) => blk.hir_id.local_id,
pprust::AnnNode::Item(_) |
- pprust::AnnNode::SubItem(_) => return Ok(()),
+ pprust::AnnNode::SubItem(_) => return,
pprust::AnnNode::Pat(pat) => pat.hir_id.local_id
};
if !self.has_bitset_for_local_id(id) {
- return Ok(());
+ return;
}
assert!(self.bits_per_id > 0);
ps.synth_comment(
format!("id {}: {}{}{}{}", id.as_usize(), entry_str,
- gens_str, action_kills_str, scope_kills_str))?;
- ps.s.space()?;
+ gens_str, action_kills_str, scope_kills_str));
+ ps.s.space();
}
- Ok(())
}
}
debug!("Dataflow result for {}:", self.analysis_name);
debug!("{}", pprust::to_string(self, |s| {
- s.cbox(pprust::indent_unit)?;
- s.ibox(0)?;
+ s.cbox(pprust::indent_unit);
+ s.ibox(0);
s.print_expr(&body.value)
}));
}
#![allow(non_camel_case_types)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(in_band_lifetimes)]
return
}
- // probestack doesn't play nice either with pgo-gen.
- if cx.sess().opts.debugging_opts.pgo_gen.enabled() {
+ // probestack doesn't play nice either with `-C profile-generate`.
+ if cx.sess().opts.cg.profile_generate.enabled() {
return;
}
}
fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
- let removals = mem::replace(&mut self.removals, Vec::new());
- let mut additions = mem::replace(&mut self.additions, Vec::new());
+ let removals = mem::take(&mut self.removals);
+ let mut additions = mem::take(&mut self.additions);
let mut strings = Vec::new();
let mut members = Vec::new();
}
}
-unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<LlvmCodegenBackend>,
- msg: &'b str,
- cookie: c_uint) {
+unsafe extern "C" fn report_inline_asm(cgcx: &CodegenContext<LlvmCodegenBackend>,
+ msg: &str,
+ cookie: c_uint) {
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
}
submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost);
- fn module_codegen<'tcx>(
- tcx: TyCtxt<'tcx>,
+ fn module_codegen(
+ tcx: TyCtxt<'_>,
cgu_name: InternedString,
) -> ModuleCodegen<ModuleLlvm> {
let cgu = tcx.codegen_unit(cgu_name);
}
}
- fn build_sibling_block<'b>(&self, name: &'b str) -> Self {
+ fn build_sibling_block(&self, name: &str) -> Self {
Builder::new_block(self.cx, self.llfn(), name)
}
pub fn const_get_real(&self, v: &'ll Value) -> Option<(f64, bool)> {
unsafe {
if self.is_const_real(v) {
+ #[allow(deprecated)]
let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
let loses_info = if loses_info == 1 { true } else { false };
return;
}
// Effectively no-ops
- "uninit" | "forget" => {
+ "forget" => {
return;
}
"needs_drop" => {
#![feature(link_args)]
#![feature(static_nobundle)]
#![feature(trusted_len)]
+#![feature(mem_take)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
use back::write::{create_target_machine, create_informational_target_machine};
) {
unsafe { allocator::codegen(tcx, mods, kind) }
}
- fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: InternedString) {
+ fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: InternedString) {
base::compile_codegen_unit(tcx, cgu_name);
}
fn target_machine_factory(
}
pub fn take_args(&mut self) -> Vec<OsString> {
- mem::replace(&mut self.args, Vec::new())
+ mem::take(&mut self.args)
}
/// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
linker_error.emit();
if sess.target.target.options.is_like_msvc && linker_not_found {
- sess.note_without_error("the msvc targets depend on the msvc linker \
- but `link.exe` was not found");
- sess.note_without_error("please ensure that VS 2013, VS 2015 or VS 2017 \
- was installed with the Visual C++ option");
+ sess.note_without_error(
+ "the msvc targets depend on the msvc linker \
+ but `link.exe` was not found",
+ );
+ sess.note_without_error(
+ "please ensure that VS 2013, VS 2015, VS 2017 or VS 2019 \
+ was installed with the Visual C++ option",
+ );
}
sess.abort_if_errors();
}
cmd.build_static_executable();
}
- if sess.opts.debugging_opts.pgo_gen.enabled() {
+ if sess.opts.cg.profile_generate.enabled() {
cmd.pgo_gen();
}
}
}
-fn reachable_non_generics_provider<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn reachable_non_generics_provider(
+ tcx: TyCtxt<'_>,
cnum: CrateNum,
-) -> &'tcx DefIdMap<SymbolExportLevel> {
+) -> &DefIdMap<SymbolExportLevel> {
assert_eq!(cnum, LOCAL_CRATE);
if !tcx.sess.opts.output_types.should_codegen() {
// let it through if it's included statically.
match tcx.hir().get(hir_id) {
Node::ForeignItem(..) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
if tcx.is_statically_included_foreign_item(def_id) {
Some(def_id)
} else {
node: hir::ImplItemKind::Method(..),
..
}) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
let generics = tcx.generics_of(def_id);
if !generics.requires_monomorphization(tcx) &&
// Functions marked with #[inline] are only ever codegened
tcx.arena.alloc(reachable_non_generics)
}
-fn is_reachable_non_generic_provider_local<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_reachable_non_generic_provider_local(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let export_threshold = threshold(tcx);
if let Some(&level) = tcx.reachable_non_generics(def_id.krate).get(&def_id) {
}
}
-fn is_reachable_non_generic_provider_extern<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
}
-fn exported_symbols_provider_local<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn exported_symbols_provider_local(
+ tcx: TyCtxt<'_>,
cnum: CrateNum,
-) -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>> {
+) -> Arc<Vec<(ExportedSymbol<'_>, SymbolExportLevel)>> {
assert_eq!(cnum, LOCAL_CRATE);
if !tcx.sess.opts.output_types.should_codegen() {
}
}
- if tcx.sess.opts.debugging_opts.pgo_gen.enabled() {
+ if tcx.sess.opts.cg.profile_generate.enabled() {
// 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.
Arc::new(symbols)
}
-fn upstream_monomorphizations_provider<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn upstream_monomorphizations_provider(
+ tcx: TyCtxt<'_>,
cnum: CrateNum,
-) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+) -> &DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
debug_assert!(cnum == LOCAL_CRATE);
let cnums = tcx.all_crate_nums(LOCAL_CRATE);
tcx.arena.alloc(instances)
}
-fn upstream_monomorphizations_for_provider<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn upstream_monomorphizations_for_provider(
+ tcx: TyCtxt<'_>,
def_id: DefId,
-) -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> {
debug_assert!(!def_id.is_local());
tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
}
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.pgo_gen = sess.opts.cg.profile_generate.clone();
+ modules_config.pgo_use = sess.opts.cg.profile_use.clone();
modules_config.opt_level = Some(sess.opts.optimize);
modules_config.opt_size = Some(sess.opts.optimize);
assert!(!started_lto);
started_lto = true;
- let needs_fat_lto =
- mem::replace(&mut needs_fat_lto, Vec::new());
- let needs_thin_lto =
- mem::replace(&mut needs_thin_lto, Vec::new());
- let import_only_modules =
- mem::replace(&mut lto_import_only_modules, Vec::new());
+ let needs_fat_lto = mem::take(&mut needs_fat_lto);
+ let needs_thin_lto = mem::take(&mut needs_thin_lto);
+ let import_only_modules = mem::take(&mut lto_import_only_modules);
for (work, cost) in generate_lto_work(&cgcx, needs_fat_lto,
needs_thin_lto, import_only_modules) {
let total_llvm_time = Instant::now().duration_since(llvm_start_time);
// This is the top-level timing for all of LLVM, set the time-depth
// to zero.
- set_time_depth(0);
+ set_time_depth(1);
print_time_passes_entry(cgcx.time_passes,
"LLVM passes",
total_llvm_time);
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
use rustc::ty::query::Providers;
use rustc::middle::cstore::{self, LinkagePreference};
-use rustc::util::common::{time, print_time_passes_entry};
+use rustc::util::common::{time, print_time_passes_entry, set_time_depth, time_depth};
use rustc::session::config::{self, EntryFnType, Lto};
use rustc::session::Session;
use rustc::util::nodemap::FxHashMap;
// Since the main thread is sometimes blocked during codegen, we keep track
// -Ztime-passes output manually.
+ let time_depth = time_depth();
+ set_time_depth(time_depth + 1);
print_time_passes_entry(tcx.sess.time_passes(),
"codegen to LLVM IR",
total_codegen_time);
+ set_time_depth(time_depth);
::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
}
}
-fn assert_and_save_dep_graph<'tcx>(tcx: TyCtxt<'tcx>) {
+fn assert_and_save_dep_graph(tcx: TyCtxt<'_>) {
time(tcx.sess,
"assert dep graph",
|| ::rustc_incremental::assert_dep_graph(tcx));
}
impl<D> FunctionDebugContext<D> {
- pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<D> {
+ pub fn get_ref(&self, span: Span) -> &FunctionDebugContextData<D> {
match *self {
FunctionDebugContext::RegularContext(ref data) => data,
FunctionDebugContext::DebugInfoDisabled => {
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(trusted_len)]
+#![feature(mem_take)]
#![allow(unused_attributes)]
#![allow(dead_code)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![recursion_limit="256"]
}
}
-pub fn cleanup_kinds<'tcx>(mir: &mir::Body<'tcx>) -> IndexVec<mir::BasicBlock, CleanupKind> {
+pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKind> {
fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
mir: &mir::Body<'tcx>) {
for (bb, data) in mir.basic_blocks().iter_enumerated() {
mods: &mut Self::Module,
kind: AllocatorKind,
);
- fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: InternedString);
+ fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: InternedString);
// If find_features is true this won't access `sess.crate_types` by assuming
// that `is_pie_binary` is false. When we discover LLVM target features
// `sess.crate_types` is uninitialized so we cannot access it.
{
fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self;
fn with_cx(cx: &'a Self::CodegenCx) -> Self;
- fn build_sibling_block<'b>(&self, name: &'b str) -> Self;
+ fn build_sibling_block(&self, name: &str) -> Self;
fn cx(&self) -> &Self::CodegenCx;
fn llbb(&self) -> Self::BasicBlock;
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use]
const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
const DEF_PATH: Symbol = sym::rustc_def_path;
-pub fn report_symbol_names<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn report_symbol_names(tcx: TyCtxt<'_>) {
// if the `rustc_attrs` feature is not enabled, then the
// attributes we are interested in cannot be present anyway, so
// skip the walk.
fn process_attrs(&mut self,
hir_id: hir::HirId) {
let tcx = self.tcx;
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
for attr in tcx.get_attrs(def_id).iter() {
if attr.check_name(SYMBOL_NAME) {
// for now, can only use on monomorphic names
--- /dev/null
+#[cfg(test)]
+mod test;
+
+/// Uses a sorted slice `data: &[E]` as a kind of "multi-map". The
+/// `key_fn` extracts a key of type `K` from the data, and this
+/// function finds the range of elements that match the key. `data`
+/// must have been sorted as if by a call to `sort_by_key` for this to
+/// work.
+pub fn binary_search_slice<E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E]
+where
+ K: Ord,
+{
+ let mid = match data.binary_search_by_key(key, &key_fn) {
+ Ok(mid) => mid,
+ Err(_) => return &[],
+ };
+
+ // We get back *some* element with the given key -- so
+ // search backwards to find the *first* one.
+ //
+ // (It'd be more efficient to use a "galloping" search
+ // here, but it's not really worth it for small-ish
+ // amounts of data.)
+ let mut start = mid;
+ while start > 0 {
+ if key_fn(&data[start - 1]) == *key {
+ start -= 1;
+ } else {
+ break;
+ }
+ }
+
+ // Now search forward to find the *last* one.
+ //
+ // (It'd be more efficient to use a "galloping" search
+ // here, but it's not really worth it for small-ish
+ // amounts of data.)
+ let mut end = mid + 1;
+ let max = data.len();
+ while end < max {
+ if key_fn(&data[end]) == *key {
+ end += 1;
+ } else {
+ break;
+ }
+ }
+
+ &data[start..end]
+}
--- /dev/null
+use super::*;
+
+type Element = (usize, &'static str);
+
+fn test_map() -> Vec<Element> {
+ let mut data = vec![(3, "three-a"), (0, "zero"), (3, "three-b"), (22, "twenty-two")];
+ data.sort_by_key(get_key);
+ data
+}
+
+fn get_key(data: &Element) -> usize {
+ data.0
+}
+
+#[test]
+fn binary_search_slice_test() {
+ let map = test_map();
+ assert_eq!(binary_search_slice(&map, get_key, &0), &[(0, "zero")]);
+ assert_eq!(binary_search_slice(&map, get_key, &1), &[]);
+ assert_eq!(binary_search_slice(&map, get_key, &3), &[(3, "three-a"), (3, "three-b")]);
+ assert_eq!(binary_search_slice(&map, get_key, &22), &[(22, "twenty-two")]);
+ assert_eq!(binary_search_slice(&map, get_key, &23), &[]);
+}
/// Iterates over the indices of set bits in a sorted order.
#[inline]
- pub fn iter<'a>(&'a self) -> BitIter<'a, T> {
+ pub fn iter(&self) -> BitIter<'_, T> {
BitIter {
cur: None,
iter: self.words.iter().enumerate(),
/// Iterates through all the columns set to true in a given row of
/// the matrix.
- pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
+ pub fn iter(&self, row: R) -> BitIter<'_, C> {
assert!(row.index() < self.num_rows);
let (start, end) = self.range(row);
BitIter {
Ok(())
}
- pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
+ pub fn decode_opaque(decoder: &mut Decoder<'_>) -> Result<Fingerprint, String> {
let mut bytes = [0; 16];
decoder.read_raw_bytes(&mut bytes)?;
self.incoming_edges(target).sources()
}
- pub fn depth_traverse<'a>(
- &'a self,
+ pub fn depth_traverse(
+ &self,
start: NodeIndex,
direction: Direction,
- ) -> DepthFirstTraversal<'a, N, E> {
+ ) -> DepthFirstTraversal<'_, N, E> {
DepthFirstTraversal::with_start_node(self, start, direction)
}
use super::super::indexed_vec::IndexVec;
-use super::{DirectedGraph, WithSuccessors, WithNumNodes};
+use super::{DirectedGraph, WithNumNodes, WithSuccessors};
+use crate::bit_set::BitSet;
#[cfg(test)]
mod test;
vec.reverse();
vec
}
+
+/// A "depth-first search" iterator for a directed graph.
+pub struct DepthFirstSearch<'graph, G>
+where
+ G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+ graph: &'graph G,
+ stack: Vec<G::Node>,
+ visited: BitSet<G::Node>,
+}
+
+impl<G> DepthFirstSearch<'graph, G>
+where
+ G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+ pub fn new(graph: &'graph G, start_node: G::Node) -> Self {
+ Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) }
+ }
+}
+
+impl<G> Iterator for DepthFirstSearch<'_, G>
+where
+ G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+ type Item = G::Node;
+
+ fn next(&mut self) -> Option<G::Node> {
+ let DepthFirstSearch { stack, visited, graph } = self;
+ let n = stack.pop()?;
+ stack.extend(graph.successors(n).filter(|&m| visited.insert(m)));
+ Some(n)
+ }
+}
pub mod iterate;
mod reference;
pub mod scc;
+pub mod vec_graph;
#[cfg(test)]
mod test;
fn num_nodes(&self) -> usize;
}
+pub trait WithNumEdges: DirectedGraph {
+ fn num_edges(&self) -> usize;
+}
+
pub trait WithSuccessors: DirectedGraph
where
Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
- fn successors<'graph>(
- &'graph self,
+ fn successors(
+ &self,
node: Self::Node,
- ) -> <Self as GraphSuccessors<'graph>>::Iter;
+ ) -> <Self as GraphSuccessors<'_>>::Iter;
+
+ fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
+ where
+ Self: WithNumNodes,
+ {
+ iterate::DepthFirstSearch::new(self, from)
+ }
}
pub trait GraphSuccessors<'graph> {
where
Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
- fn predecessors<'graph>(
- &'graph self,
+ fn predecessors(
+ &self,
node: Self::Node,
- ) -> <Self as GraphPredecessors<'graph>>::Iter;
+ ) -> <Self as GraphPredecessors<'_>>::Iter;
}
pub trait GraphPredecessors<'graph> {
}
impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G {
- fn successors<'iter>(&'iter self, node: Self::Node) -> <Self as GraphSuccessors<'iter>>::Iter {
+ fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
(**self).successors(node)
}
}
impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G {
- fn predecessors<'iter>(&'iter self,
- node: Self::Node)
- -> <Self as GraphPredecessors<'iter>>::Iter {
+ fn predecessors(&self,
+ node: Self::Node)
+ -> <Self as GraphPredecessors<'_>>::Iter {
(**self).predecessors(node)
}
}
//! O(n) time.
use crate::fx::FxHashSet;
-use crate::graph::{DirectedGraph, WithNumNodes, WithSuccessors};
+use crate::graph::{DirectedGraph, WithNumNodes, WithNumEdges, WithSuccessors, GraphSuccessors};
+use crate::graph::vec_graph::VecGraph;
use crate::indexed_vec::{Idx, IndexVec};
use std::ops::Range;
pub fn successors(&self, scc: S) -> &[S] {
self.scc_data.successors(scc)
}
+
+ /// Construct the reverse graph of the SCC graph.
+ pub fn reverse(&self) -> VecGraph<S> {
+ VecGraph::new(
+ self.num_sccs(),
+ self.all_sccs()
+ .flat_map(|source| self.successors(source).iter().map(move |&target| {
+ (target, source)
+ }))
+ .collect(),
+ )
+ }
+}
+
+impl<N: Idx, S: Idx> DirectedGraph for Sccs<N, S> {
+ type Node = S;
+}
+
+impl<N: Idx, S: Idx> WithNumNodes for Sccs<N, S> {
+ fn num_nodes(&self) -> usize {
+ self.num_sccs()
+ }
+}
+
+impl<N: Idx, S: Idx> WithNumEdges for Sccs<N, S> {
+ fn num_edges(&self) -> usize {
+ self.scc_data.all_successors.len()
+ }
+}
+
+impl<N: Idx, S: Idx> GraphSuccessors<'graph> for Sccs<N, S> {
+ type Item = S;
+
+ type Iter = std::iter::Cloned<std::slice::Iter<'graph, S>>;
+}
+
+impl<N: Idx, S: Idx> WithSuccessors for Sccs<N, S> {
+ fn successors<'graph>(
+ &'graph self,
+ node: S
+ ) -> <Self as GraphSuccessors<'graph>>::Iter {
+ self.successors(node).iter().cloned()
+ }
}
impl<S: Idx> SccData<S> {
}
impl WithPredecessors for TestGraph {
- fn predecessors<'graph>(&'graph self,
- node: usize)
- -> <Self as GraphPredecessors<'graph>>::Iter {
+ fn predecessors(&self,
+ node: usize)
+ -> <Self as GraphPredecessors<'_>>::Iter {
self.predecessors[&node].iter().cloned()
}
}
impl WithSuccessors for TestGraph {
- fn successors<'graph>(&'graph self, node: usize) -> <Self as GraphSuccessors<'graph>>::Iter {
+ fn successors(&self, node: usize) -> <Self as GraphSuccessors<'_>>::Iter {
self.successors[&node].iter().cloned()
}
}
--- /dev/null
+use crate::indexed_vec::{Idx, IndexVec};
+use crate::graph::{DirectedGraph, WithNumNodes, WithNumEdges, WithSuccessors, GraphSuccessors};
+
+#[cfg(test)]
+mod test;
+
+pub struct VecGraph<N: Idx> {
+ /// Maps from a given node to an index where the set of successors
+ /// for that node starts. The index indexes into the `edges`
+ /// vector. To find the range for a given node, we look up the
+ /// start for that node and then the start for the next node
+ /// (i.e., with an index 1 higher) and get the range between the
+ /// two. This vector always has an extra entry so that this works
+ /// even for the max element.
+ node_starts: IndexVec<N, usize>,
+
+ edge_targets: Vec<N>,
+}
+
+impl<N: Idx> VecGraph<N> {
+ pub fn new(
+ num_nodes: usize,
+ mut edge_pairs: Vec<(N, N)>,
+ ) -> Self {
+ // Sort the edges by the source -- this is important.
+ edge_pairs.sort();
+
+ let num_edges = edge_pairs.len();
+
+ // Store the *target* of each edge into `edge_targets`.
+ let edge_targets: Vec<N> = edge_pairs.iter().map(|&(_, target)| target).collect();
+
+ // Create the *edge starts* array. We are iterating over over
+ // the (sorted) edge pairs. We maintain the invariant that the
+ // length of the `node_starts` arary is enough to store the
+ // current source node -- so when we see that the source node
+ // for an edge is greater than the current length, we grow the
+ // edge-starts array by just enough.
+ let mut node_starts = IndexVec::with_capacity(num_edges);
+ for (index, &(source, _)) in edge_pairs.iter().enumerate() {
+ // If we have a list like `[(0, x), (2, y)]`:
+ //
+ // - Start out with `node_starts` of `[]`
+ // - Iterate to `(0, x)` at index 0:
+ // - Push one entry because `node_starts.len()` (0) is <= the source (0)
+ // - Leaving us with `node_starts` of `[0]`
+ // - Iterate to `(2, y)` at index 1:
+ // - Push one entry because `node_starts.len()` (1) is <= the source (2)
+ // - Push one entry because `node_starts.len()` (2) is <= the source (2)
+ // - Leaving us with `node_starts` of `[0, 1, 1]`
+ // - Loop terminates
+ while node_starts.len() <= source.index() {
+ node_starts.push(index);
+ }
+ }
+
+ // Pad out the `node_starts` array so that it has `num_nodes +
+ // 1` entries. Continuing our example above, if `num_nodes` is
+ // be `3`, we would push one more index: `[0, 1, 1, 2]`.
+ //
+ // Interpretation of that vector:
+ //
+ // [0, 1, 1, 2]
+ // ---- range for N=2
+ // ---- range for N=1
+ // ---- range for N=0
+ while node_starts.len() <= num_nodes {
+ node_starts.push(edge_targets.len());
+ }
+
+ assert_eq!(node_starts.len(), num_nodes + 1);
+
+ Self { node_starts, edge_targets }
+ }
+
+ /// Gets the successors for `source` as a slice.
+ pub fn successors(&self, source: N) -> &[N] {
+ let start_index = self.node_starts[source];
+ let end_index = self.node_starts[source.plus(1)];
+ &self.edge_targets[start_index..end_index]
+ }
+}
+
+impl<N: Idx> DirectedGraph for VecGraph<N> {
+ type Node = N;
+}
+
+impl<N: Idx> WithNumNodes for VecGraph<N> {
+ fn num_nodes(&self) -> usize {
+ self.node_starts.len() - 1
+ }
+}
+
+impl<N: Idx> WithNumEdges for VecGraph<N> {
+ fn num_edges(&self) -> usize {
+ self.edge_targets.len()
+ }
+}
+
+impl<N: Idx> GraphSuccessors<'graph> for VecGraph<N> {
+ type Item = N;
+
+ type Iter = std::iter::Cloned<std::slice::Iter<'graph, N>>;
+}
+
+impl<N: Idx> WithSuccessors for VecGraph<N> {
+ fn successors<'graph>(
+ &'graph self,
+ node: N
+ ) -> <Self as GraphSuccessors<'graph>>::Iter {
+ self.successors(node).iter().cloned()
+ }
+}
--- /dev/null
+use super::*;
+
+fn create_graph() -> VecGraph<usize> {
+ // Create a simple graph
+ //
+ // 5
+ // |
+ // V
+ // 0 --> 1 --> 2
+ // |
+ // v
+ // 3 --> 4
+ //
+ // 6
+
+ VecGraph::new(
+ 7,
+ vec![
+ (0, 1),
+ (1, 2),
+ (1, 3),
+ (3, 4),
+ (5, 1),
+ ],
+ )
+}
+
+#[test]
+fn num_nodes() {
+ let graph = create_graph();
+ assert_eq!(graph.num_nodes(), 7);
+}
+
+#[test]
+fn succesors() {
+ let graph = create_graph();
+ assert_eq!(graph.successors(0), &[1]);
+ assert_eq!(graph.successors(1), &[2, 3]);
+ assert_eq!(graph.successors(2), &[]);
+ assert_eq!(graph.successors(3), &[4]);
+ assert_eq!(graph.successors(4), &[]);
+ assert_eq!(graph.successors(5), &[1]);
+ assert_eq!(graph.successors(6), &[]);
+}
+
+#[test]
+fn dfs() {
+ let graph = create_graph();
+ let dfs: Vec<_> = graph.depth_first_search(0).collect();
+ assert_eq!(dfs, vec![0, 1, 3, 4, 2]);
+}
fn index(self) -> usize;
fn increment_by(&mut self, amount: usize) {
- let v = self.index() + amount;
- *self = Self::new(v);
+ *self = self.plus(amount);
+ }
+
+ fn plus(self, amount: usize) -> Self {
+ Self::new(self.index() + amount)
}
}
}
}
+ impl std::ops::Add<usize> for $type {
+ type Output = Self;
+
+ fn add(self, other: usize) -> Self {
+ Self::new(self.index() + other)
+ }
+ }
+
impl Idx for $type {
#[inline]
fn new(value: usize) -> Self {
#![cfg_attr(test, feature(test))]
#![deny(rust_2018_idioms)]
+#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
#[macro_use]
extern crate log;
pub mod macros;
pub mod svh;
pub mod base_n;
+pub mod binary_search_util;
pub mod bit_set;
pub mod box_region;
pub mod const_cstr;
/// A simple static assertion macro.
#[macro_export]
-#[cfg_attr(bootstrap, allow_internal_unstable(type_ascription, underscore_const_names))]
-#[cfg_attr(not(bootstrap), allow_internal_unstable(type_ascription))]
+#[allow_internal_unstable(type_ascription)]
macro_rules! static_assert {
($test:expr) => {
// Use the bool to access an array such that if the bool is false, the access
/// Type size assertion. The first argument is a type and the second argument is its expected size.
#[macro_export]
-#[cfg_attr(bootstrap, allow_internal_unstable(underscore_const_names))]
macro_rules! static_assert_size {
($ty:ty, $size:expr) => {
const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
self.edges.is_empty()
}
+ pub fn elements(&self) -> impl Iterator<Item=&T> {
+ self.elements.iter()
+ }
+
fn index(&self, a: &T) -> Option<Index> {
self.map.get(a).cloned()
}
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
pub extern crate getopts;
use rustc::lint::Lint;
use rustc::lint;
use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::util::common::{time, ErrorReported, install_panic_hook};
+use rustc::util::common::{ErrorReported, install_panic_hook, print_time_passes_entry};
+use rustc::util::common::{set_time_depth, time};
use rustc_metadata::locator;
use rustc_metadata::cstore::CStore;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use std::env;
use std::ffi::OsString;
use std::io::{self, Read, Write};
+use std::mem;
use std::panic::{self, catch_unwind};
use std::path::PathBuf;
use std::process::{self, Command, Stdio};
use std::str;
-use std::mem;
+use std::time::Instant;
use syntax::ast;
use syntax::source_map::FileLoader;
/// Exit status code used for successful compilation and help output.
pub const EXIT_SUCCESS: i32 = 0;
-/// Exit status code used for compilation failures and invalid flags.
+/// Exit status code used for compilation failures and invalid flags.
pub const EXIT_FAILURE: i32 = 1;
const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
impl Callbacks for DefaultCallbacks {}
+#[derive(Default)]
+pub struct TimePassesCallbacks {
+ time_passes: bool,
+}
+
+impl Callbacks for TimePassesCallbacks {
+ fn config(&mut self, config: &mut interface::Config) {
+ self.time_passes =
+ config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time;
+ }
+}
+
// Parse args and run the compiler. This is the primary entry point for rustc.
// See comments on CompilerCalls below for details about the callbacks argument.
// The FileLoader provides a way to load files from sources other than the file system.
}
pub fn main() {
+ let start = Instant::now();
init_rustc_env_logger();
+ let mut callbacks = TimePassesCallbacks::default();
let result = report_ices_to_stderr_if_any(|| {
let args = env::args_os().enumerate()
.map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
&format!("Argument {} is not valid Unicode: {:?}", i, arg))
}))
.collect::<Vec<_>>();
- run_compiler(&args, &mut DefaultCallbacks, None, None)
+ run_compiler(&args, &mut callbacks, None, None)
}).and_then(|result| result);
- process::exit(match result {
+ let exit_code = match result {
Ok(_) => EXIT_SUCCESS,
Err(_) => EXIT_FAILURE,
- });
+ };
+ // The extra `\t` is necessary to align this label with the others.
+ set_time_depth(0);
+ print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed());
+ process::exit(exit_code);
}
_ => panic!("Should use call_with_pp_support_hir"),
}
}
- fn call_with_pp_support_hir<'tcx, A, F>(&self, tcx: TyCtxt<'tcx>, f: F) -> A
+ fn call_with_pp_support_hir<A, F>(&self, tcx: TyCtxt<'_>, f: F) -> A
where
F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A,
{
trait PrinterSupport: pprust::PpAnn {
/// Provides a uniform interface for re-extracting a reference to a
/// `Session` from a value that now owns it.
- fn sess<'a>(&'a self) -> &'a Session;
+ fn sess(&self) -> &Session;
/// Produces the pretty-print annotation object.
///
trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
/// Provides a uniform interface for re-extracting a reference to a
/// `Session` from a value that now owns it.
- fn sess<'a>(&'a self) -> &'a Session;
+ fn sess(&self) -> &Session;
/// Provides a uniform interface for re-extracting a reference to an
/// `hir_map::Map` from a value that now owns it.
}
impl<'hir> PrinterSupport for NoAnn<'hir> {
- fn sess<'a>(&'a self) -> &'a Session {
+ fn sess(&self) -> &Session {
self.sess
}
}
impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
- fn sess<'a>(&'a self) -> &'a Session {
+ fn sess(&self) -> &Session {
self.sess
}
impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
- -> io::Result<()> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
if let Some(tcx) = self.tcx {
pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
- } else {
- Ok(())
}
}
}
}
impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
- fn sess<'a>(&'a self) -> &'a Session {
+ fn sess(&self) -> &Session {
self.sess
}
}
impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
- fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> {
+ fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
match node {
pprust::AnnNode::Expr(_) => s.popen(),
- _ => Ok(()),
+ _ => {}
}
}
- fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> {
+ fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
match node {
pprust::AnnNode::Ident(_) |
- pprust::AnnNode::Name(_) => Ok(()),
+ pprust::AnnNode::Name(_) => {},
pprust::AnnNode::Item(item) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(item.id.to_string())
}
pprust::AnnNode::SubItem(id) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(id.to_string())
}
pprust::AnnNode::Block(blk) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(format!("block {}", blk.id))
}
pprust::AnnNode::Expr(expr) => {
- s.s.space()?;
- s.synth_comment(expr.id.to_string())?;
+ s.s.space();
+ s.synth_comment(expr.id.to_string());
s.pclose()
}
pprust::AnnNode::Pat(pat) => {
- s.s.space()?;
- s.synth_comment(format!("pat {}", pat.id))
+ s.s.space();
+ s.synth_comment(format!("pat {}", pat.id));
}
}
}
}
impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
- fn sess<'a>(&'a self) -> &'a Session {
+ fn sess(&self) -> &Session {
self.sess
}
}
impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
- -> io::Result<()> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
if let Some(ref tcx) = self.tcx {
pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
- } else {
- Ok(())
}
}
- fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
+ fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
match node {
pprust_hir::AnnNode::Expr(_) => s.popen(),
- _ => Ok(()),
+ _ => {}
}
}
- fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
+ fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
match node {
- pprust_hir::AnnNode::Name(_) => Ok(()),
+ pprust_hir::AnnNode::Name(_) => {},
pprust_hir::AnnNode::Item(item) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(format!("hir_id: {} hir local_id: {}",
item.hir_id, item.hir_id.local_id.as_u32()))
}
pprust_hir::AnnNode::SubItem(id) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(id.to_string())
}
pprust_hir::AnnNode::Block(blk) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(format!("block hir_id: {} hir local_id: {}",
blk.hir_id, blk.hir_id.local_id.as_u32()))
}
pprust_hir::AnnNode::Expr(expr) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(format!("expr hir_id: {} hir local_id: {}",
- expr.hir_id, expr.hir_id.local_id.as_u32()))?;
+ expr.hir_id, expr.hir_id.local_id.as_u32()));
s.pclose()
}
pprust_hir::AnnNode::Pat(pat) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(format!("pat hir_id: {} hir local_id: {}",
pat.hir_id, pat.hir_id.local_id.as_u32()))
}
}
impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
- fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> {
+ fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
match node {
pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
- s.s.space()?;
+ s.s.space();
// FIXME #16420: this doesn't display the connections
// between syntax contexts
s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
}
pprust::AnnNode::Name(&name) => {
- s.s.space()?;
+ s.s.space();
s.synth_comment(name.as_u32().to_string())
}
- _ => Ok(()),
+ _ => {}
}
}
}
}
impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
- fn sess<'a>(&'a self) -> &'a Session {
+ fn sess(&self) -> &Session {
&self.tcx.sess
}
}
fn node_path(&self, id: hir::HirId) -> Option<String> {
- Some(self.tcx.def_path_str(self.tcx.hir().local_def_id_from_hir_id(id)))
+ Some(self.tcx.def_path_str(self.tcx.hir().local_def_id(id)))
}
}
impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
- -> io::Result<()> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
let old_tables = self.tables.get();
if let pprust_hir::Nested::Body(id) = nested {
self.tables.set(self.tcx.body_tables(id));
}
- pprust_hir::PpAnn::nested(self.tcx.hir(), state, nested)?;
+ pprust_hir::PpAnn::nested(self.tcx.hir(), state, nested);
self.tables.set(old_tables);
- Ok(())
}
- fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
+ fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
match node {
pprust_hir::AnnNode::Expr(_) => s.popen(),
- _ => Ok(()),
+ _ => {}
}
}
- fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
+ fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
match node {
pprust_hir::AnnNode::Expr(expr) => {
- s.s.space()?;
- s.s.word("as")?;
- s.s.space()?;
- s.s.word(self.tables.get().expr_ty(expr).to_string())?;
- s.pclose()
+ s.s.space();
+ s.s.word("as");
+ s.s.space();
+ s.s.word(self.tables.get().expr_ty(expr).to_string());
+ s.pclose();
}
- _ => Ok(()),
+ _ => {},
}
}
}
let (src, src_name) = get_source(input, sess);
let mut rdr = &*src;
- let mut out = Vec::new();
+ let mut out = String::new();
if let PpmSource(s) = ppm {
// Silently ignores an identified node.
- let out: &mut dyn Write = &mut out;
+ let out = &mut out;
s.call_with_pp_support(sess, None, move |annotation| {
debug!("pretty printing source code {:?}", s);
let sess = annotation.sess();
krate,
src_name,
&mut rdr,
- box out,
+ out,
annotation.pp_ann(),
false)
- }).unwrap()
+ })
} else {
unreachable!();
};
- write_output(out, ofile);
+ write_output(out.into_bytes(), ofile);
}
pub fn print_after_hir_lowering<'tcx>(
let (src, src_name) = get_source(input, tcx.sess);
let mut rdr = &src[..];
- let mut out = Vec::new();
+ let mut out = String::new();
match (ppm, opt_uii) {
(PpmSource(s), _) => {
// Silently ignores an identified node.
- let out: &mut dyn Write = &mut out;
+ let out = &mut out;
s.call_with_pp_support(tcx.sess, Some(tcx), move |annotation| {
debug!("pretty printing source code {:?}", s);
let sess = annotation.sess();
krate,
src_name,
&mut rdr,
- box out,
+ out,
annotation.pp_ann(),
true)
})
}
(PpmHir(s), None) => {
- let out: &mut dyn Write = &mut out;
+ let out = &mut out;
s.call_with_pp_support_hir(tcx, move |annotation, krate| {
debug!("pretty printing source code {:?}", s);
let sess = annotation.sess();
krate,
src_name,
&mut rdr,
- box out,
+ out,
annotation.pp_ann())
})
}
(PpmHirTree(s), None) => {
- let out: &mut dyn Write = &mut out;
+ let out = &mut out;
s.call_with_pp_support_hir(tcx, move |_annotation, krate| {
debug!("pretty printing source code {:?}", s);
- write!(out, "{:#?}", krate)
- })
+ *out = format!("{:#?}", krate);
+ });
}
(PpmHir(s), Some(uii)) => {
- let out: &mut dyn Write = &mut out;
+ let out = &mut out;
s.call_with_pp_support_hir(tcx, move |annotation, _| {
debug!("pretty printing source code {:?}", s);
let sess = annotation.sess();
&sess.parse_sess,
src_name,
&mut rdr,
- box out,
+ out,
annotation.pp_ann());
for node_id in uii.all_matching_node_ids(hir_map) {
let hir_id = tcx.hir().node_to_hir_id(node_id);
let node = hir_map.get(hir_id);
- pp_state.print_node(node)?;
- pp_state.s.space()?;
+ pp_state.print_node(node);
+ pp_state.s.space();
let path = annotation.node_path(hir_id)
.expect("-Z unpretty missing node paths");
- pp_state.synth_comment(path)?;
- pp_state.s.hardbreak()?;
+ pp_state.synth_comment(path);
+ pp_state.s.hardbreak();
}
- pp_state.s.eof()
+ pp_state.s.eof();
})
}
(PpmHirTree(s), Some(uii)) => {
- let out: &mut dyn Write = &mut out;
+ let out = &mut out;
s.call_with_pp_support_hir(tcx, move |_annotation, _krate| {
debug!("pretty printing source code {:?}", s);
for node_id in uii.all_matching_node_ids(tcx.hir()) {
let hir_id = tcx.hir().node_to_hir_id(node_id);
let node = tcx.hir().get(hir_id);
- write!(out, "{:#?}", node)?;
+ out.push_str(&format!("{:#?}", node));
}
- Ok(())
})
}
_ => unreachable!(),
}
- .unwrap();
- write_output(out, ofile);
+ write_output(out.into_bytes(), ofile);
}
// In an ideal world, this would be a public function called by the driver after
// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
// with a different callback than the standard driver, so that isn't easy.
// Instead, we call that function ourselves.
-fn print_with_analysis<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn print_with_analysis(
+ tcx: TyCtxt<'_>,
ppm: PpMode,
uii: Option<UserIdentifiedItem>,
ofile: Option<&Path>,
let mut print = || match ppm {
PpmMir | PpmMirCFG => {
if let Some(nodeid) = nodeid {
- let def_id = tcx.hir().local_def_id(nodeid);
+ let def_id = tcx.hir().local_def_id_from_node_id(nodeid);
match ppm {
PpmMir => write_mir_pretty(tcx, Some(def_id), &mut out),
PpmMirCFG => write_mir_graphviz(tcx, Some(def_id), &mut out),
}
}
- fn writable<'a>(&'a mut self) -> WritableDst<'a> {
+ fn writable(&mut self) -> WritableDst<'_> {
match *self {
Destination::Terminal(ref mut t) => WritableDst::Terminal(t),
Destination::Buffered(ref mut t) => {
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[allow(unused_extern_crates)]
self.err_count.store(0, SeqCst);
}
- pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
+ pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Cancelled, "")
}
- pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_warn<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
result.set_span(sp);
if !self.flags.can_emit_warnings {
}
result
}
- pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
result.set_span(sp);
result.code(code);
}
result
}
- pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
if !self.flags.can_emit_warnings {
result.cancel();
}
result
}
- pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_err<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
result.set_span(sp);
result
}
- pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
result.set_span(sp);
result.code(code);
result
}
// FIXME: This method should be removed (every error should have an associated error code).
- pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Error, msg)
}
- pub fn struct_err_with_code<'a>(
- &'a self,
+ pub fn struct_err_with_code(
+ &self,
msg: &str,
code: DiagnosticId,
- ) -> DiagnosticBuilder<'a> {
+ ) -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
result.code(code);
result
}
- pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
result.set_span(sp);
result
}
- pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'a> {
+ pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
result.set_span(sp);
result.code(code);
result
}
- pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+ pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Fatal, msg)
}
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Error);
}
- pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn mut_span_err<S: Into<MultiSpan>>(&self,
+ sp: S,
+ msg: &str)
+ -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
result.set_span(sp);
result
pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Note);
}
- pub fn span_note_diag<'a>(&'a self,
- sp: Span,
- msg: &str)
- -> DiagnosticBuilder<'a> {
+ pub fn span_note_diag(&self,
+ sp: Span,
+ msg: &str)
+ -> DiagnosticBuilder<'_> {
let mut db = DiagnosticBuilder::new(self, Note, msg);
db.set_span(sp);
db
use syntax::ast;
use syntax_pos::Span;
-pub fn assert_dep_graph<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
tcx.dep_graph.with_ignore(|| {
if tcx.sess.opts.debugging_opts.dump_dep_graph {
dump_graph(tcx);
}
fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = self.tcx.hir().local_def_id(hir_id);
let def_path_hash = self.tcx.def_path_hash(def_id);
for attr in attrs {
if attr.check_name(ATTR_IF_THIS_CHANGED) {
const CFG: Symbol = sym::cfg;
const KIND: Symbol = sym::kind;
-pub fn assert_module_sources<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn assert_module_sources(tcx: TyCtxt<'_>) {
tcx.dep_graph.with_ignore(|| {
if tcx.sess.opts.incremental.is_none() {
return;
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use] extern crate rustc;
}
}
-pub fn check_dirty_clean_annotations<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
// can't add `#[rustc_dirty]` etc without opting in to this feature
if !tcx.features().rustc_attrs {
return;
}
fn check_item(&mut self, item_id: hir::HirId, item_span: Span) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item_id);
+ let def_id = self.tcx.hir().local_def_id(item_id);
for attr in self.tcx.get_attrs(def_id).iter() {
let assertion = match self.assertion_maybe(item_id, attr) {
Some(a) => a,
use super::file_format;
use super::work_product;
-pub fn dep_graph_tcx_init<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn dep_graph_tcx_init(tcx: TyCtxt<'_>) {
if !tcx.dep_graph.is_fully_enabled() {
return
}
}))
}
-pub fn load_query_result_cache<'sess>(sess: &'sess Session) -> OnDiskCache<'sess> {
+pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> {
if sess.opts.incremental.is_none() ||
!sess.opts.debugging_opts.incremental_queries {
return OnDiskCache::new_empty(sess.source_map());
use super::file_format;
use super::work_product;
-pub fn save_dep_graph<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn save_dep_graph(tcx: TyCtxt<'_>) {
debug!("save_dep_graph()");
tcx.dep_graph.with_ignore(|| {
let sess = tcx.sess;
#![cfg_attr(unix, feature(libc))]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![allow(unused_imports)]
/// Runs the resolution, type-checking, region checking and other
/// miscellaneous analysis passes on the crate.
-fn analysis<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Result<()> {
+fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
assert_eq!(cnum, LOCAL_CRATE);
let sess = tcx.sess;
});
}, {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
- tcx.ensure().check_mod_loops(tcx.hir().local_def_id(module));
- tcx.ensure().check_mod_attrs(tcx.hir().local_def_id(module));
- tcx.ensure().check_mod_unstable_api_usage(tcx.hir().local_def_id(module));
+ tcx.ensure().check_mod_loops(tcx.hir().local_def_id_from_node_id(module));
+ tcx.ensure().check_mod_attrs(tcx.hir().local_def_id_from_node_id(module));
+ tcx.ensure().check_mod_unstable_api_usage(
+ tcx.hir().local_def_id_from_node_id(module));
});
});
});
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
- tcx.ensure().check_mod_liveness(tcx.hir().local_def_id(module));
+ tcx.ensure().check_mod_liveness(tcx.hir().local_def_id_from_node_id(module));
- tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id(module));
+ tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id_from_node_id(module));
});
});
});
}, {
time(sess, "privacy checking modules", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
- tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
+ tcx.ensure().check_mod_privacy(tcx.hir().local_def_id_from_node_id(module));
});
});
});
Ok(())
}
-fn encode_and_write_metadata<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn encode_and_write_metadata(
+ tcx: TyCtxt<'_>,
outputs: &OutputFilenames,
) -> (middle::cstore::EncodedMetadata, bool) {
#[derive(PartialEq, Eq, PartialOrd, Ord)]
use syntax::attr;
use syntax::symbol::sym;
-pub fn find<'tcx>(tcx: TyCtxt<'tcx>) -> Option<DefId> {
+pub fn find(tcx: TyCtxt<'_>) -> Option<DefId> {
tcx.proc_macro_decls_static(LOCAL_CRATE)
}
-fn proc_macro_decls_static<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Option<DefId> {
+fn proc_macro_decls_static(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
assert_eq!(cnum, LOCAL_CRATE);
let mut finder = Finder { decls: None };
tcx.hir().krate().visit_all_item_likes(&mut finder);
- finder.decls.map(|id| tcx.hir().local_def_id_from_hir_id(id))
+ finder.decls.map(|id| tcx.hir().local_def_id(id))
}
struct Finder {
);
None
} else {
+ if !sess.opts.cg.extra_filename.is_empty() {
+ sess.warn("ignoring -C extra-filename flag due to -o flag");
+ }
Some(out_file.clone())
};
if *odir != None {
sess.warn("ignoring --out-dir flag due to -o flag");
}
- if !sess.opts.cg.extra_filename.is_empty() {
- sess.warn("ignoring -C extra-filename flag due to -o flag");
- }
OutputFilenames {
out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
hir::ItemKind::Enum(..) |
hir::ItemKind::Struct(..) |
hir::ItemKind::Union(..) => {
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(it.hir_id);
self.check_heap_type(cx, it.span, cx.tcx.type_of(def_id))
}
_ => ()
hir::ItemKind::Struct(ref struct_def, _) |
hir::ItemKind::Union(ref struct_def, _) => {
for struct_field in struct_def.fields() {
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(struct_field.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(struct_field.hir_id);
self.check_heap_type(cx, struct_field.span,
cx.tcx.type_of(def_id));
}
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.hir_id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Union(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.hir_id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Enum(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.hir_id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
_ => return,
_ => return,
};
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(it.hir_id);
let prfn = match cx.tcx.extern_mod_stmt_cnum(def_id) {
Some(cnum) => cx.tcx.plugin_registrar_fn(cnum),
None => {
if let hir::ItemKind::Union(ref vdata, _) = item.node {
for field in vdata.fields() {
let field_ty = ctx.tcx.type_of(
- ctx.tcx.hir().local_def_id_from_hir_id(field.hir_id));
+ ctx.tcx.hir().local_def_id(field.hir_id));
if field_ty.needs_drop(ctx.tcx, ctx.param_env) {
ctx.span_lint(UNIONS_WITH_DROP_FIELDS,
field.span,
use rustc::ty::Predicate::*;
if cx.tcx.features().trivial_bounds {
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let predicates = cx.tcx.predicates_of(def_id);
for &(predicate, span) in &predicates.predicates {
let predicate_kind_name = match predicate {
ty_generics: &'tcx ty::Generics,
) -> Vec<ty::Region<'tcx>> {
let index = ty_generics.param_def_id_to_index[
- &tcx.hir().local_def_id_from_hir_id(param.hir_id)];
+ &tcx.hir().local_def_id(param.hir_id)];
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
use rustc::middle::resolve_lifetime::Region;
let infer_static = cx.tcx.features().infer_static_outlives_requirements;
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(item.hir_id);
if let hir::ItemKind::Struct(_, ref hir_generics)
| hir::ItemKind::Enum(_, ref hir_generics)
| hir::ItemKind::Union(_, ref hir_generics) = item.node
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use]
};
}
-fn lint_mod<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn lint_mod(tcx: TyCtxt<'_>, module_def_id: DefId) {
lint::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
}
pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
+ store.register_early_pass(sess, false, false, box LintPassImpl);
store.register_late_pass(sess, false, false, false, box TyTyKind);
store.register_group(
sess,
false,
- "internal",
+ "rustc::internal",
None,
vec![
LintId::of(DEFAULT_HASH_TYPES),
LintId::of(USAGE_OF_TY_TYKIND),
+ LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
LintId::of(TY_PASS_BY_REFERENCE),
LintId::of(USAGE_OF_QUALIFIED_TY),
],
}
pub fn method_context(cx: &LateContext<'_, '_>, id: hir::HirId) -> MethodLateContext {
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = cx.tcx.hir().local_def_id(id);
let item = cx.tcx.associated_item(def_id);
match item.container {
ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
}
fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl) {
- let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = self.cx.tcx.hir().local_def_id(id);
let sig = self.cx.tcx.fn_sig(def_id);
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
let inputs = if sig.c_variadic {
}
fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
- let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = self.cx.tcx.hir().local_def_id(id);
let ty = self.cx.tcx.type_of(def_id);
self.check_type_for_ffi_and_report_errors(span, ty);
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
if let hir::ItemKind::Enum(ref enum_definition, _) = it.node {
- let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let item_def_id = cx.tcx.hir().local_def_id(it.hir_id);
let t = cx.tcx.type_of(item_def_id);
let ty = cx.tcx.erase_regions(&t);
let layout = match cx.layout_of(ty) {
}
let ty = cx.tables.expr_ty(&expr);
- let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "");
+ let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", false);
let mut fn_warned = false;
let mut op_warned = false;
ty: Ty<'tcx>,
expr: &hir::Expr,
span: Span,
- descr_post_path: &str,
+ descr_pre: &str,
+ descr_post: &str,
+ plural: bool,
) -> bool {
if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(
cx.tcx.hir().get_module_parent(expr.hir_id), ty)
return true;
}
+ let plural_suffix = if plural { "s" } else { "" };
+
match ty.sty {
- ty::Adt(def, _) => check_must_use_def(cx, def.did, span, "", descr_post_path),
+ ty::Adt(..) if ty.is_box() => {
+ let boxed_ty = ty.boxed_ty();
+ let descr_pre = &format!("{}boxed ", descr_pre);
+ check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural)
+ }
+ ty::Adt(def, _) => {
+ check_must_use_def(cx, def.did, span, descr_pre, descr_post)
+ }
ty::Opaque(def, _) => {
let mut has_emitted = false;
for (predicate, _) in &cx.tcx.predicates_of(def).predicates {
if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
let def_id = trait_ref.def_id;
- if check_must_use_def(cx, def_id, span, "implementer of ", "") {
+ let descr_pre = &format!(
+ "{}implementer{} of ",
+ descr_pre,
+ plural_suffix,
+ );
+ if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
has_emitted = true;
break;
}
for predicate in binder.skip_binder().iter() {
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
let def_id = trait_ref.def_id;
- if check_must_use_def(cx, def_id, span, "", " trait object") {
+ let descr_post = &format!(
+ " trait object{}{}",
+ plural_suffix,
+ descr_post,
+ );
+ if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
has_emitted = true;
break;
}
vec![]
};
for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
- let descr_post_path = &format!(" in tuple element {}", i);
+ let descr_post = &format!(" in tuple element {}", i);
let span = *spans.get(i).unwrap_or(&span);
- if check_must_use_ty(cx, ty, expr, span, descr_post_path) {
+ if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural) {
has_emitted = true;
}
}
has_emitted
}
+ ty::Array(ty, len) => match len.assert_usize(cx.tcx) {
+ // If the array is definitely non-empty, we can do `#[must_use]` checking.
+ Some(n) if n != 0 => {
+ let descr_pre = &format!(
+ "{}array{} of ",
+ descr_pre,
+ plural_suffix,
+ );
+ check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, true)
+ }
+ // Otherwise, we don't lint, to avoid false positives.
+ _ => false,
+ }
_ => false,
}
}
#![feature(proc_macro_hygiene)]
#![deny(rust_2018_idioms)]
+#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
#![recursion_limit="128"]
let mut dep_node_force_stream = quote! {};
let mut try_load_from_on_disk_cache_stream = quote! {};
let mut no_force_queries = Vec::new();
+ let mut cached_queries = quote! {};
for group in groups.0 {
let mut group_stream = quote! {};
_ => quote! { #result_full },
};
+ if modifiers.cache.is_some() {
+ cached_queries.extend(quote! {
+ #name,
+ });
+ }
+
if modifiers.cache.is_some() && !modifiers.no_force {
try_load_from_on_disk_cache_stream.extend(quote! {
DepKind::#name => {
}
}
}
+ macro_rules! rustc_cached_queries {
+ ($($macro:tt)*) => {
+ $($macro)*(#cached_queries);
+ }
+ }
+
#query_description_stream
impl DepNode {
fn inject_profiler_runtime(&mut self) {
if self.sess.opts.debugging_opts.profile ||
- self.sess.opts.debugging_opts.pgo_gen.enabled()
+ self.sess.opts.cg.profile_generate.enabled()
{
info!("loading profiler");
exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
}
-pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
+pub fn provide(providers: &mut Providers<'_>) {
// FIXME(#44234) - almost all of these queries have no sub-queries and
// therefore no actual inputs, they're just reading tables calculated in
// resolve! Does this work? Unsure! That's what the issue is about
self.do_postorder_cnums_untracked()
}
- fn encode_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>) -> EncodedMetadata {
+ fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
encoder::encode_metadata(tcx)
}
(id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility),
) -> Entry<'tcx> {
let tcx = self.tcx;
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
let data = ModData {
span: self.lazy(&tcx.def_span(def_id)),
attributes: self.encode_attributes(attrs),
children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
- tcx.hir().local_def_id_from_hir_id(item_id.id).index
+ tcx.hir().local_def_id(item_id.id).index
})),
stability: self.encode_stability(def_id),
deprecation: self.encode_deprecation(def_id),
// for methods, write all the stuff get_trait_method
// needs to know
let ctor = struct_def.ctor_hir_id()
- .map(|ctor_hir_id| tcx.hir().local_def_id_from_hir_id(ctor_hir_id).index);
+ .map(|ctor_hir_id| tcx.hir().local_def_id(ctor_hir_id).index);
let repr_options = get_repr_options(tcx, def_id);
hir::ItemKind::ForeignMod(ref fm) => {
self.lazy_seq(fm.items
.iter()
- .map(|foreign_item| tcx.hir().local_def_id_from_hir_id(
+ .map(|foreign_item| tcx.hir().local_def_id(
foreign_item.hir_id).index))
}
hir::ItemKind::Enum(..) => {
/// Serialize the text of exported macros
fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> {
use syntax::print::pprust;
- let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
+ let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
Entry {
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
body: pprust::tts_to_string(¯o_def.body.trees().collect::<Vec<_>>()),
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
intravisit::walk_item(self, item);
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
match item.node {
hir::ItemKind::ExternCrate(_) |
hir::ItemKind::Use(..) => {} // ignore these
}
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
intravisit::walk_foreign_item(self, ni);
- let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
+ let def_id = self.tcx.hir().local_def_id(ni.hir_id);
self.record(def_id,
EncodeContext::encode_info_for_foreign_item,
(def_id, ni));
intravisit::walk_variant(self, v, g, id);
if let Some(ref discr) = v.node.disr_expr {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
+ let def_id = self.tcx.hir().local_def_id(discr.hir_id);
self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
}
}
self.encode_info_for_ty(ty);
}
fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
+ let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
}
}
fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
for param in &generics.params {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ let def_id = self.tcx.hir().local_def_id(param.hir_id);
match param.kind {
GenericParamKind::Lifetime { .. } => continue,
GenericParamKind::Type { ref default, .. } => {
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
match ty.node {
hir::TyKind::Array(_, ref length) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
+ let def_id = self.tcx.hir().local_def_id(length.hir_id);
self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
}
_ => {}
fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprKind::Closure(..) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
+ let def_id = self.tcx.hir().local_def_id(expr.hir_id);
self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
}
_ => {}
/// so it's easier to do that here then to wait until we would encounter
/// normally in the visitor walk.
fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
match item.node {
hir::ItemKind::Static(..) |
hir::ItemKind::Const(..) |
// If the struct has a constructor, encode it.
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
- let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
+ let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
self.record(ctor_def_id,
EncodeContext::encode_struct_ctor,
(def_id, ctor_def_id));
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if let hir::ItemKind::Impl(..) = item.node {
- let impl_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let impl_id = self.tcx.hir().local_def_id(item.hir_id);
if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
self.impls
.entry(trait_ref.def_id)
// will allow us to slice the metadata to the precise length that we just
// generated regardless of trailing bytes that end up in it.
-pub fn encode_metadata<'tcx>(tcx: TyCtxt<'tcx>) -> EncodedMetadata {
+pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
let mut encoder = opaque::Encoder::new(vec![]);
encoder.emit_raw_bytes(METADATA_HEADER);
EncodedMetadata { raw_data: result }
}
-pub fn get_repr_options<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> ReprOptions {
+pub fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
let ty = tcx.type_of(did);
match ty.sty {
ty::Adt(ref def, _) => return def.repr,
use rustc::middle::cstore::ForeignModule;
use rustc::ty::TyCtxt;
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<ForeignModule> {
+pub fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
let mut collector = Collector {
tcx,
modules: Vec::new(),
};
let foreign_items = fm.items.iter()
- .map(|it| self.tcx.hir().local_def_id_from_hir_id(it.hir_id))
+ .map(|it| self.tcx.hir().local_def_id(it.hir_id))
.collect();
self.modules.push(ForeignModule {
foreign_items,
- def_id: self.tcx.hir().local_def_id_from_hir_id(it.hir_id),
+ def_id: self.tcx.hir().local_def_id(it.hir_id),
});
}
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
extern crate libc;
use rustc_target::spec::abi::Abi;
use syntax::symbol::sym;
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<String> {
+pub fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
let mut collector = Collector {
args: Vec::new(),
};
use syntax::symbol::{Symbol, sym};
use syntax::{span_err, struct_span_err};
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<NativeLibrary> {
+pub fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
let mut collector = Collector {
tcx,
libs: Vec::new(),
name: None,
kind: cstore::NativeUnknown,
cfg: None,
- foreign_module: Some(self.tcx.hir().local_def_id_from_hir_id(it.hir_id)),
+ foreign_module: Some(self.tcx.hir().local_def_id(it.hir_id)),
wasm_import_module: None,
};
let mut kind_specified = false;
};
}
-fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BorrowCheckResult<'tcx> {
+fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> {
let input_body = tcx.mir_validated(def_id);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id));
mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
// Convert any reservation warnings into lints.
- let reservation_warnings = mem::replace(&mut mbcx.reservation_warnings, Default::default());
+ let reservation_warnings = mem::take(&mut mbcx.reservation_warnings);
for (_, (place, span, location, bk, borrow)) in reservation_warnings {
let mut initial_diag =
mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow);
use crate::borrow_check::nll::type_check::Locations;
-use crate::borrow_check::nll::constraints::ConstraintIndex;
-use crate::borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::OutlivesConstraintIndex;
+use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
use rustc::mir::ConstraintCategory;
use rustc::ty::RegionVid;
use rustc_data_structures::graph;
/// -> R2` or `R2 -> R1` depending on the direction type `D`.
crate struct ConstraintGraph<D: ConstraintGraphDirecton> {
_direction: D,
- first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
- next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
+ first_constraints: IndexVec<RegionVid, Option<OutlivesConstraintIndex>>,
+ next_constraints: IndexVec<OutlivesConstraintIndex, Option<OutlivesConstraintIndex>>,
}
crate type NormalConstraintGraph = ConstraintGraph<Normal>;
/// reporting.
crate fn new(
direction: D,
- set: &ConstraintSet,
+ set: &OutlivesConstraintSet,
num_region_vars: usize,
) -> Self {
let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
- let mut next_constraints = IndexVec::from_elem(None, &set.constraints);
+ let mut next_constraints = IndexVec::from_elem(None, &set.outlives);
- for (idx, constraint) in set.constraints.iter_enumerated().rev() {
+ for (idx, constraint) in set.outlives.iter_enumerated().rev() {
let head = &mut first_constraints[D::start_region(constraint)];
let next = &mut next_constraints[idx];
debug_assert!(next.is_none());
/// and not constraints.
crate fn region_graph<'rg>(
&'rg self,
- set: &'rg ConstraintSet,
+ set: &'rg OutlivesConstraintSet,
static_region: RegionVid,
) -> RegionGraph<'rg, D> {
RegionGraph::new(set, self, static_region)
crate fn outgoing_edges<'a>(
&'a self,
region_sup: RegionVid,
- constraints: &'a ConstraintSet,
+ constraints: &'a OutlivesConstraintSet,
static_region: RegionVid,
) -> Edges<'a, D> {
//if this is the `'static` region and the graph's direction is normal,
crate struct Edges<'s, D: ConstraintGraphDirecton> {
graph: &'s ConstraintGraph<D>,
- constraints: &'s ConstraintSet,
- pointer: Option<ConstraintIndex>,
+ constraints: &'s OutlivesConstraintSet,
+ pointer: Option<OutlivesConstraintIndex>,
next_static_idx: Option<usize>,
static_region: RegionVid,
}
/// reverse) constraint graph. It implements the graph traits and is
/// usd for doing the SCC computation.
crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
- set: &'s ConstraintSet,
+ set: &'s OutlivesConstraintSet,
constraint_graph: &'s ConstraintGraph<D>,
static_region: RegionVid,
}
/// construct SCCs for region inference but also for error
/// reporting.
crate fn new(
- set: &'s ConstraintSet,
+ set: &'s OutlivesConstraintSet,
constraint_graph: &'s ConstraintGraph<D>,
static_region: RegionVid,
) -> Self {
}
impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> {
- fn successors<'graph>(
- &'graph self,
+ fn successors(
+ &self,
node: Self::Node,
- ) -> <Self as graph::GraphSuccessors<'graph>>::Iter {
+ ) -> <Self as graph::GraphSuccessors<'_>>::Iter {
self.outgoing_regions(node)
}
}
+use crate::borrow_check::nll::type_check::Locations;
use rustc::mir::ConstraintCategory;
use rustc::ty::RegionVid;
use rustc_data_structures::graph::scc::Sccs;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use crate::borrow_check::nll::type_check::Locations;
-
use std::fmt;
-use std::ops::Deref;
+use std::ops::Index;
crate mod graph;
+/// A set of NLL region constraints. These include "outlives"
+/// constraints of the form `R1: R2`. Each constraint is identified by
+/// a unique `OutlivesConstraintIndex` and you can index into the set
+/// (`constraint_set[i]`) to access the constraint details.
#[derive(Clone, Default)]
-crate struct ConstraintSet {
- constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
+crate struct OutlivesConstraintSet {
+ outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint>,
}
-impl ConstraintSet {
+impl OutlivesConstraintSet {
crate fn push(&mut self, constraint: OutlivesConstraint) {
debug!(
- "ConstraintSet::push({:?}: {:?} @ {:?}",
+ "OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
constraint.sup, constraint.sub, constraint.locations
);
if constraint.sup == constraint.sub {
// 'a: 'a is pretty uninteresting
return;
}
- self.constraints.push(constraint);
+ self.outlives.push(constraint);
}
/// Constructs a "normal" graph from the constraint set; the graph makes it
/// easy to find the constraints affecting a particular region.
///
/// N.B., this graph contains a "frozen" view of the current
- /// constraints. Any new constraints added to the `ConstraintSet`
+ /// constraints. Any new constraints added to the `OutlivesConstraintSet`
/// after the graph is built will not be present in the graph.
crate fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph {
graph::ConstraintGraph::new(graph::Normal, self, num_region_vars)
let region_graph = &constraint_graph.region_graph(self, static_region);
Sccs::new(region_graph)
}
+
+ crate fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint> {
+ &self.outlives
+ }
}
-impl Deref for ConstraintSet {
- type Target = IndexVec<ConstraintIndex, OutlivesConstraint>;
+impl Index<OutlivesConstraintIndex> for OutlivesConstraintSet {
+ type Output = OutlivesConstraint;
- fn deref(&self) -> &Self::Target {
- &self.constraints
+ fn index(&self, i: OutlivesConstraintIndex) -> &Self::Output {
+ &self.outlives[i]
}
}
}
newtype_index! {
- pub struct ConstraintIndex {
- DEBUG_FORMAT = "ConstraintIndex({})"
+ pub struct OutlivesConstraintIndex {
+ DEBUG_FORMAT = "OutlivesConstraintIndex({})"
}
}
--- /dev/null
+use crate::rustc::ty::{self, Ty};
+use rustc::hir::def_id::DefId;
+use rustc::infer::region_constraints::MemberConstraint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use std::hash::Hash;
+use std::ops::Index;
+use syntax_pos::Span;
+
+/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
+/// indexed by the region `R0`.
+crate struct MemberConstraintSet<'tcx, R>
+where
+ R: Copy + Hash + Eq,
+{
+ /// Stores the first "member" constraint for a given `R0`. This is an
+ /// index into the `constraints` vector below.
+ first_constraints: FxHashMap<R, NllMemberConstraintIndex>,
+
+ /// Stores the data about each `R0 member of [R1..Rn]` constraint.
+ /// These are organized into a linked list, so each constraint
+ /// contains the index of the next constraint with the same `R0`.
+ constraints: IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'tcx>>,
+
+ /// Stores the `R1..Rn` regions for *all* sets. For any given
+ /// constraint, we keep two indices so that we can pull out a
+ /// slice.
+ choice_regions: Vec<ty::RegionVid>,
+}
+
+/// Represents a `R0 member of [R1..Rn]` constraint
+crate struct NllMemberConstraint<'tcx> {
+ next_constraint: Option<NllMemberConstraintIndex>,
+
+ /// The opaque type whose hidden type is being inferred. (Used in error reporting.)
+ crate opaque_type_def_id: DefId,
+
+ /// The span where the hidden type was instantiated.
+ crate definition_span: Span,
+
+ /// The hidden type in which `R0` appears. (Used in error reporting.)
+ crate hidden_ty: Ty<'tcx>,
+
+ /// The region `R0`.
+ crate member_region_vid: ty::RegionVid,
+
+ /// Index of `R1` in `choice_regions` vector from `MemberConstraintSet`.
+ start_index: usize,
+
+ /// Index of `Rn` in `choice_regions` vector from `MemberConstraintSet`.
+ end_index: usize,
+}
+
+newtype_index! {
+ crate struct NllMemberConstraintIndex {
+ DEBUG_FORMAT = "MemberConstraintIndex({})"
+ }
+}
+
+impl Default for MemberConstraintSet<'tcx, ty::RegionVid> {
+ fn default() -> Self {
+ Self {
+ first_constraints: Default::default(),
+ constraints: Default::default(),
+ choice_regions: Default::default(),
+ }
+ }
+}
+
+impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
+ /// Pushes a member constraint into the set.
+ ///
+ /// The input member constraint `m_c` is in the form produced by
+ /// the the `rustc::infer` code.
+ ///
+ /// The `to_region_vid` callback fn is used to convert the regions
+ /// within into `RegionVid` format -- it typically consults the
+ /// `UniversalRegions` data structure that is known to the caller
+ /// (but which this code is unaware of).
+ crate fn push_constraint(
+ &mut self,
+ m_c: &MemberConstraint<'tcx>,
+ mut to_region_vid: impl FnMut(ty::Region<'tcx>) -> ty::RegionVid,
+ ) {
+ debug!("push_constraint(m_c={:?})", m_c);
+ let member_region_vid: ty::RegionVid = to_region_vid(m_c.member_region);
+ let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
+ let start_index = self.choice_regions.len();
+ let end_index = start_index + m_c.choice_regions.len();
+ debug!("push_constraint: member_region_vid={:?}", member_region_vid);
+ let constraint_index = self.constraints.push(NllMemberConstraint {
+ next_constraint,
+ member_region_vid,
+ opaque_type_def_id: m_c.opaque_type_def_id,
+ definition_span: m_c.definition_span,
+ hidden_ty: m_c.hidden_ty,
+ start_index,
+ end_index,
+ });
+ self.first_constraints.insert(member_region_vid, constraint_index);
+ self.choice_regions.extend(m_c.choice_regions.iter().map(|&r| to_region_vid(r)));
+ }
+}
+
+impl<R1> MemberConstraintSet<'tcx, R1>
+where
+ R1: Copy + Hash + Eq,
+{
+ /// Remap the "member region" key using `map_fn`, producing a new
+ /// member constraint set. This is used in the NLL code to map from
+ /// the original `RegionVid` to an scc index. In some cases, we
+ /// may have multiple `R1` values mapping to the same `R2` key -- that
+ /// is ok, the two sets will be merged.
+ crate fn into_mapped<R2>(
+ self,
+ mut map_fn: impl FnMut(R1) -> R2,
+ ) -> MemberConstraintSet<'tcx, R2>
+ where
+ R2: Copy + Hash + Eq,
+ {
+ // We can re-use most of the original data, just tweaking the
+ // linked list links a bit.
+ //
+ // For example if we had two keys `Ra` and `Rb` that both now
+ // wind up mapped to the same key `S`, we would append the
+ // linked list for `Ra` onto the end of the linked list for
+ // `Rb` (or vice versa) -- this basically just requires
+ // rewriting the final link from one list to point at the othe
+ // other (see `append_list`).
+
+ let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
+
+ let mut first_constraints2 = FxHashMap::default();
+ first_constraints2.reserve(first_constraints.len());
+
+ for (r1, start1) in first_constraints {
+ let r2 = map_fn(r1);
+ if let Some(&start2) = first_constraints2.get(&r2) {
+ append_list(&mut constraints, start1, start2);
+ }
+ first_constraints2.insert(r2, start1);
+ }
+
+ MemberConstraintSet {
+ first_constraints: first_constraints2,
+ constraints,
+ choice_regions,
+ }
+ }
+}
+
+impl<R> MemberConstraintSet<'tcx, R>
+where
+ R: Copy + Hash + Eq,
+{
+ crate fn all_indices(
+ &self,
+ ) -> impl Iterator<Item = NllMemberConstraintIndex> {
+ self.constraints.indices()
+ }
+
+ /// Iterate down the constraint indices associated with a given
+ /// peek-region. You can then use `choice_regions` and other
+ /// methods to access data.
+ crate fn indices(
+ &self,
+ member_region_vid: R,
+ ) -> impl Iterator<Item = NllMemberConstraintIndex> + '_ {
+ let mut next = self.first_constraints.get(&member_region_vid).cloned();
+ std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
+ if let Some(current) = next {
+ next = self.constraints[current].next_constraint;
+ Some(current)
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Returns the "choice regions" for a given member
+ /// constraint. This is the `R1..Rn` from a constraint like:
+ ///
+ /// ```
+ /// R0 member of [R1..Rn]
+ /// ```
+ crate fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
+ let NllMemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
+ &self.choice_regions[*start_index..*end_index]
+ }
+}
+
+impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
+where
+ R: Copy + Hash + Eq,
+{
+ type Output = NllMemberConstraint<'tcx>;
+
+ fn index(&self, i: NllMemberConstraintIndex) -> &NllMemberConstraint<'tcx> {
+ &self.constraints[i]
+ }
+}
+
+/// Given a linked list starting at `source_list` and another linked
+/// list starting at `target_list`, modify `target_list` so that it is
+/// followed by `source_list`.
+///
+/// Before:
+///
+/// ```
+/// target_list: A -> B -> C -> (None)
+/// source_list: D -> E -> F -> (None)
+/// ```
+///
+/// After:
+///
+/// ```
+/// target_list: A -> B -> C -> D -> E -> F -> (None)
+/// ```
+fn append_list(
+ constraints: &mut IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
+ target_list: NllMemberConstraintIndex,
+ source_list: NllMemberConstraintIndex,
+) {
+ let mut p = target_list;
+ loop {
+ let mut r = &mut constraints[p];
+ match r.next_constraint {
+ Some(q) => p = q,
+ None => {
+ r.next_constraint = Some(source_list);
+ return;
+ }
+ }
+ }
+}
mod universal_regions;
mod constraints;
+mod member_constraints;
use self::facts::AllFacts;
use self::region_infer::RegionInferenceContext;
placeholder_index_to_region: _,
mut liveness_constraints,
outlives_constraints,
+ member_constraints,
closure_bounds_mapping,
type_tests,
} = constraints;
universal_region_relations,
body,
outlives_constraints,
+ member_constraints,
closure_bounds_mapping,
type_tests,
liveness_constraints,
}
}
- let mut constraints: Vec<_> = self.constraints.iter().collect();
+ let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort();
for constraint in &constraints {
let OutlivesConstraint {
use crate::borrow_check::nll::constraints::OutlivesConstraint;
+use crate::borrow_check::nll::region_infer::AppliedMemberConstraint;
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
use crate::borrow_check::nll::type_check::Locations;
use crate::borrow_check::nll::universal_regions::DefiningTy;
Trace::NotVisited => {
bug!("found unvisited region {:?} on path to {:?}", p, r)
}
+
Trace::FromOutlivesConstraint(c) => {
result.push(c);
p = c.sup;
// Otherwise, walk over the outgoing constraints and
// enqueue any regions we find, keeping track of how we
// reached them.
+
+ // A constraint like `'r: 'x` can come from our constraint
+ // graph.
let fr_static = self.universal_regions.fr_static;
- for constraint in self.constraint_graph
- .outgoing_edges(r, &self.constraints, fr_static)
- {
+ let outgoing_edges_from_graph = self.constraint_graph
+ .outgoing_edges(r, &self.constraints, fr_static);
+
+
+ // But member constraints can also give rise to `'r: 'x`
+ // edges that were not part of the graph initially, so
+ // watch out for those.
+ let outgoing_edges_from_picks = self.applied_member_constraints(r)
+ .iter()
+ .map(|&AppliedMemberConstraint { min_choice, member_constraint_index, .. }| {
+ let p_c = &self.member_constraints[member_constraint_index];
+ OutlivesConstraint {
+ sup: r,
+ sub: min_choice,
+ locations: Locations::All(p_c.definition_span),
+ category: ConstraintCategory::OpaqueType,
+ }
+ });
+
+ for constraint in outgoing_edges_from_graph.chain(outgoing_edges_from_picks) {
debug_assert_eq!(constraint.sup, r);
let sub_region = constraint.sub;
if let Trace::NotVisited = context[sub_region] {
// Finds some region R such that `fr1: R` and `R` is live at
// `elem`.
- crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
+ crate fn find_sub_region_live_at(
+ &self,
+ fr1: RegionVid,
+ elem: Location,
+ ) -> RegionVid {
debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
self.find_constraint_paths_between_regions(fr1, |r| {
// First look for some `r` such that `fr1: r` and `r` is live at `elem`
fr1: RegionVid,
fr2: RegionVid,
) -> (ConstraintCategory, Span) {
- let (category, _, span) =
- self.best_blame_constraint(body, fr1, |r| self.provides_universal_region(r, fr1, fr2));
+ let (category, _, span) = self.best_blame_constraint(
+ body,
+ fr1,
+ |r| self.provides_universal_region(r, fr1, fr2),
+ );
(category, span)
}
vids.into()
}
fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
- (&self.regioncx.constraints.raw[..]).into()
+ (&self.regioncx.constraints.outlives().raw[..]).into()
}
// Render `a: b` as `a -> b`, indicating the flow
use super::universal_regions::UniversalRegions;
use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
-use crate::borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::{
+ ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
+};
+use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
use crate::borrow_check::nll::region_infer::values::{
- PlaceholderIndices, RegionElement, ToElementIndex
+ PlaceholderIndices, RegionElement, ToElementIndex,
};
-use crate::borrow_check::Upvar;
use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
use crate::borrow_check::nll::type_check::Locations;
+use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryOutlivesConstraint;
+use rustc::infer::opaque_types;
use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
use rustc::mir::{
- ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, Body,
+ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
+ ConstraintCategory, Local, Location,
};
use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
-use rustc::util::common::{self, ErrorReported};
+use rustc::util::common::ErrorReported;
+use rustc_data_structures::binary_search_util;
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::graph::WithSuccessors;
use rustc_data_structures::graph::scc::Sccs;
+use rustc_data_structures::graph::vec_graph::VecGraph;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use syntax_pos::Span;
liveness_constraints: LivenessValues<RegionVid>,
/// The outlives constraints computed by the type-check.
- constraints: Rc<ConstraintSet>,
+ constraints: Rc<OutlivesConstraintSet>,
/// The constraint-set, but in graph form, making it easy to traverse
/// the constraints adjacent to a particular region. Used to construct
/// the SCC (see `constraint_sccs`) and for error reporting.
constraint_graph: Rc<NormalConstraintGraph>,
- /// The SCC computed from `constraints` and the constraint graph. Used to
+ /// The SCC computed from `constraints` and the constraint
+ /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
/// compute the values of each region.
constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+ /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
+ /// exists if `B: A`. Computed lazilly.
+ rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+
+ /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
+ member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+
+ /// Records the member constraints that we applied to each scc.
+ /// This is useful for error reporting. Once constraint
+ /// propagation is done, this vector is sorted according to
+ /// `member_region_scc`.
+ member_constraints_applied: Vec<AppliedMemberConstraint>,
+
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
}
+/// Each time that `apply_member_constraint` is successful, it appends
+/// one of these structs to the `member_constraints_applied` field.
+/// This is used in error reporting to trace out what happened.
+///
+/// The way that `apply_member_constraint` works is that it effectively
+/// adds a new lower bound to the SCC it is analyzing: so you wind up
+/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
+/// minimal viable option.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+struct AppliedMemberConstraint {
+ /// The SCC that was affected. (The "member region".)
+ ///
+ /// The vector if `AppliedMemberConstraint` elements is kept sorted
+ /// by this field.
+ member_region_scc: ConstraintSccIndex,
+
+ /// The "best option" that `apply_member_constraint` found -- this was
+ /// added as an "ad-hoc" lower-bound to `member_region_scc`.
+ min_choice: ty::RegionVid,
+
+ /// The "member constraint index" -- we can find out details about
+ /// the constraint from
+ /// `set.member_constraints[member_constraint_index]`.
+ member_constraint_index: NllMemberConstraintIndex,
+}
+
struct RegionDefinition<'tcx> {
/// What kind of variable is this -- a free region? existential
/// variable? etc. (See the `NLLRegionVariableOrigin` for more
placeholder_indices: Rc<PlaceholderIndices>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
_body: &Body<'tcx>,
- outlives_constraints: ConstraintSet,
+ outlives_constraints: OutlivesConstraintSet,
+ member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);
+ let member_constraints =
+ Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
+
let mut result = Self {
definitions,
liveness_constraints,
constraints,
constraint_graph,
constraint_sccs,
+ rev_constraint_graph: None,
+ member_constraints,
+ member_constraints_applied: Vec::new(),
closure_bounds_mapping,
scc_universes,
scc_representatives,
debug!(
"init_free_and_bound_regions: placeholder {:?} is \
not compatible with universe {:?} of its SCC {:?}",
- placeholder,
- scc_universe,
- scc,
+ placeholder, scc_universe, scc,
);
self.add_incompatible_universe(scc);
}
self.scc_universes[scc]
}
+ /// Once region solving has completed, this function will return
+ /// the member constraints that were applied to the value of a given
+ /// region `r`. See `AppliedMemberConstraint`.
+ fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
+ let scc = self.constraint_sccs.scc(r.to_region_vid());
+ binary_search_util::binary_search_slice(
+ &self.member_constraints_applied,
+ |applied| applied.member_region_scc,
+ &scc,
+ )
+ }
+
/// Performs region inference and report errors if we see any
/// unsatisfiable constraints. If this is a closure, returns the
/// region requirements to propagate to our creator, if any.
upvars: &[Upvar],
mir_def_id: DefId,
errors_buffer: &mut Vec<Diagnostic>,
- ) -> Option<ClosureRegionRequirements<'tcx>> {
- common::time_ext(
- infcx.tcx.sess.time_extended(),
- Some(infcx.tcx.sess),
- &format!("solve_nll_region_constraints({:?})", mir_def_id),
- || self.solve_inner(infcx, body, upvars, mir_def_id, errors_buffer),
- )
- }
-
- fn solve_inner(
- &mut self,
- infcx: &InferCtxt<'_, 'tcx>,
- body: &Body<'tcx>,
- upvars: &[Upvar],
- mir_def_id: DefId,
- errors_buffer: &mut Vec<Diagnostic>,
) -> Option<ClosureRegionRequirements<'tcx>> {
self.propagate_constraints(body);
// to store those. Otherwise, we'll pass in `None` to the
// functions below, which will trigger them to report errors
// eagerly.
- let mut outlives_requirements = if infcx.tcx.is_closure(mir_def_id) {
- Some(vec![])
- } else {
- None
- };
+ let mut outlives_requirements =
+ if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
self.check_type_tests(
infcx,
errors_buffer,
);
+ self.check_member_constraints(infcx, mir_def_id, errors_buffer);
+
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
if outlives_requirements.is_empty() {
None
} else {
let num_external_vids = self.universal_regions.num_global_and_external_regions();
- Some(ClosureRegionRequirements {
- num_external_vids,
- outlives_requirements,
- })
+ Some(ClosureRegionRequirements { num_external_vids, outlives_requirements })
}
}
debug!("propagate_constraints()");
debug!("propagate_constraints: constraints={:#?}", {
- let mut constraints: Vec<_> = self.constraints.iter().collect();
+ let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort();
constraints
.into_iter()
for scc_index in self.constraint_sccs.all_sccs() {
self.propagate_constraint_sccs_if_new(scc_index, visited);
}
+
+ // Sort the applied member constraints so we can binary search
+ // through them later.
+ self.member_constraints_applied.sort_by_key(|applied| applied.member_region_scc);
}
+ /// Computes the value of the SCC `scc_a` if it has not already
+ /// been computed. The `visited` parameter is a bitset
#[inline]
fn propagate_constraint_sccs_if_new(
&mut self,
}
}
+ /// Computes the value of the SCC `scc_a`, which has not yet been
+ /// computed. This works by first computing all successors of the
+ /// SCC (if they haven't been computed already) and then unioning
+ /// together their elements.
fn propagate_constraint_sccs_new(
&mut self,
scc_a: ConstraintSccIndex,
// Walk each SCC `B` such that `A: B`...
for &scc_b in constraint_sccs.successors(scc_a) {
- debug!(
- "propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}",
- scc_a, scc_b
- );
+ debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
// ...compute the value of `B`...
self.propagate_constraint_sccs_if_new(scc_b, visited);
}
}
+ // Now take member constraints into account.
+ let member_constraints = self.member_constraints.clone();
+ for m_c_i in member_constraints.indices(scc_a) {
+ self.apply_member_constraint(
+ scc_a,
+ m_c_i,
+ member_constraints.choice_regions(m_c_i),
+ );
+ }
+
debug!(
"propagate_constraint_sccs: scc_a = {:?} has value {:?}",
scc_a,
);
}
+ /// Invoked for each `R0 member of [R1..Rn]` constraint.
+ ///
+ /// `scc` is the SCC containing R0, and `choice_regions` are the
+ /// `R1..Rn` regions -- they are always known to be universal
+ /// regions (and if that's not true, we just don't attempt to
+ /// enforce the constraint).
+ ///
+ /// The current value of `scc` at the time the method is invoked
+ /// is considered a *lower bound*. If possible, we will modify
+ /// the constraint to set it equal to one of the option regions.
+ /// If we make any changes, returns true, else false.
+ fn apply_member_constraint(
+ &mut self,
+ scc: ConstraintSccIndex,
+ member_constraint_index: NllMemberConstraintIndex,
+ choice_regions: &[ty::RegionVid],
+ ) -> bool {
+ debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
+
+ if let Some(uh_oh) =
+ choice_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
+ {
+ // FIXME(#61773): This case can only occur with
+ // `impl_trait_in_bindings`, I believe, and we are just
+ // opting not to handle it for now. See #61773 for
+ // details.
+ bug!(
+ "member constraint for `{:?}` has an option region `{:?}` \
+ that is not a universal region",
+ self.member_constraints[member_constraint_index].opaque_type_def_id,
+ uh_oh,
+ );
+ }
+
+ // Create a mutable vector of the options. We'll try to winnow
+ // them down.
+ let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
+
+ // The 'member region' in a member constraint is part of the
+ // hidden type, which must be in the root universe. Therefore,
+ // it cannot have any placeholders in its value.
+ assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
+ debug_assert!(
+ self.scc_values.placeholders_contained_in(scc).next().is_none(),
+ "scc {:?} in a member constraint has placeholder value: {:?}",
+ scc,
+ self.scc_values.region_value_str(scc),
+ );
+
+ // The existing value for `scc` is a lower-bound. This will
+ // consist of some set `{P} + {LB}` of points `{P}` and
+ // lower-bound free regions `{LB}`. As each choice region `O`
+ // is a free region, it will outlive the points. But we can
+ // only consider the option `O` if `O: LB`.
+ choice_regions.retain(|&o_r| {
+ self.scc_values
+ .universal_regions_outlived_by(scc)
+ .all(|lb| self.universal_region_relations.outlives(o_r, lb))
+ });
+ debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions);
+
+ // Now find all the *upper bounds* -- that is, each UB is a
+ // free region that must outlive the member region `R0` (`UB:
+ // R0`). Therefore, we need only keep an option `O` if `UB: O`
+ // for all UB.
+ if choice_regions.len() > 1 {
+ let universal_region_relations = self.universal_region_relations.clone();
+ let rev_constraint_graph = self.rev_constraint_graph();
+ for ub in self.upper_bounds(scc, &rev_constraint_graph) {
+ debug!("apply_member_constraint: ub={:?}", ub);
+ choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
+ }
+ debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
+ }
+
+ // If we ruled everything out, we're done.
+ if choice_regions.is_empty() {
+ return false;
+ }
+
+ // Otherwise, we need to find the minimum remaining choice, if
+ // any, and take that.
+ debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions);
+ let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
+ let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
+ let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
+ if r1_outlives_r2 && r2_outlives_r1 {
+ Some(r1.min(r2))
+ } else if r1_outlives_r2 {
+ Some(r2)
+ } else if r2_outlives_r1 {
+ Some(r1)
+ } else {
+ None
+ }
+ };
+ let mut min_choice = choice_regions[0];
+ for &other_option in &choice_regions[1..] {
+ debug!(
+ "apply_member_constraint: min_choice={:?} other_option={:?}",
+ min_choice, other_option,
+ );
+ match min(min_choice, other_option) {
+ Some(m) => min_choice = m,
+ None => {
+ debug!(
+ "apply_member_constraint: {:?} and {:?} are incomparable; no min choice",
+ min_choice, other_option,
+ );
+ return false;
+ }
+ }
+ }
+
+ let min_choice_scc = self.constraint_sccs.scc(min_choice);
+ debug!(
+ "apply_member_constraint: min_choice={:?} best_choice_scc={:?}",
+ min_choice,
+ min_choice_scc,
+ );
+ if self.scc_values.add_region(scc, min_choice_scc) {
+ self.member_constraints_applied.push(AppliedMemberConstraint {
+ member_region_scc: scc,
+ min_choice,
+ member_constraint_index,
+ });
+
+ true
+ } else {
+ false
+ }
+ }
+
+ /// Compute and return the reverse SCC-based constraint graph (lazilly).
+ fn upper_bounds(
+ &'a mut self,
+ scc0: ConstraintSccIndex,
+ rev_constraint_graph: &'a VecGraph<ConstraintSccIndex>,
+ ) -> impl Iterator<Item = RegionVid> + 'a {
+ let scc_values = &self.scc_values;
+ let mut duplicates = FxHashSet::default();
+ rev_constraint_graph
+ .depth_first_search(scc0)
+ .skip(1)
+ .flat_map(move |scc1| scc_values.universal_regions_outlived_by(scc1))
+ .filter(move |&r| duplicates.insert(r))
+ }
+
+ /// Compute and return the reverse SCC-based constraint graph (lazilly).
+ fn rev_constraint_graph(
+ &mut self,
+ ) -> Rc<VecGraph<ConstraintSccIndex>> {
+ if let Some(g) = &self.rev_constraint_graph {
+ return g.clone();
+ }
+
+ let rev_graph = Rc::new(self.constraint_sccs.reverse());
+ self.rev_constraint_graph = Some(rev_graph.clone());
+ rev_graph
+ }
+
/// Returns `true` if all the elements in the value of `scc_b` are nameable
/// in `scc_a`. Used during constraint propagation, and only once
/// the value of `scc_b` has been computed.
// Otherwise, we have to iterate over the universe elements in
// B's value, and check whether all of them are nameable
// from universe_a
- self.scc_values
- .placeholders_contained_in(scc_b)
- .all(|p| universe_a.can_name(p.universe))
+ self.scc_values.placeholders_contained_in(scc_b).all(|p| universe_a.can_name(p.universe))
}
/// Extend `scc` so that it can outlive some placeholder region
) -> bool {
let tcx = infcx.tcx;
- let TypeTest {
- generic_kind,
- lower_bound,
- locations,
- verify_bound: _,
- } = type_test;
+ let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
let generic_ty = generic_kind.to_ty(tcx);
let subject = match self.try_promote_type_test_subject(infcx, generic_ty) {
ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx;
- let gcx = tcx.global_tcx();
debug!("try_promote_type_test_subject(ty = {:?})", ty);
});
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
- // `lift_to_global` will only fail if we failed to promote some region.
- gcx.lift_to_global(&ty)?;
+ // `has_local_value` will only be true if we failed to promote some region.
+ if ty.has_local_value() {
+ return None;
+ }
Some(ClosureOutlivesSubject::Ty(ty))
}
/// except that it converts further takes the non-local upper
/// bound of `'y`, so that the final result is non-local.
fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
- debug!(
- "non_local_universal_upper_bound(r={:?}={})",
- r,
- self.region_value_str(r)
- );
+ debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
let lub = self.universal_upper_bound(r);
// creator.
let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
- debug!(
- "non_local_universal_upper_bound: non_local_lub={:?}",
- non_local_lub
- );
+ debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
non_local_lub
}
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
/// a result `'y`.
fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
- debug!(
- "universal_upper_bound(r={:?}={})",
- r,
- self.region_value_str(r)
- );
+ debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
// Find the smallest universal region that contains all other
// universal regions within `region`.
lower_bound: RegionVid,
verify_bound: &VerifyBound<'tcx>,
) -> bool {
- debug!(
- "eval_verify_bound(lower_bound={:?}, verify_bound={:?})",
- lower_bound, verify_bound
- );
+ debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound);
match verify_bound {
VerifyBound::IfEq(test_ty, verify_bound1) => {
VerifyBound::OutlivedBy(r) => {
let r_vid = self.to_region_vid(r);
- self.eval_outlives(body, r_vid, lower_bound)
+ self.eval_outlives(r_vid, lower_bound)
}
VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
})
}
- // Evaluate whether `sup_region: sub_region @ point`.
- fn eval_outlives(
- &self,
- _body: &Body<'tcx>,
- sup_region: RegionVid,
- sub_region: RegionVid,
- ) -> bool {
+ // Evaluate whether `sup_region == sub_region`.
+ fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
+ self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1)
+ }
+
+ // Evaluate whether `sup_region: sub_region`.
+ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
debug!("eval_outlives({:?}: {:?})", sup_region, sub_region);
debug!(
- "eval_outlives: sup_region's value = {:?}",
+ "eval_outlives: sup_region's value = {:?} universal={:?}",
self.region_value_str(sup_region),
+ self.universal_regions.is_universal_region(sup_region),
);
debug!(
- "eval_outlives: sub_region's value = {:?}",
+ "eval_outlives: sub_region's value = {:?} universal={:?}",
self.region_value_str(sub_region),
+ self.universal_regions.is_universal_region(sub_region),
);
let sub_region_scc = self.constraint_sccs.scc(sub_region);
// now). Therefore, the sup-region outlives the sub-region if,
// for each universal region R1 in the sub-region, there
// exists some region R2 in the sup-region that outlives R1.
- let universal_outlives = self.scc_values
- .universal_regions_outlived_by(sub_region_scc)
- .all(|r1| {
+ let universal_outlives =
+ self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| {
self.scc_values
.universal_regions_outlived_by(sup_region_scc)
.any(|r2| self.universal_region_relations.outlives(r2, r1))
return true;
}
- self.scc_values
- .contains_points(sup_region_scc, sub_region_scc)
+ self.scc_values.contains_points(sup_region_scc, sub_region_scc)
}
/// Once regions have been propagated, this method is used to see
// Because this free region must be in the ROOT universe, we
// know it cannot contain any bound universes.
assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
- debug_assert!(
- self.scc_values
- .placeholders_contained_in(longer_fr_scc)
- .next()
- .is_none()
- );
+ debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
// Only check all of the relations for the main representative of each
// SCC, otherwise just check that we outlive said representative. This
errors_buffer: &mut Vec<Diagnostic>,
) -> Option<ErrorReported> {
// If it is known that `fr: o`, carry on.
- if self.universal_region_relations
- .outlives(longer_fr, shorter_fr)
- {
+ if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
return None;
}
// We'll call it `fr-` -- it's ever so slightly smaller than
// `longer_fr`.
- if let Some(fr_minus) = self
- .universal_region_relations
- .non_local_lower_bound(longer_fr)
+ if let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
{
debug!("check_universal_region: fr_minus={:?}", fr_minus);
// Grow `shorter_fr` until we find some non-local regions. (We
// always will.) We'll call them `shorter_fr+` -- they're ever
// so slightly larger than `shorter_fr`.
- let shorter_fr_plus = self.universal_region_relations
- .non_local_upper_bounds(&shorter_fr);
- debug!(
- "check_universal_region: shorter_fr_plus={:?}",
- shorter_fr_plus
- );
+ let shorter_fr_plus =
+ self.universal_region_relations.non_local_upper_bounds(&shorter_fr);
+ debug!("check_universal_region: shorter_fr_plus={:?}", shorter_fr_plus);
for &&fr in &shorter_fr_plus {
// Push the constraint `fr-: shorter_fr+`
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
longer_fr: RegionVid,
placeholder: ty::PlaceholderRegion,
) {
- debug!(
- "check_bound_universal_region(fr={:?}, placeholder={:?})",
- longer_fr, placeholder,
- );
+ debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,);
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
- debug!(
- "check_bound_universal_region: longer_fr_scc={:?}",
- longer_fr_scc,
- );
+ debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
// If we have some bound universal region `'a`, then the only
// elements it can contain is itself -- we don't know anything
// else about it!
let error_element = match {
- self.scc_values
- .elements_contained_in(longer_fr_scc)
- .find(|element| match element {
- RegionElement::Location(_) => true,
- RegionElement::RootUniversalRegion(_) => true,
- RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
- })
+ self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
+ RegionElement::Location(_) => true,
+ RegionElement::RootUniversalRegion(_) => true,
+ RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
+ })
} {
Some(v) => v,
None => return,
let error_region = match error_element {
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
RegionElement::RootUniversalRegion(r) => r,
- RegionElement::PlaceholderRegion(error_placeholder) => self.definitions
+ RegionElement::PlaceholderRegion(error_placeholder) => self
+ .definitions
.iter_enumerated()
.filter_map(|(r, definition)| match definition.origin {
NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
// the AST-based checker uses a more conservative check,
// so to even see this error, one must pass in a special
// flag.
- let mut diag = infcx
- .tcx
- .sess
- .struct_span_err(span, "higher-ranked subtype error");
+ let mut diag = infcx.tcx.sess.struct_span_err(span, "higher-ranked subtype error");
diag.emit();
}
+
+ fn check_member_constraints(
+ &self,
+ infcx: &InferCtxt<'_, 'tcx>,
+ mir_def_id: DefId,
+ errors_buffer: &mut Vec<Diagnostic>,
+ ) {
+ let member_constraints = self.member_constraints.clone();
+ for m_c_i in member_constraints.all_indices() {
+ debug!("check_member_constraint(m_c_i={:?})", m_c_i);
+ let m_c = &member_constraints[m_c_i];
+ let member_region_vid = m_c.member_region_vid;
+ debug!(
+ "check_member_constraint: member_region_vid={:?} with value {}",
+ member_region_vid,
+ self.region_value_str(member_region_vid),
+ );
+ let choice_regions = member_constraints.choice_regions(m_c_i);
+ debug!("check_member_constraint: choice_regions={:?}", choice_regions);
+
+ // Did the member region wind up equal to any of the option regions?
+ if let Some(o) = choice_regions.iter().find(|&&o_r| {
+ self.eval_equal(o_r, m_c.member_region_vid)
+ }) {
+ debug!("check_member_constraint: evaluated as equal to {:?}", o);
+ continue;
+ }
+
+ // If not, report an error.
+ let region_scope_tree = &infcx.tcx.region_scope_tree(mir_def_id);
+ let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
+ opaque_types::unexpected_hidden_region_diagnostic(
+ infcx.tcx,
+ Some(region_scope_tree),
+ m_c.opaque_type_def_id,
+ m_c.hidden_ty,
+ member_region,
+ )
+ .buffer(errors_buffer);
+ }
+ }
}
impl<'tcx> RegionDefinition<'tcx> {
_ => NLLRegionVariableOrigin::Existential,
};
- Self {
- origin,
- universe,
- external_name: None,
- }
+ Self { origin, universe, external_name: None }
}
}
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
- ) -> Vec<QueryRegionConstraint<'tcx>>;
+ ) -> Vec<QueryOutlivesConstraint<'tcx>>;
fn subst_closure_mapping<T>(
&self,
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
- ) -> Vec<QueryRegionConstraint<'tcx>> {
+ ) -> Vec<QueryOutlivesConstraint<'tcx>> {
debug!(
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
closure_def_id, closure_substs
if let ty::ReClosureBound(vid) = r {
closure_mapping[*vid]
} else {
- bug!(
- "subst_closure_mapping: encountered non-closure bound free region {:?}",
- r
- )
+ bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r)
}
})
}
}
/// Iterate through each region that has a value in this set.
- crate fn rows<'a>(&'a self) -> impl Iterator<Item = N> {
+ crate fn rows(&self) -> impl Iterator<Item=N> {
self.points.rows()
}
use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
use crate::borrow_check::nll::universal_regions::UniversalRegions;
use crate::borrow_check::nll::ToRegionVid;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
+use rustc::infer::canonical::QueryOutlivesConstraint;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
}
}
- pub(super) fn convert_all(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
- for query_constraint in query_constraints {
+ pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
+ debug!("convert_all(query_constraints={:#?})", query_constraints);
+
+ let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
+
+ // Annoying: to invoke `self.to_region_vid`, we need access to
+ // `self.constraints`, but we also want to be mutating
+ // `self.member_constraints`. For now, just swap out the value
+ // we want and replace at the end.
+ let mut tmp = std::mem::replace(
+ &mut self.constraints.member_constraints,
+ Default::default(),
+ );
+ for member_constraint in member_constraints {
+ tmp.push_constraint(
+ member_constraint,
+ |r| self.to_region_vid(r),
+ );
+ }
+ self.constraints.member_constraints = tmp;
+
+ for query_constraint in outlives {
self.convert(query_constraint);
}
}
- pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>) {
+ pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
debug!("generate: constraints at: {:#?}", self.locations);
// Extract out various useful fields we'll need below.
use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
use crate::borrow_check::nll::universal_regions::UniversalRegions;
use crate::borrow_check::nll::ToRegionVid;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
use rustc::infer::outlives::free_region_map::FreeRegionRelations;
use rustc::infer::region_constraints::GenericKind;
use rustc::infer::InferCtxt;
self.relations.relate_universal_regions(fr, fr_fn_body);
}
- for data in constraint_sets {
+ for data in &constraint_sets {
constraint_conversion::ConstraintConversion::new(
self.infcx,
&self.universal_regions,
Locations::All(DUMMY_SP),
ConstraintCategory::Internal,
&mut self.constraints,
- ).convert_all(&data);
+ ).convert_all(data);
}
CreateResult {
/// either the return type of the MIR or one of its arguments. At
/// the same time, compute and add any implied bounds that come
/// from this local.
- fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<Vec<QueryRegionConstraint<'tcx>>>> {
+ fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<QueryRegionConstraints<'tcx>>> {
debug!("add_implied_bounds(ty={:?})", ty);
let (bounds, constraints) =
self.param_env
use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::ConstraintSet;
+use crate::borrow_check::nll::constraints::OutlivesConstraintSet;
use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::borrow_check::nll::universal_regions::UniversalRegions;
fn regions_that_outlive_free_regions(
num_region_vars: usize,
universal_regions: &UniversalRegions<'tcx>,
- constraint_set: &ConstraintSet,
+ constraint_set: &OutlivesConstraintSet,
) -> FxHashSet<RegionVid> {
// Build a graph of the outlives constraints thus far. This is
// a reverse graph, so for each constraint `R1: R2` we have an
use crate::dataflow::indexes::MovePathIndex;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Body};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc::traits::query::type_op::outlives::DropckOutlives;
struct DropData<'tcx> {
dropck_result: DropckOutlivesResult<'tcx>,
- region_constraint_data: Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>,
+ region_constraint_data: Option<Rc<QueryRegionConstraints<'tcx>>>,
}
struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
use crate::borrow_check::borrow_set::BorrowSet;
use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::member_constraints::MemberConstraintSet;
use crate::borrow_check::nll::facts::AllFacts;
use crate::borrow_check::nll::region_infer::values::LivenessValues;
use crate::borrow_check::nll::region_infer::values::PlaceholderIndex;
use either::Either;
use rustc::hir;
use rustc::hir::def_id::DefId;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
liveness_constraints: LivenessValues::new(elements.clone()),
- outlives_constraints: ConstraintSet::default(),
+ outlives_constraints: OutlivesConstraintSet::default(),
+ member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
};
let location_table = cx.location_table;
facts
.outlives
- .extend(cx.constraints.outlives_constraints.iter().flat_map(
+ .extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
|constraint: &OutlivesConstraint| {
if let Some(from_location) = constraint.locations.from_location() {
Either::Left(iter::once((
);
let locations = location.to_locations();
- for constraint in constraints.iter() {
+ for constraint in constraints.outlives().iter() {
let mut constraint = *constraint;
constraint.locations = locations;
if let ConstraintCategory::Return
infcx: &'a InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
last_span: Span,
+ body: &'a Body<'tcx>,
/// User type annotations are shared between the main MIR and the MIR of
/// all of the promoted items.
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
/// hence it must report on their liveness constraints.
crate liveness_constraints: LivenessValues<RegionVid>,
- crate outlives_constraints: ConstraintSet,
+ crate outlives_constraints: OutlivesConstraintSet,
+
+ crate member_constraints: MemberConstraintSet<'tcx, RegionVid>,
crate closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
infcx,
last_span: DUMMY_SP,
mir_def_id,
+ body,
user_type_annotations: &body.user_type_annotations,
param_env,
region_bound_pairs,
&mut self,
locations: Locations,
category: ConstraintCategory,
- data: &[QueryRegionConstraint<'tcx>],
+ data: &QueryRegionConstraints<'tcx>,
) {
debug!(
"push_region_constraints: constraints generated at {:?} are {:#?}",
locations,
category,
&mut self.borrowck_context.constraints,
- ).convert_all(&data);
+ ).convert_all(data);
}
/// Convenient wrapper around `relate_tys::relate_types` -- see
let infcx = self.infcx;
let tcx = infcx.tcx;
let param_env = self.param_env;
+ let body = self.body;
debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
let opaque_type_map = self.fully_perform_op(
locations,
dummy_body_id,
param_env,
&anon_ty,
+ locations.span(body),
));
debug!(
"eq_opaque_type_and_type: \
location: Location,
) -> ty::InstantiatedPredicates<'tcx> {
if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
- let closure_constraints =
- closure_region_requirements.apply_requirements(tcx, def_id, substs);
+ let closure_constraints = QueryRegionConstraints {
+ outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs),
+
+ // Presently, closures never propagate member
+ // constraints to their parents -- they are enforced
+ // locally. This is largely a non-issue as member
+ // constraints only come from `-> impl Trait` and
+ // friends which don't appear (thus far...) in
+ // closures.
+ member_constraints: vec![],
+ };
let bounds_mapping = closure_constraints
+ .outlives
.iter()
.enumerate()
.filter_map(|(idx, constraint)| {
local_id: *late_bound,
};
let name = tcx.hir().name(hir_id).as_interned_str();
- let region_def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let region_def_id = tcx.hir().local_def_id(hir_id);
let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
scope: fn_def_id,
bound_region: ty::BoundRegion::BrNamed(region_def_id, name),
/// Determines if a given borrow is borrowing local data
/// This is called for all Yield statements on movable generators
-pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
+pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
place.iterate(|place_base, place_projection| {
match place_base {
PlaceBase::Static(..) => return false,
/// Determines the category for a given expression. Note that scope
/// and paren expressions have no category.
impl Category {
- pub fn of<'tcx>(ek: &ExprKind<'tcx>) -> Option<Category> {
+ pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
match *ek {
ExprKind::Scope { .. } => None,
};
// Step 5. Create everything else: the guards and the arms.
+ let match_scope = self.scopes.topmost();
+
let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| {
let arm_source_info = self.source_info(arm.span);
- let region_scope = (arm.scope, arm_source_info);
- self.in_scope(region_scope, arm.lint_level, |this| {
+ let arm_scope = (arm.scope, arm_source_info);
+ self.in_scope(arm_scope, arm.lint_level, |this| {
let body = this.hir.mirror(arm.body.clone());
let scope = this.declare_bindings(
None,
arm.guard.clone(),
&fake_borrow_temps,
scrutinee_span,
- region_scope,
+ match_scope,
);
} else {
arm_block = this.cfg.start_new_block();
arm.guard.clone(),
&fake_borrow_temps,
scrutinee_span,
- region_scope,
+ match_scope,
);
this.cfg.terminate(
binding_end,
guard: Option<Guard<'tcx>>,
fake_borrows: &Vec<(&Place<'tcx>, Local)>,
scrutinee_span: Span,
- region_scope: (region::Scope, SourceInfo),
+ region_scope: region::Scope,
) -> BasicBlock {
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
candidate: &mut Candidate<'pat, 'tcx>) {
// repeatedly simplify match pairs until fixed point is reached
loop {
- let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
+ let match_pairs = mem::take(&mut candidate.match_pairs);
let mut changed = false;
for match_pair in match_pairs {
match self.simplify_match_pair(match_pair, candidate) {
}
}
-fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool {
+fn is_switch_ty(ty: Ty<'_>) -> bool {
ty.is_integral() || ty.is_char() || ty.is_bool()
}
use super::lints;
/// Construct the MIR for a given `DefId`.
-pub fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Body<'tcx> {
+pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
// Figure out what primary body this item has.
// fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced)
let fn_sig = cx.tables().liberated_fn_sigs()[id].clone();
- let fn_def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let fn_def_id = tcx.hir().local_def_id(id);
let ty = tcx.type_of(fn_def_id);
let mut abi = fn_sig.abi;
///////////////////////////////////////////////////////////////////////////
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
-fn liberated_closure_env_ty<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn liberated_closure_env_ty(
+ tcx: TyCtxt<'_>,
closure_expr_id: hir::HirId,
body_id: hir::BodyId,
-) -> Ty<'tcx> {
+) -> Ty<'_> {
let closure_ty = tcx.body_tables(body_id).node_type(closure_expr_id);
let (closure_def_id, closure_substs) = match closure_ty.sty {
};
}
-fn should_abort_on_panic<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, abi: Abi) -> bool {
+fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool {
// Not callable from C, so we can safely unwind through these
if abi == Abi::Rust || abi == Abi::RustCall { return false; }
let span = tcx_hir.span(fn_id);
let hir_tables = hir.tables();
- let fn_def_id = tcx_hir.local_def_id_from_hir_id(fn_id);
+ let fn_def_id = tcx_hir.local_def_id(fn_id);
// Gather the upvars of a closure, if any.
let mut upvar_mutbls = vec![];
}
let arg_scope_s = (arg_scope, source_info);
- unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
- builder.args_and_body(block, &arguments, arg_scope, &body.value)
- }));
+ // `return_block` is called when we evaluate a `return` expression, so
+ // we just use `START_BLOCK` here.
+ unpack!(block = builder.in_breakable_scope(
+ None,
+ START_BLOCK,
+ Place::RETURN_PLACE,
+ |builder| {
+ builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
+ builder.args_and_body(block, &arguments, arg_scope, &body.value)
+ })
+ },
+ ));
// Attribute epilogue to function's closing brace
let fn_end = span.shrink_to_hi();
let source_info = builder.source_info(fn_end);
}
let body = self.hir.mirror(ast_body);
- // `return_block` is called when we evaluate a `return` expression, so
- // we just use `START_BLOCK` here.
- self.in_breakable_scope(None, START_BLOCK, Place::RETURN_PLACE, |this| {
- this.into(&Place::RETURN_PLACE, block, body)
- })
+ self.into(&Place::RETURN_PLACE, block, body)
}
fn get_unit_temp(&mut self) -> Place<'tcx> {
}
}
- fn num_scopes_to(&self, region_scope: (region::Scope, SourceInfo), span: Span) -> usize {
- let scope_count = 1 + self.scopes.iter().rev()
- .position(|scope| scope.region_scope == region_scope.0)
+ fn num_scopes_above(&self, region_scope: region::Scope, span: Span) -> usize {
+ let scope_count = self.scopes.iter().rev()
+ .position(|scope| scope.region_scope == region_scope)
.unwrap_or_else(|| {
span_bug!(span, "region_scope {:?} does not enclose", region_scope)
});
/// Returns the topmost active scope, which is known to be alive until
/// the next scope expression.
- fn topmost(&self) -> region::Scope {
+ pub(super) fn topmost(&self) -> region::Scope {
self.scopes.last().expect("topmost_scope: no scopes present").region_scope
}
} else {
assert!(value.is_none(), "`return` and `break` should have a destination");
}
- self.exit_scope(source_info.span, (region_scope, source_info), block, target_block);
+ self.exit_scope(source_info.span, region_scope, block, target_block);
self.cfg.start_new_block().unit()
}
/// needed. See module comment for details.
pub fn exit_scope(&mut self,
span: Span,
- region_scope: (region::Scope, SourceInfo),
+ region_scope: region::Scope,
mut block: BasicBlock,
target: BasicBlock) {
debug!("exit_scope(region_scope={:?}, block={:?}, target={:?})",
region_scope, block, target);
- let scope_count = self.scopes.num_scopes_to(region_scope, span);
+ let scope_count = self.scopes.num_scopes_above(region_scope, span);
// If we are emitting a `drop` statement, we need to have the cached
// diverge cleanup pads ready in case that drop panics.
continue;
}
let source_info = scope.source_info(span);
- block = match scope.cached_exits.entry((target, region_scope.0)) {
+ block = match scope.cached_exits.entry((target, region_scope)) {
Entry::Occupied(e) => {
self.cfg.terminate(block, source_info,
TerminatorKind::Goto { target: *e.get() });
use crate::interpret::{self,
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar,
RawConst, ConstValue,
- InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpretCx, StackPopCleanup,
+ InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpCx, StackPopCleanup,
Allocation, AllocId, MemoryKind, Memory,
snapshot, RefTracking, intern_const_alloc_recursive,
};
/// Should be a power of two for performance reasons.
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
-/// The `InterpretCx` is only meant to be used to do field and index projections into constants for
+/// The `InterpCx` is only meant to be used to do field and index projections into constants for
/// `simd_shuffle` and const patterns in match arms.
///
/// The function containing the `match` that is currently being analyzed may have generic bounds
param_env: ty::ParamEnv<'tcx>,
) -> CompileTimeEvalContext<'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
- InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
+ InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default())
}
pub(crate) fn eval_promoted<'mir, 'tcx>(
}
crate type CompileTimeEvalContext<'mir, 'tcx> =
- InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
+ InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
impl interpret::MayLeak for ! {
#[inline(always)]
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
type MemoryKinds = !;
type PointerTag = ();
+ type ExtraFnVal = !;
type FrameExtra = ();
type MemoryExtra = ();
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
#[inline(always)]
- fn enforce_validity(_ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool {
+ fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
false // for now, we don't enforce validity
}
fn find_fn(
- ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: Option<PlaceTy<'tcx>>,
}))
}
+ fn call_extra_fn(
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ fn_val: !,
+ _args: &[OpTy<'tcx>],
+ _dest: Option<PlaceTy<'tcx>>,
+ _ret: Option<mir::BasicBlock>,
+ ) -> InterpResult<'tcx> {
+ match fn_val {}
+ }
+
fn call_intrinsic(
- ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: PlaceTy<'tcx>,
}
fn ptr_op(
- _ecx: &InterpretCx<'mir, 'tcx, Self>,
+ _ecx: &InterpCx<'mir, 'tcx, Self>,
_bin_op: mir::BinOp,
_left: ImmTy<'tcx>,
_right: ImmTy<'tcx>,
}
fn box_alloc(
- _ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>,
) -> InterpResult<'tcx> {
Err(
)
}
- fn before_terminator(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+ fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
{
let steps = &mut ecx.machine.steps_since_detector_enabled;
}
#[inline(always)]
- fn stack_push(_ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+ fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}
/// Called immediately before a stack frame gets popped.
#[inline(always)]
- fn stack_pop(_ecx: &mut InterpretCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
+ fn stack_pop(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
Ok(())
}
}
}
pub fn error_to_const_error<'mir, 'tcx>(
- ecx: &InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+ ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
mut error: InterpErrorInfo<'tcx>,
) -> ConstEvalErr<'tcx> {
error.print_backtrace();
}
let span = tcx.def_span(cid.instance.def_id());
- let mut ecx = InterpretCx::new(tcx.at(span), key.param_env, CompileTimeInterpreter::new());
+ let mut ecx = InterpCx::new(
+ tcx.at(span),
+ key.param_env,
+ CompileTimeInterpreter::new(),
+ Default::default()
+ );
let res = ecx.load_mir(cid.instance.def);
res.map(|body| {
use crate::dataflow::move_paths::{HasMoveData, MovePathIndex};
use std::iter;
+use std::borrow::Borrow;
/// A trait for "cartesian products" of multiple FlowAtLocation.
///
/// (e.g., via `reconstruct_statement_effect` and
/// `reconstruct_terminator_effect`; don't forget to call
/// `apply_local_effect`).
-pub struct FlowAtLocation<'tcx, BD>
+pub struct FlowAtLocation<'tcx, BD, DR = DataflowResults<'tcx, BD>>
where
BD: BitDenotation<'tcx>,
+ DR: Borrow<DataflowResults<'tcx, BD>>,
{
- base_results: DataflowResults<'tcx, BD>,
+ base_results: DR,
curr_state: BitSet<BD::Idx>,
stmt_trans: GenKillSet<BD::Idx>,
}
-impl<'tcx, BD> FlowAtLocation<'tcx, BD>
+impl<'tcx, BD, DR> FlowAtLocation<'tcx, BD, DR>
where
BD: BitDenotation<'tcx>,
+ DR: Borrow<DataflowResults<'tcx, BD>>,
{
/// Iterate over each bit set in the current state.
pub fn each_state_bit<F>(&self, f: F)
self.stmt_trans.gen_set.iter().for_each(f)
}
- pub fn new(results: DataflowResults<'tcx, BD>) -> Self {
- let bits_per_block = results.sets().bits_per_block();
+ pub fn new(results: DR) -> Self {
+ let bits_per_block = results.borrow().sets().bits_per_block();
let curr_state = BitSet::new_empty(bits_per_block);
let stmt_trans = GenKillSet::from_elem(HybridBitSet::new_empty(bits_per_block));
FlowAtLocation {
/// Access the underlying operator.
pub fn operator(&self) -> &BD {
- self.base_results.operator()
+ self.base_results.borrow().operator()
}
pub fn contains(&self, x: BD::Idx) -> bool {
}
}
-impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD>
- where BD: BitDenotation<'tcx>
+impl<'tcx, BD, DR> FlowsAtLocation for FlowAtLocation<'tcx, BD, DR>
+where
+ BD: BitDenotation<'tcx>,
+ DR: Borrow<DataflowResults<'tcx, BD>>,
{
fn reset_to_entry_of(&mut self, bb: BasicBlock) {
- self.curr_state.overwrite(self.base_results.sets().entry_set_for(bb.index()));
+ self.curr_state.overwrite(self.base_results.borrow().sets().entry_set_for(bb.index()));
}
fn reset_to_exit_of(&mut self, bb: BasicBlock) {
self.reset_to_entry_of(bb);
- let trans = self.base_results.sets().trans_for(bb.index());
+ let trans = self.base_results.borrow().sets().trans_for(bb.index());
trans.apply(&mut self.curr_state)
}
fn reconstruct_statement_effect(&mut self, loc: Location) {
self.stmt_trans.clear();
self.base_results
+ .borrow()
.operator()
.before_statement_effect(&mut self.stmt_trans, loc);
self.stmt_trans.apply(&mut self.curr_state);
self.base_results
+ .borrow()
.operator()
.statement_effect(&mut self.stmt_trans, loc);
}
fn reconstruct_terminator_effect(&mut self, loc: Location) {
self.stmt_trans.clear();
self.base_results
+ .borrow()
.operator()
.before_terminator_effect(&mut self.stmt_trans, loc);
self.stmt_trans.apply(&mut self.curr_state);
self.base_results
+ .borrow()
.operator()
.terminator_effect(&mut self.stmt_trans, loc);
}
}
-impl<'tcx, T> FlowAtLocation<'tcx, T>
+impl<'tcx, T, DR> FlowAtLocation<'tcx, T, DR>
where
T: HasMoveData<'tcx> + BitDenotation<'tcx, Idx = MovePathIndex>,
+ DR: Borrow<DataflowResults<'tcx, T>>,
{
pub fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
// We process `mpi` before the loop below, for two reasons:
trans: &'gk mut GenKillSet<Local>,
}
-fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
+fn find_local(place: &Place<'_>) -> Option<Local> {
place.iterate(|place_base, place_projection| {
for proj in place_projection {
if proj.elem == ProjectionElem::Deref {
pub use super::*;
use rustc::mir::*;
+use rustc::mir::visit::{
+ PlaceContext, Visitor, NonMutatingUseContext,
+};
+use std::cell::RefCell;
use crate::dataflow::BitDenotation;
+use crate::dataflow::HaveBeenBorrowedLocals;
+use crate::dataflow::{DataflowResults, DataflowResultsCursor, DataflowResultsRefCursor};
#[derive(Copy, Clone)]
pub struct MaybeStorageLive<'a, 'tcx> {
}
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
- // Nothing is live on function entry
+ // Nothing is live on function entry (generators only have a self
+ // argument, and we don't care about that)
+ assert_eq!(1, self.body.arg_count);
}
fn statement_effect(&self,
/// bottom = dead
const BOTTOM_VALUE: bool = false;
}
+
+/// Dataflow analysis that determines whether each local requires storage at a
+/// given location; i.e. whether its storage can go away without being observed.
+pub struct RequiresStorage<'mir, 'tcx> {
+ body: &'mir Body<'tcx>,
+ borrowed_locals:
+ RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
+}
+
+impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
+ pub fn new(
+ body: &'mir Body<'tcx>,
+ borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
+ ) -> Self {
+ RequiresStorage {
+ body,
+ borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body)),
+ }
+ }
+
+ pub fn body(&self) -> &Body<'tcx> {
+ self.body
+ }
+}
+
+impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
+ type Idx = Local;
+ fn name() -> &'static str { "requires_storage" }
+ fn bits_per_block(&self) -> usize {
+ self.body.local_decls.len()
+ }
+
+ fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
+ // Nothing is live on function entry (generators only have a self
+ // argument, and we don't care about that)
+ assert_eq!(1, self.body.arg_count);
+ }
+
+ fn statement_effect(&self,
+ sets: &mut GenKillSet<Local>,
+ loc: Location) {
+ self.check_for_move(sets, loc);
+ self.check_for_borrow(sets, loc);
+
+ let stmt = &self.body[loc.block].statements[loc.statement_index];
+ match stmt.kind {
+ StatementKind::StorageLive(l) => sets.gen(l),
+ StatementKind::StorageDead(l) => sets.kill(l),
+ StatementKind::Assign(ref place, _)
+ | StatementKind::SetDiscriminant { ref place, .. } => {
+ place.base_local().map(|l| sets.gen(l));
+ }
+ StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
+ for p in &**outputs {
+ p.base_local().map(|l| sets.gen(l));
+ }
+ }
+ _ => (),
+ }
+ }
+
+ fn terminator_effect(&self,
+ sets: &mut GenKillSet<Local>,
+ loc: Location) {
+ self.check_for_move(sets, loc);
+ self.check_for_borrow(sets, loc);
+ }
+
+ fn propagate_call_return(
+ &self,
+ in_out: &mut BitSet<Local>,
+ _call_bb: mir::BasicBlock,
+ _dest_bb: mir::BasicBlock,
+ dest_place: &mir::Place<'tcx>,
+ ) {
+ dest_place.base_local().map(|l| in_out.insert(l));
+ }
+}
+
+impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
+ /// Kill locals that are fully moved and have not been borrowed.
+ fn check_for_move(&self, sets: &mut GenKillSet<Local>, loc: Location) {
+ let mut visitor = MoveVisitor {
+ sets,
+ borrowed_locals: &self.borrowed_locals,
+ };
+ visitor.visit_location(self.body, loc);
+ }
+
+ /// Gen locals that are newly borrowed. This includes borrowing any part of
+ /// a local (we rely on this behavior of `HaveBeenBorrowedLocals`).
+ fn check_for_borrow(&self, sets: &mut GenKillSet<Local>, loc: Location) {
+ let mut borrowed_locals = self.borrowed_locals.borrow_mut();
+ borrowed_locals.seek(loc);
+ borrowed_locals.each_gen_bit(|l| sets.gen(l));
+ }
+}
+
+impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
+ /// bottom = dead
+ const BOTTOM_VALUE: bool = false;
+}
+
+struct MoveVisitor<'a, 'mir, 'tcx> {
+ borrowed_locals:
+ &'a RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
+ sets: &'a mut GenKillSet<Local>,
+}
+
+impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
+ fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
+ if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
+ let mut borrowed_locals = self.borrowed_locals.borrow_mut();
+ borrowed_locals.seek(loc);
+ if !borrowed_locals.contains(*local) {
+ self.sets.kill(*local);
+ }
+ }
+ }
+}
use std::path::PathBuf;
use std::usize;
-pub use self::impls::{MaybeStorageLive};
+pub use self::impls::{MaybeStorageLive, RequiresStorage};
pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
pub use self::impls::DefinitelyInitializedPlaces;
pub use self::impls::EverInitializedPlaces;
BD: BitDenotation<'tcx>,
{
fn walk_cfg(&mut self, in_out: &mut BitSet<BD::Idx>) {
- let mut dirty_queue: WorkQueue<mir::BasicBlock> =
- WorkQueue::with_all(self.builder.body.basic_blocks().len());
let body = self.builder.body;
+
+ // Initialize the dirty queue in reverse post-order. This makes it more likely that the
+ // entry state for each basic block will have the effects of its predecessors applied
+ // before it is processed. In fact, for CFGs without back edges, this guarantees that
+ // dataflow will converge in exactly `N` iterations, where `N` is the number of basic
+ // blocks.
+ let mut dirty_queue: WorkQueue<mir::BasicBlock> =
+ WorkQueue::with_none(body.basic_blocks().len());
+ for (bb, _) in traversal::reverse_postorder(body) {
+ dirty_queue.insert(bb);
+ }
+
+ // Add blocks which are not reachable from START_BLOCK to the work queue. These blocks will
+ // be processed after the ones added above.
+ for bb in body.basic_blocks().indices() {
+ dirty_queue.insert(bb);
+ }
+
while let Some(bb) = dirty_queue.pop() {
let (on_entry, trans) = self.builder.flow_state.sets.get_mut(bb.index());
debug_assert!(in_out.words().len() == on_entry.words().len());
fn body(&self) -> &'a Body<'tcx>;
}
+/// Allows iterating dataflow results in a flexible and reasonably fast way.
+pub struct DataflowResultsCursor<'mir, 'tcx, BD, DR = DataflowResults<'tcx, BD>>
+where
+ BD: BitDenotation<'tcx>,
+ DR: Borrow<DataflowResults<'tcx, BD>>,
+{
+ flow_state: FlowAtLocation<'tcx, BD, DR>,
+
+ // The statement (or terminator) whose effect has been reconstructed in
+ // flow_state.
+ curr_loc: Option<Location>,
+
+ body: &'mir Body<'tcx>,
+}
+
+pub type DataflowResultsRefCursor<'mir, 'tcx, BD> =
+ DataflowResultsCursor<'mir, 'tcx, BD, &'mir DataflowResults<'tcx, BD>>;
+
+impl<'mir, 'tcx, BD, DR> DataflowResultsCursor<'mir, 'tcx, BD, DR>
+where
+ BD: BitDenotation<'tcx>,
+ DR: Borrow<DataflowResults<'tcx, BD>>,
+{
+ pub fn new(result: DR, body: &'mir Body<'tcx>) -> Self {
+ DataflowResultsCursor {
+ flow_state: FlowAtLocation::new(result),
+ curr_loc: None,
+ body,
+ }
+ }
+
+ /// Seek to the given location in MIR. This method is fast if you are
+ /// traversing your MIR statements in order.
+ ///
+ /// After calling `seek`, the current state will reflect all effects up to
+ /// and including the `before_statement_effect` of the statement at location
+ /// `loc`. The `statement_effect` of the statement at `loc` will be
+ /// available as the current effect (see e.g. `each_gen_bit`).
+ ///
+ /// If `loc.statement_index` equals the number of statements in the block,
+ /// we will reconstruct the terminator effect in the same way as described
+ /// above.
+ pub fn seek(&mut self, loc: Location) {
+ if self.curr_loc.map(|cur| loc == cur).unwrap_or(false) {
+ return;
+ }
+
+ let start_index;
+ let should_reset = match self.curr_loc {
+ None => true,
+ Some(cur)
+ if loc.block != cur.block || loc.statement_index < cur.statement_index => true,
+ _ => false,
+ };
+ if should_reset {
+ self.flow_state.reset_to_entry_of(loc.block);
+ start_index = 0;
+ } else {
+ let curr_loc = self.curr_loc.unwrap();
+ start_index = curr_loc.statement_index;
+ // Apply the effect from the last seek to the current state.
+ self.flow_state.apply_local_effect(curr_loc);
+ }
+
+ for stmt in start_index..loc.statement_index {
+ let mut stmt_loc = loc;
+ stmt_loc.statement_index = stmt;
+ self.flow_state.reconstruct_statement_effect(stmt_loc);
+ self.flow_state.apply_local_effect(stmt_loc);
+ }
+
+ if loc.statement_index == self.body[loc.block].statements.len() {
+ self.flow_state.reconstruct_terminator_effect(loc);
+ } else {
+ self.flow_state.reconstruct_statement_effect(loc);
+ }
+ self.curr_loc = Some(loc);
+ }
+
+ /// Return whether the current state contains bit `x`.
+ pub fn contains(&self, x: BD::Idx) -> bool {
+ self.flow_state.contains(x)
+ }
+
+ /// Iterate over each `gen` bit in the current effect (invoke `seek` first).
+ pub fn each_gen_bit<F>(&self, f: F)
+ where
+ F: FnMut(BD::Idx),
+ {
+ self.flow_state.each_gen_bit(f)
+ }
+}
+
pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
analysis: &T,
result: &DataflowResults<'tcx, T>,
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding instead. For instance:
-```compile_pass
+```
struct Irrefutable(i32);
let irr = Irrefutable(0);
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding inside a `loop` instead. For instance:
-```compile_pass,no_run
+```no_run
struct Irrefutable(i32);
let irr = Irrefutable(0);
// Now comes the rote stuff:
hir::ExprKind::Repeat(ref v, ref count) => {
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(count.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(count.hir_id);
let substs = InternalSubsts::identity_for_item(cx.tcx.global_tcx(), def_id);
let instance = ty::Instance::resolve(
cx.tcx.global_tcx(),
Res::Def(DefKind::ConstParam, def_id) => {
let hir_id = cx.tcx.hir().as_local_hir_id(def_id).unwrap();
let item_id = cx.tcx.hir().get_parent_node(hir_id);
- let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(item_id);
+ let item_def_id = cx.tcx.hir().local_def_id(item_id);
let generics = cx.tcx.generics_of(item_def_id);
- let local_def_id = cx.tcx.hir().local_def_id_from_hir_id(hir_id);
+ let local_def_id = cx.tcx.hir().local_def_id(hir_id);
let index = generics.param_def_id_to_index[&local_def_id];
let name = cx.tcx.hir().name(hir_id).as_interned_str();
let val = ConstValue::Param(ty::ParamConst::new(index, name));
) -> ExprRef<'tcx> {
let upvar_id = ty::UpvarId {
var_path: ty::UpvarPath { hir_id: var_hir_id },
- closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(),
+ closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).to_local(),
};
let upvar_capture = cx.tables().upvar_capture(upvar_id);
let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
impl<'a, 'tcx> Cx<'a, 'tcx> {
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
let tcx = infcx.tcx;
- let src_def_id = tcx.hir().local_def_id_from_hir_id(src_id);
+ let src_def_id = tcx.hir().local_def_id(src_id);
let tables = tcx.typeck_tables_of(src_def_id);
let body_owner_kind = tcx.hir().body_owner_kind(src_id);
use crate::hair::*;
use rustc::hir;
-use syntax::ptr::P;
+use rustc::hir::ptr::P;
pub trait ToRef {
type Output;
fn from_ctor(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> Option<IntRange<'tcx>> {
// Floating-point ranges are permitted and we don't want
// to consider them when constructing integer ranges.
- fn is_integral<'tcx>(ty: Ty<'tcx>) -> bool {
+ fn is_integral(ty: Ty<'_>) -> bool {
match ty.sty {
ty::Char | ty::Int(_) | ty::Uint(_) => true,
_ => false,
use rustc::hir::def::*;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use rustc::hir::ptr::P;
use rustc::hir::{self, Pat, PatKind};
use smallvec::smallvec;
use std::slice;
-use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-pub(crate) fn check_match<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) {
tcx.hir().body_owned_by(id)
} else {
}.visit_body(tcx.hir().body(body_id));
}
-fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> {
+fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> {
struct_span_err!(sess, sp, E0004, "{}", &error_message)
}
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
+use rustc::hir::ptr::P;
use rustc_data_structures::indexed_vec::Idx;
use std::cmp::Ordering;
use std::fmt;
use syntax::ast;
-use syntax::ptr::P;
use syntax::symbol::sym;
use syntax_pos::Span;
use rustc::ty::{self, Ty, TypeAndMut};
use rustc::ty::layout::{self, TyLayout, Size};
use rustc::ty::adjustment::{PointerCast};
-use syntax::ast::{FloatTy, IntTy, UintTy};
+use syntax::ast::FloatTy;
use syntax::symbol::sym;
use rustc_apfloat::ieee::{Single, Double};
};
use rustc::mir::CastKind;
-use super::{InterpretCx, Machine, PlaceTy, OpTy, Immediate};
+use super::{InterpCx, Machine, PlaceTy, OpTy, Immediate, FnVal};
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
def_id,
substs,
).ok_or_else(|| InterpError::TooGeneric.into());
- let fn_ptr = self.memory.create_fn_alloc(instance?);
+ let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance?));
self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
}
_ => bug!("reify fn pointer on {:?}", src.layout.ty),
substs,
ty::ClosureKind::FnOnce,
);
- let fn_ptr = self.memory.create_fn_alloc(instance);
+ let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into());
self.write_immediate(val, dest)?;
}
"Unexpected cast from type {:?}", src_layout.ty
);
match val.to_bits_or_ptr(src_layout.size, self) {
- Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
+ Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout),
Ok(data) => self.cast_from_int(data, src_layout, dest_layout),
}
}
fn cast_from_ptr(
&self,
ptr: Pointer<M::PointerTag>,
- ty: Ty<'tcx>
+ src_layout: TyLayout<'tcx>,
+ dest_layout: TyLayout<'tcx>,
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
use rustc::ty::TyKind::*;
- match ty.sty {
+
+ match dest_layout.ty.sty {
// Casting to a reference or fn pointer is not permitted by rustc,
// no need to support it here.
- RawPtr(_) |
- Int(IntTy::Isize) |
- Uint(UintTy::Usize) => Ok(ptr.into()),
- Int(_) | Uint(_) => err!(ReadPointerAsBytes),
- _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
+ RawPtr(_) => Ok(ptr.into()),
+ Int(_) | Uint(_) => {
+ let size = self.memory.pointer_size();
+
+ match self.force_bits(Scalar::Ptr(ptr), size) {
+ Ok(bits) => self.cast_from_int(bits, src_layout, dest_layout),
+ Err(_) if dest_layout.size == size => Ok(ptr.into()),
+ Err(e) => Err(e),
+ }
+ }
+ _ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty)
}
}
Memory, Machine
};
-pub struct InterpretCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
+pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// Stores the `Machine` instance.
pub machine: M,
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> {
#[inline]
fn data_layout(&self) -> &layout::TargetDataLayout {
&self.tcx.data_layout
}
}
-impl<'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'mir, 'tcx, M>
+impl<'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpCx<'mir, 'tcx, M>
where
M: Machine<'mir, 'tcx>,
{
}
}
-impl<'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpretCx<'mir, 'tcx, M>
+impl<'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'mir, 'tcx, M>
where
M: Machine<'mir, 'tcx>,
{
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
type Ty = Ty<'tcx>;
type TyLayout = InterpResult<'tcx, TyLayout<'tcx>>;
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
- pub fn new(tcx: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>, machine: M) -> Self {
- InterpretCx {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+ pub fn new(
+ tcx: TyCtxtAt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ machine: M,
+ memory_extra: M::MemoryExtra,
+ ) -> Self {
+ InterpCx {
machine,
tcx,
param_env,
- memory: Memory::new(tcx),
+ memory: Memory::new(tcx, memory_extra),
stack: Vec::new(),
vtables: FxHashMap::default(),
}
};
use super::{
- Machine, PlaceTy, OpTy, InterpretCx, Immediate,
+ Machine, PlaceTy, OpTy, InterpCx, Immediate,
};
mod type_name;
Ok(Scalar::from_uint(bits_out, size))
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Returns `true` if emulation happened.
pub fn emulate_intrinsic(
&mut self,
use super::{
Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
- InterpretCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory
+ InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory
};
/// Whether this kind of memory is allowed to leak
/// The `default()` is used for pointers to consts, statics, vtables and functions.
type PointerTag: ::std::fmt::Debug + Copy + Eq + Hash + 'static;
+ /// Machines can define extra (non-instance) things that represent values of function pointers.
+ /// For example, Miri uses this to return a fucntion pointer from `dlsym`
+ /// that can later be called to execute the right thing.
+ type ExtraFnVal: ::std::fmt::Debug + Copy;
+
/// Extra data stored in every call frame.
type FrameExtra;
/// Extra data stored in memory. A reference to this is available when `AllocExtra`
/// gets initialized, so you can e.g., have an `Rc` here if there is global state you
/// need access to in the `AllocExtra` hooks.
- type MemoryExtra: Default;
+ type MemoryExtra;
/// Extra data stored in every allocation.
type AllocExtra: AllocationExtra<Self::PointerTag> + 'static;
const STATIC_KIND: Option<Self::MemoryKinds>;
/// Whether to enforce the validity invariant
- fn enforce_validity(ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool;
+ fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
/// Called before a basic block terminator is executed.
/// You can use this to detect endlessly running programs.
- fn before_terminator(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
+ fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
/// Entry point to all function calls.
///
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
/// was used.
fn find_fn(
- ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
ret: Option<mir::BasicBlock>,
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>>;
+ /// Execute `fn_val`. it is the hook's responsibility to advance the instruction
+ /// pointer as appropriate.
+ fn call_extra_fn(
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ fn_val: Self::ExtraFnVal,
+ args: &[OpTy<'tcx, Self::PointerTag>],
+ dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
+ ret: Option<mir::BasicBlock>,
+ ) -> InterpResult<'tcx>;
+
/// Directly process an intrinsic without pushing a stack frame.
/// If this returns successfully, the engine will take care of jumping to the next block.
fn call_intrinsic(
- ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: PlaceTy<'tcx, Self::PointerTag>,
///
/// Returns a (value, overflowed) pair if the operation succeeded
fn ptr_op(
- ecx: &InterpretCx<'mir, 'tcx, Self>,
+ ecx: &InterpCx<'mir, 'tcx, Self>,
bin_op: mir::BinOp,
left: ImmTy<'tcx, Self::PointerTag>,
right: ImmTy<'tcx, Self::PointerTag>,
/// Heap allocations via the `box` keyword.
fn box_alloc(
- ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
dest: PlaceTy<'tcx, Self::PointerTag>,
) -> InterpResult<'tcx>;
/// Executes a retagging operation
#[inline]
fn retag(
- _ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_kind: mir::RetagKind,
_place: PlaceTy<'tcx, Self::PointerTag>,
) -> InterpResult<'tcx> {
}
/// Called immediately before a new stack frame got pushed
- fn stack_push(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
+ fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
/// Called immediately after a stack frame gets popped
fn stack_pop(
- ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
extra: Self::FrameExtra,
) -> InterpResult<'tcx>;
MaybeDead,
}
+/// The value of a function pointer.
+#[derive(Debug, Copy, Clone)]
+pub enum FnVal<'tcx, Other> {
+ Instance(Instance<'tcx>),
+ Other(Other),
+}
+
+impl<'tcx, Other> FnVal<'tcx, Other> {
+ pub fn as_instance(self) -> InterpResult<'tcx, Instance<'tcx>> {
+ match self {
+ FnVal::Instance(instance) =>
+ Ok(instance),
+ FnVal::Other(_) =>
+ err!(MachineError(
+ format!("Expected instance function pointer, got 'other' pointer")
+ )),
+ }
+ }
+}
+
// `Memory` has to depend on the `Machine` because some of its operations
// (e.g., `get`) call a `Machine` hook.
pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
// FIXME: this should not be public, but interning currently needs access to it
pub(super) alloc_map: M::MemoryMap,
+ /// Map for "extra" function pointers.
+ extra_fn_ptr_map: FxHashMap<AllocId, M::ExtraFnVal>,
+
/// To be able to compare pointers with NULL, and to check alignment for accesses
/// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
/// that do not exist any more.
+ // FIXME: this should not be public, but interning currently needs access to it
pub(super) dead_alloc_map: FxHashMap<AllocId, (Size, Align)>,
/// Extra data added by the machine.
pub extra: M::MemoryExtra,
/// Lets us implement `HasDataLayout`, which is awfully convenient.
- pub(super) tcx: TyCtxtAt<'tcx>,
+ pub tcx: TyCtxtAt<'tcx>,
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> {
fn clone(&self) -> Self {
Memory {
alloc_map: self.alloc_map.clone(),
+ extra_fn_ptr_map: self.extra_fn_ptr_map.clone(),
dead_alloc_map: self.dead_alloc_map.clone(),
extra: (),
tcx: self.tcx,
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
- pub fn new(tcx: TyCtxtAt<'tcx>) -> Self {
+ pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
Memory {
alloc_map: M::MemoryMap::default(),
+ extra_fn_ptr_map: FxHashMap::default(),
dead_alloc_map: FxHashMap::default(),
- extra: M::MemoryExtra::default(),
+ extra,
tcx,
}
}
ptr.with_tag(M::tag_static_base_pointer(ptr.alloc_id, &self))
}
- pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer<M::PointerTag> {
- let id = self.tcx.alloc_map.lock().create_fn_alloc(instance);
+ pub fn create_fn_alloc(
+ &mut self,
+ fn_val: FnVal<'tcx, M::ExtraFnVal>,
+ ) -> Pointer<M::PointerTag>
+ {
+ let id = match fn_val {
+ FnVal::Instance(instance) => self.tcx.alloc_map.lock().create_fn_alloc(instance),
+ FnVal::Other(extra) => {
+ // FIXME(RalfJung): Should we have a cache here?
+ let id = self.tcx.alloc_map.lock().reserve();
+ let old = self.extra_fn_ptr_map.insert(id, extra);
+ assert!(old.is_none());
+ id
+ }
+ };
self.tag_static_base_pointer(Pointer::from(id))
}
pub fn reallocate(
&mut self,
ptr: Pointer<M::PointerTag>,
- old_size: Size,
- old_align: Align,
+ old_size_and_align: Option<(Size, Align)>,
new_size: Size,
new_align: Align,
kind: MemoryKind<M::MemoryKinds>,
// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
// This happens so rarely, the perf advantage is outweighed by the maintenance cost.
let new_ptr = self.allocate(new_size, new_align, kind);
+ let old_size = match old_size_and_align {
+ Some((size, _align)) => size,
+ None => Size::from_bytes(self.get(ptr.alloc_id)?.bytes.len() as u64),
+ };
self.copy(
ptr.into(),
- old_align,
+ Align::from_bytes(1).unwrap(), // old_align anyway gets checked below by `deallocate`
new_ptr.into(),
new_align,
old_size.min(new_size),
/*nonoverlapping*/ true,
)?;
- self.deallocate(ptr, Some((old_size, old_align)), kind)?;
+ self.deallocate(ptr, old_size_and_align, kind)?;
Ok(new_ptr)
}
pub fn deallocate(
&mut self,
ptr: Pointer<M::PointerTag>,
- size_and_align: Option<(Size, Align)>,
+ old_size_and_align: Option<(Size, Align)>,
kind: MemoryKind<M::MemoryKinds>,
) -> InterpResult<'tcx> {
trace!("deallocating: {}", ptr.alloc_id);
format!("{:?}", kind),
));
}
- if let Some((size, align)) = size_and_align {
+ if let Some((size, align)) = old_size_and_align {
if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
let bytes = Size::from_bytes(alloc.bytes.len() as u64);
return err!(IncorrectAllocationInformation(size,
id: AllocId,
liveness: AllocCheck,
) -> InterpResult<'static, (Size, Align)> {
+ // Regular allocations.
if let Ok(alloc) = self.get(id) {
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
}
- // can't do this in the match argument, we may get cycle errors since the lock would get
- // dropped after the match.
+ // Function pointers.
+ if let Ok(_) = self.get_fn_alloc(id) {
+ return if let AllocCheck::Dereferencable = liveness {
+ // The caller requested no function pointers.
+ err!(DerefFunctionPointer)
+ } else {
+ Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
+ };
+ }
+ // Foreign statics.
+ // Can't do this in the match argument, we may get cycle errors since the lock would
+ // be held throughout the match.
let alloc = self.tcx.alloc_map.lock().get(id);
- // Could also be a fn ptr or extern static
match alloc {
- Some(GlobalAlloc::Function(..)) => {
- if let AllocCheck::Dereferencable = liveness {
- // The caller requested no function pointers.
- err!(DerefFunctionPointer)
- } else {
- Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
- }
- }
- // `self.get` would also work, but can cause cycles if a static refers to itself
Some(GlobalAlloc::Static(did)) => {
- // The only way `get` couldn't have worked here is if this is an extern static
assert!(self.tcx.is_foreign_item(did));
// Use size and align of the type
let ty = self.tcx.type_of(did);
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
- Ok((layout.size, layout.align.abi))
+ return Ok((layout.size, layout.align.abi));
}
- _ => {
- if let Ok(alloc) = self.get(id) {
- Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align))
- }
- else if let AllocCheck::MaybeDead = liveness {
- // Deallocated pointers are allowed, we should be able to find
- // them in the map.
- Ok(*self.dead_alloc_map.get(&id)
- .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
- } else {
- err!(DanglingPointerDeref)
- }
- },
+ _ => {}
+ }
+ // The rest must be dead.
+ if let AllocCheck::MaybeDead = liveness {
+ // Deallocated pointers are allowed, we should be able to find
+ // them in the map.
+ Ok(*self.dead_alloc_map.get(&id)
+ .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
+ } else {
+ err!(DanglingPointerDeref)
}
}
- pub fn get_fn(&self, ptr: Pointer<M::PointerTag>) -> InterpResult<'tcx, Instance<'tcx>> {
+ fn get_fn_alloc(&self, id: AllocId) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
+ trace!("reading fn ptr: {}", id);
+ if let Some(extra) = self.extra_fn_ptr_map.get(&id) {
+ Ok(FnVal::Other(*extra))
+ } else {
+ match self.tcx.alloc_map.lock().get(id) {
+ Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)),
+ _ => Err(InterpError::ExecuteMemory.into()),
+ }
+ }
+ }
+
+ pub fn get_fn(
+ &self,
+ ptr: Scalar<M::PointerTag>,
+ ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
+ let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value.
if ptr.offset.bytes() != 0 {
return err!(InvalidFunctionPointer);
}
- trace!("reading fn ptr: {}", ptr.alloc_id);
- match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
- Some(GlobalAlloc::Function(instance)) => Ok(instance),
- _ => Err(InterpError::ExecuteMemory.into()),
- }
+ self.get_fn_alloc(ptr.alloc_id)
}
pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
pub use self::eval_context::{
- InterpretCx, Frame, StackPopCleanup, LocalState, LocalValue,
+ InterpCx, Frame, StackPopCleanup, LocalState, LocalValue,
};
pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
-pub use self::memory::{Memory, MemoryKind, AllocCheck};
+pub use self::memory::{Memory, MemoryKind, AllocCheck, FnVal};
pub use self::machine::{Machine, AllocMap, MayLeak};
sign_extend, truncate,
};
use super::{
- InterpretCx, Machine,
+ InterpCx, Machine,
MemPlace, MPlaceTy, PlaceTy, Place,
};
pub use rustc::mir::interpret::ScalarMaybeUndef;
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
/// Returns `None` if the layout does not permit loading this as a value.
fn try_read_immediate_from_mplace(
use rustc_apfloat::Float;
use rustc::mir::interpret::{InterpResult, Scalar};
-use super::{InterpretCx, PlaceTy, Immediate, Machine, ImmTy};
+use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
/// and a boolean signifying the potential overflow to the destination.
pub fn binop_with_overflow(
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn binary_char_op(
&self,
bin_op: mir::BinOp,
use super::{
GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
- InterpretCx, Machine, AllocMap, AllocationExtra,
+ InterpCx, Machine, AllocMap, AllocationExtra,
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
};
}
// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
-impl<'mir, 'tcx, Tag, M> InterpretCx<'mir, 'tcx, M>
+impl<'mir, 'tcx, Tag, M> InterpCx<'mir, 'tcx, M>
where
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
Tag: ::std::fmt::Debug + Copy + Eq + Hash + 'static,
// global table but not in its local memory: It calls back into tcx through
// a query, triggering the CTFE machinery to actually turn this lazy reference
// into a bunch of bytes. IOW, statics are evaluated with CTFE even when
- // this InterpretCx uses another Machine (e.g., in miri). This is what we
+ // this InterpCx uses another Machine (e.g., in miri). This is what we
// want! This way, computing statics works consistently between codegen
// and miri: They use the same query to eventually obtain a `ty::Const`
// and use that for further computation.
-//! This module contains the `InterpretCx` methods for executing a single step of the interpreter.
+//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.
use rustc::ty::layout::LayoutOf;
use rustc::mir::interpret::{InterpResult, Scalar, PointerArithmetic};
-use super::{InterpretCx, Machine};
+use super::{InterpCx, Machine};
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub fn run(&mut self) -> InterpResult<'tcx> {
while self.step()? {}
Ok(())
use syntax::source_map::Span;
use rustc_target::spec::abi::Abi;
-use rustc::mir::interpret::{InterpResult, PointerArithmetic, InterpError, Scalar};
use super::{
- InterpretCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
+ InterpResult, PointerArithmetic, InterpError, Scalar,
+ InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
};
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[inline]
pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> InterpResult<'tcx> {
if let Some(target) = target {
};
let func = self.eval_operand(func, None)?;
- let (fn_def, abi) = match func.layout.ty.sty {
+ let (fn_val, abi) = match func.layout.ty.sty {
ty::FnPtr(sig) => {
let caller_abi = sig.abi();
- let fn_ptr = self.force_ptr(self.read_scalar(func)?.not_undef()?)?;
- let instance = self.memory.get_fn(fn_ptr)?;
- (instance, caller_abi)
+ let fn_ptr = self.read_scalar(func)?.not_undef()?;
+ let fn_val = self.memory.get_fn(fn_ptr)?;
+ (fn_val, caller_abi)
}
ty::FnDef(def_id, substs) => {
let sig = func.layout.ty.fn_sig(*self.tcx);
- (self.resolve(def_id, substs)?, sig.abi())
+ (FnVal::Instance(self.resolve(def_id, substs)?), sig.abi())
},
_ => {
let msg = format!("can't handle callee of type {:?}", func.layout.ty);
};
let args = self.eval_operands(args)?;
self.eval_fn_call(
- fn_def,
+ fn_val,
terminator.source_info.span,
abi,
&args[..],
/// Call this function -- pushing the stack frame and initializing the arguments.
fn eval_fn_call(
&mut self,
- instance: ty::Instance<'tcx>,
+ fn_val: FnVal<'tcx, M::ExtraFnVal>,
span: Span,
caller_abi: Abi,
args: &[OpTy<'tcx, M::PointerTag>],
dest: Option<PlaceTy<'tcx, M::PointerTag>>,
ret: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
- trace!("eval_fn_call: {:#?}", instance);
+ trace!("eval_fn_call: {:#?}", fn_val);
+
+ let instance = match fn_val {
+ FnVal::Instance(instance) => instance,
+ FnVal::Other(extra) => {
+ return M::call_extra_fn(self, extra, args, dest, ret);
+ }
+ };
match instance.def {
ty::InstanceDef::Intrinsic(..) => {
self.tcx.data_layout.pointer_align.abi,
)?.expect("cannot be a ZST");
let fn_ptr = self.memory.get(vtable_slot.alloc_id)?
- .read_ptr_sized(self, vtable_slot)?.to_ptr()?;
- let instance = self.memory.get_fn(fn_ptr)?;
+ .read_ptr_sized(self, vtable_slot)?.not_undef()?;
+ let drop_fn = self.memory.get_fn(fn_ptr)?;
// `*mut receiver_place.layout.ty` is almost the layout that we
// want for args[0]: We have to project to field 0 because we want
});
trace!("Patched self operand to {:#?}", args[0]);
// recurse with concrete function
- self.eval_fn_call(instance, span, caller_abi, &args, dest, ret)
+ self.eval_fn_call(drop_fn, span, caller_abi, &args, dest, ret)
}
}
}
let dest = MPlaceTy::dangling(self.layout_of(ty)?, self);
self.eval_fn_call(
- instance,
+ FnVal::Instance(instance),
span,
Abi::Rust,
&[arg.into()],
use rustc::ty::layout::{Size, Align, LayoutOf};
use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic};
-use super::{InterpretCx, InterpError, Machine, MemoryKind};
+use super::{InterpCx, InterpError, Machine, MemoryKind, FnVal};
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
/// objects.
///
let tcx = &*self.tcx;
let drop = Instance::resolve_drop_in_place(*tcx, ty);
- let drop = self.memory.create_fn_alloc(drop);
+ let drop = self.memory.create_fn_alloc(FnVal::Instance(drop));
// no need to do any alignment checks on the memory accesses below, because we know the
// allocation is correctly aligned as we created it above. Also we're only offsetting by
def_id,
substs,
).ok_or_else(|| InterpError::TooGeneric)?;
- let fn_ptr = self.memory.create_fn_alloc(instance);
+ let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?;
self.memory
.get_mut(method_ptr.alloc_id)?
let drop_fn = self.memory
.get(vtable.alloc_id)?
.read_ptr_sized(self, vtable)?
- .to_ptr()?;
- let drop_instance = self.memory.get_fn(drop_fn)?;
+ .not_undef()?;
+ // We *need* an instance here, no other kind of function value, to be able
+ // to determine the type.
+ let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
trace!("Found drop fn: {:?}", drop_instance);
let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx);
let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
use rustc::ty::layout::{self, TyLayout, LayoutOf, VariantIdx};
use rustc::ty;
use rustc_data_structures::fx::FxHashSet;
-use rustc::mir::interpret::{
- GlobalAlloc, InterpResult, InterpError,
-};
use std::hash::Hash;
use super::{
- OpTy, Machine, InterpretCx, ValueVisitor, MPlaceTy,
+ GlobalAlloc, InterpResult, InterpError,
+ OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy,
};
macro_rules! validation_failure {
debug_assert!(hi <= max_hi);
if lo > hi {
format!("less or equal to {}, or greater or equal to {}", hi, lo)
+ } else if lo == hi {
+ format!("equal to {}", lo)
+ } else if lo == 0 {
+ debug_assert!(hi < max_hi, "should not be printing if the range covers everything");
+ format!("less or equal to {}", hi)
+ } else if hi == max_hi {
+ debug_assert!(lo > 0, "should not be printing if the range covers everything");
+ format!("greater or equal to {}", lo)
} else {
- if lo == 0 {
- debug_assert!(hi < max_hi, "should not be printing if the range covers everything");
- format!("less or equal to {}", hi)
- } else if hi == max_hi {
- format!("greater or equal to {}", lo)
- } else {
- format!("in the range {:?}", r)
- }
+ format!("in the range {:?}", r)
}
}
MPlaceTy<'tcx, M::PointerTag>,
Vec<PathElem>,
>>,
- ecx: &'rt InterpretCx<'mir, 'tcx, M>,
+ ecx: &'rt InterpCx<'mir, 'tcx, M>,
}
impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M> {
type V = OpTy<'tcx, M::PointerTag>;
#[inline(always)]
- fn ecx(&self) -> &InterpretCx<'mir, 'tcx, M> {
+ fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
&self.ecx
}
}
ty::FnPtr(_sig) => {
let value = value.to_scalar_or_undef();
- let ptr = try_validation!(value.to_ptr(),
- value, self.path, "a pointer");
- let _fn = try_validation!(self.ecx.memory.get_fn(ptr),
- value, self.path, "a function pointer");
+ let _fn = try_validation!(
+ value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
+ value, self.path, "a function pointer"
+ );
// FIXME: Check if the signature matches
}
// This should be all the primitive types
if lo == 1 && hi == max_hi {
// Only NULL is the niche. So make sure the ptr is NOT NULL.
if self.ecx.memory.ptr_may_be_null(ptr) {
- // These conditions are just here to improve the diagnostics so we can
- // differentiate between null pointers and dangling pointers
- if self.ref_tracking_for_consts.is_some() &&
- self.ecx.memory.get(ptr.alloc_id).is_err() &&
- self.ecx.memory.get_fn(ptr).is_err() {
- return validation_failure!(
- "encountered dangling pointer", self.path
- );
- }
- return validation_failure!("a potentially NULL pointer", self.path);
+ return validation_failure!(
+ "a potentially NULL pointer",
+ self.path,
+ format!(
+ "something that cannot possibly fail to be {}",
+ wrapping_range_format(&layout.valid_range, max_hi)
+ )
+ );
}
return Ok(());
} else {
- // Conservatively, we reject, because the pointer *could* have this
+ // Conservatively, we reject, because the pointer *could* have a bad
// value.
return validation_failure!(
"a pointer",
}
}
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// This function checks the data at `op`. `op` is assumed to cover valid memory if it
/// is an indirect operand.
/// It will error if the bits at the destination do not match the ones described by the layout.
};
use super::{
- Machine, InterpretCx, MPlaceTy, OpTy,
+ Machine, InterpCx, MPlaceTy, OpTy,
};
// A thing that we can project into, and that has a layout.
/// Makes this into an `OpTy`.
fn to_op(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>>;
/// Creates this from an `MPlaceTy`.
/// Projects to the given enum variant.
fn project_downcast(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
variant: VariantIdx,
) -> InterpResult<'tcx, Self>;
/// Projects to the n-th field.
fn project_field(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
field: u64,
) -> InterpResult<'tcx, Self>;
}
#[inline(always)]
fn to_op(
self,
- _ecx: &InterpretCx<'mir, 'tcx, M>,
+ _ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
Ok(self)
}
#[inline(always)]
fn project_downcast(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
variant: VariantIdx,
) -> InterpResult<'tcx, Self> {
ecx.operand_downcast(self, variant)
#[inline(always)]
fn project_field(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
field: u64,
) -> InterpResult<'tcx, Self> {
ecx.operand_field(self, field)
#[inline(always)]
fn to_op(
self,
- _ecx: &InterpretCx<'mir, 'tcx, M>,
+ _ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
Ok(self.into())
}
#[inline(always)]
fn project_downcast(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
variant: VariantIdx,
) -> InterpResult<'tcx, Self> {
ecx.mplace_downcast(self, variant)
#[inline(always)]
fn project_field(
self,
- ecx: &InterpretCx<'mir, 'tcx, M>,
+ ecx: &InterpCx<'mir, 'tcx, M>,
field: u64,
) -> InterpResult<'tcx, Self> {
ecx.mplace_field(self, field)
pub trait $visitor_trait_name<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
type V: Value<'mir, 'tcx, M>;
- /// The visitor must have an `InterpretCx` in it.
+ /// The visitor must have an `InterpCx` in it.
fn ecx(&$($mutability)? self)
- -> &$($mutability)? InterpretCx<'mir, 'tcx, M>;
+ -> &$($mutability)? InterpCx<'mir, 'tcx, M>;
// Recursive actions, ready to be overloaded.
/// Visits the given value, dispatching as appropriate to more specialized visitors.
#![feature(slice_concat_ext)]
#![feature(trusted_len)]
#![feature(try_blocks)]
+#![feature(mem_take)]
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use] extern crate log;
}
}
-pub fn collect_crate_mono_items<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn collect_crate_mono_items(
+ tcx: TyCtxt<'_>,
mode: MonoItemCollectionMode,
-) -> (FxHashSet<MonoItem<'tcx>>, InliningMap<'tcx>) {
+) -> (FxHashSet<MonoItem<'_>>, InliningMap<'_>) {
let roots = time(tcx.sess, "collecting roots", || {
collect_roots(tcx, mode)
});
// Find all non-generic items by walking the HIR. These items serve as roots to
// start monomorphizing from.
-fn collect_roots<'tcx>(tcx: TyCtxt<'tcx>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'tcx>> {
+fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
debug!("Collecting roots");
let mut roots = Vec::new();
}
}
-fn create_fn_mono_item<'tcx>(instance: Instance<'tcx>) -> MonoItem<'tcx> {
+fn create_fn_mono_item(instance: Instance<'_>) -> MonoItem<'_> {
debug!("create_fn_mono_item(instance={})", instance);
MonoItem::Fn(instance)
}
hir::ItemKind::Union(_, ref generics) => {
if generics.params.is_empty() {
if self.mode == MonoItemCollectionMode::Eager {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
debug!("RootCollector: ADT drop-glue for {}",
def_id_to_string(self.tcx, def_id));
hir::ItemKind::GlobalAsm(..) => {
debug!("RootCollector: ItemKind::GlobalAsm({})",
def_id_to_string(self.tcx,
- self.tcx.hir().local_def_id_from_hir_id(item.hir_id)));
+ self.tcx.hir().local_def_id(item.hir_id)));
self.output.push(MonoItem::GlobalAsm(item.hir_id));
}
hir::ItemKind::Static(..) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
debug!("RootCollector: ItemKind::Static({})",
def_id_to_string(self.tcx, def_id));
self.output.push(MonoItem::Static(def_id));
// actually used somewhere. Just declaring them is insufficient.
// but even just declaring them must collect the items they refer to
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let instance = Instance::mono(self.tcx, def_id);
let cid = GlobalId {
}
}
hir::ItemKind::Fn(..) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
self.push_if_root(def_id);
}
}
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
match ii.node {
hir::ImplItemKind::Method(hir::MethodSig { .. }, _) => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(ii.hir_id);
+ let def_id = self.tcx.hir().local_def_id(ii.hir_id);
self.push_if_root(def_id);
}
_ => { /* Nothing to do here */ }
}
}
-fn item_requires_monomorphization<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let generics = tcx.generics_of(def_id);
generics.requires_monomorphization(tcx)
}
}
}
- let impl_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let impl_def_id = tcx.hir().local_def_id(item.hir_id);
debug!("create_mono_items_for_default_impls(item={})",
def_id_to_string(tcx, impl_def_id));
}
}
-fn def_id_to_string<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> String {
+fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
let mut output = String::new();
let printer = DefPathBasedNames::new(tcx, false, false);
printer.push_def_path(def_id, &mut output);
tcx.symbol_name(Instance::mono(tcx, def_id))
}
MonoItem::GlobalAsm(hir_id) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
ty::SymbolName {
name: InternedString::intern(&format!("global_asm_{:?}", def_id))
}
};
}
MonoItem::GlobalAsm(hir_id) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(*hir_id);
+ let def_id = tcx.hir().local_def_id(*hir_id);
return if tcx.is_reachable_non_generic(def_id) {
*can_be_internalized = false;
default_visibility(tcx, def_id, false)
Some(def_id)
}
MonoItem::Static(def_id) => Some(def_id),
- MonoItem::GlobalAsm(hir_id) => Some(tcx.hir().local_def_id_from_hir_id(hir_id)),
+ MonoItem::GlobalAsm(hir_id) => Some(tcx.hir().local_def_id(hir_id)),
}
}
}
}
-fn collect_and_partition_mono_items<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn collect_and_partition_mono_items(
+ tcx: TyCtxt<'_>,
cnum: CrateNum,
-) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>) {
+) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'_>>>>) {
assert_eq!(cnum, LOCAL_CRATE);
let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
body
}
-pub fn build_adt_ctor<'tcx>(tcx: TyCtxt<'tcx>, ctor_id: DefId) -> &'tcx Body<'tcx> {
+pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
let span = tcx.hir().span_if_local(ctor_id)
/// after the assignment, we can be sure to obtain the same place value.
/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
/// copies. Data races are UB.)
-fn is_stable<'tcx>(
- place: &Place<'tcx>,
+fn is_stable(
+ place: &Place<'_>,
) -> bool {
use rustc::mir::Place::*;
}
}
-fn check_unused_unsafe<'a, 'tcx>(
- tcx: TyCtxt<'tcx>,
+fn check_unused_unsafe(
+ tcx: TyCtxt<'_>,
def_id: DefId,
used_unsafe: &FxHashSet<hir::HirId>,
- unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>,
+ unsafe_blocks: &mut Vec<(hir::HirId, bool)>,
) {
let body_id =
tcx.hir().as_local_hir_id(def_id).and_then(|hir_id| {
hir::intravisit::Visitor::visit_body(&mut visitor, body);
}
-fn unsafety_check_result<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> UnsafetyCheckResult {
+fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult {
debug!("unsafety_violations({:?})", def_id);
// N.B., this borrow is valid because all the consumers of
}
}
-fn unsafe_derive_on_repr_packed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: DefId) {
let lint_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(||
bug!("checking unsafety for non-local def id {:?}", def_id));
db.emit();
}
-fn builtin_derive_def_id<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<DefId> {
+fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
debug!("builtin_derive_def_id({:?})", def_id);
if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
if tcx.has_attr(impl_def_id, sym::automatically_derived) {
}
}
-pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
debug!("check_unsafety({:?})", def_id);
// closures are handled by their parent fn.
};
use crate::interpret::{
- self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy,
+ self, InterpCx, ScalarMaybeUndef, Immediate, OpTy,
ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState,
};
use crate::const_eval::{
/// Finds optimization opportunities on the MIR.
struct ConstPropagator<'mir, 'tcx> {
- ecx: InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+ ecx: InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
tcx: TyCtxt<'tcx>,
source: MirSource<'tcx>,
can_const_prop: IndexVec<Local, bool>,
// If the local is `Unitialized` or `Dead` then we haven't propagated a value into it.
//
- // `InterpretCx::access_local()` mostly takes care of this for us however, for ZSTs,
+ // `InterpCx::access_local()` mostly takes care of this for us however, for ZSTs,
// it will synthesize a value for us. In doing so, that will cause the
// `get_const(l).is_empty()` assert right before we call `set_const()` in `visit_statement`
// to fail.
pub struct Marker(pub &'static str);
impl MirPass for Marker {
- fn name<'a>(&'a self) -> Cow<'a, str> {
+ fn name(&self) -> Cow<'_, str> {
Cow::Borrowed(self.0)
}
}
}
-pub fn emit_mir<'tcx>(tcx: TyCtxt<'tcx>, outputs: &OutputFilenames) -> io::Result<()> {
+pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> {
let path = outputs.path(OutputType::Mir);
let mut f = File::create(&path)?;
mir_util::write_mir_pretty(tcx, None, &mut f)?;
use crate::transform::no_landing_pads::no_landing_pads;
use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation};
use crate::dataflow::{do_dataflow, DebugFormatted, state_for_location};
-use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
+use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals, RequiresStorage};
use crate::util::dump_mir;
use crate::util::liveness;
// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
- // This is only used for immovable generators.
- let borrowed_locals = if !movable {
- let analysis = HaveBeenBorrowedLocals::new(body);
- let result =
- do_dataflow(tcx, body, def_id, &[], &dead_unwinds, analysis,
- |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
- Some((analysis, result))
- } else {
- None
- };
+ let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body);
+ let borrowed_locals_result =
+ do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis,
+ |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+
+ // Calculate the MIR locals that we actually need to keep storage around
+ // for.
+ let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
+ let requires_storage =
+ do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis,
+ |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+ let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
// Calculate the liveness of MIR locals ignoring borrows.
let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len());
statement_index: data.statements.len(),
};
- if let Some((ref analysis, ref result)) = borrowed_locals {
+ if !movable {
let borrowed_locals = state_for_location(loc,
- analysis,
- result,
+ &borrowed_locals_analysis,
+ &borrowed_locals_result,
body);
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
// This is correct for movable generators since borrows cannot live across
liveness.outs[block].union(&borrowed_locals);
}
- let mut storage_liveness = state_for_location(loc,
- &storage_live_analysis,
- &storage_live,
- body);
+ let storage_liveness = state_for_location(loc,
+ &storage_live_analysis,
+ &storage_live,
+ body);
// Store the storage liveness for later use so we can restore the state
// after a suspension point
storage_liveness_map.insert(block, storage_liveness.clone());
- // Mark locals without storage statements as always having live storage
- storage_liveness.union(&ignored.0);
+ let mut storage_required = state_for_location(loc,
+ &requires_storage_analysis,
+ &requires_storage,
+ body);
+
+ // Mark locals without storage statements as always requiring storage
+ storage_required.union(&ignored.0);
// Locals live are live at this point only if they are used across
// suspension points (the `liveness` variable)
- // and their storage is live (the `storage_liveness` variable)
- let mut live_locals_here = storage_liveness;
+ // and their storage is required (the `storage_required` variable)
+ let mut live_locals_here = storage_required;
live_locals_here.intersect(&liveness.outs[block]);
// The generator argument is ignored
live_locals_here.remove(self_arg());
+ debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here);
+
// Add the locals live at this suspension point to the set of locals which live across
// any suspension points
live_locals.union(&live_locals_here);
live_locals_at_suspension_points.push(live_locals_here);
}
}
+ debug!("live_locals = {:?}", live_locals);
// Renumber our liveness_map bitsets to include only the locals we are
// saving.
body,
&live_locals,
&ignored,
- storage_live,
- storage_live_analysis);
+ requires_storage,
+ requires_storage_analysis);
LivenessInfo {
live_locals,
body: &'mir Body<'tcx>,
stored_locals: &liveness::LiveVarSet,
ignored: &StorageIgnored,
- storage_live: DataflowResults<'tcx, MaybeStorageLive<'mir, 'tcx>>,
- _storage_live_analysis: MaybeStorageLive<'mir, 'tcx>,
+ requires_storage: DataflowResults<'tcx, RequiresStorage<'mir, 'tcx>>,
+ _requires_storage_analysis: RequiresStorage<'mir, 'tcx>,
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
assert_eq!(body.local_decls.len(), ignored.0.domain_size());
assert_eq!(body.local_decls.len(), stored_locals.domain_size());
let mut visitor = StorageConflictVisitor {
body,
stored_locals: &stored_locals,
- local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len())
+ local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()),
};
- let mut state = FlowAtLocation::new(storage_live);
+ let mut state = FlowAtLocation::new(requires_storage);
visitor.analyze_results(&mut state);
let local_conflicts = visitor.local_conflicts;
impl<'body, 'tcx, 's> DataflowResultsConsumer<'body, 'tcx>
for StorageConflictVisitor<'body, 'tcx, 's>
{
- type FlowState = FlowAtLocation<'tcx, MaybeStorageLive<'body, 'tcx>>;
+ type FlowState = FlowAtLocation<'tcx, RequiresStorage<'body, 'tcx>>;
fn body(&self) -> &'body Body<'tcx> {
self.body
impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> {
fn apply_state(&mut self,
- flow_state: &FlowAtLocation<'tcx, MaybeStorageLive<'body, 'tcx>>,
+ flow_state: &FlowAtLocation<'tcx, RequiresStorage<'body, 'tcx>>,
loc: Location) {
// Ignore unreachable blocks.
match self.body.basic_blocks()[loc.block].terminator().kind {
dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()) );
}
-fn source_info<'tcx>(body: &Body<'tcx>) -> SourceInfo {
+fn source_info(body: &Body<'_>) -> SourceInfo {
SourceInfo {
span: body.span,
scope: OUTERMOST_SOURCE_SCOPE,
}
}
-fn insert_clean_drop<'tcx>(body: &mut Body<'tcx>) -> BasicBlock {
+fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
let return_block = insert_term_block(body, TerminatorKind::Return);
// Create a block to destroy an unresumed generators. This can only destroy upvars.
};
}
-fn is_mir_available<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
tcx.mir_keys(def_id.krate).contains(&def_id)
}
/// Finds the full set of `DefId`s within the current crate that have
/// MIR associated with them.
-fn mir_keys<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) -> &'tcx DefIdSet {
+fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
assert_eq!(krate, LOCAL_CRATE);
let mut set = DefIdSet::default();
_: hir::HirId,
_: Span) {
if let hir::VariantData::Tuple(_, hir_id) = *v {
- self.set.insert(self.tcx.hir().local_def_id_from_hir_id(hir_id));
+ self.set.insert(self.tcx.hir().local_def_id(hir_id));
}
intravisit::walk_struct_def(self, v)
}
tcx.arena.alloc(set)
}
-fn mir_built<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
+fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
let mir = build::mir_build(tcx, def_id);
tcx.alloc_steal_mir(mir)
}
/// pass will be named after the type, and it will consist of a main
/// loop that goes over each available MIR and applies `run_pass`.
pub trait MirPass {
- fn name<'a>(&'a self) -> Cow<'a, str> {
+ fn name(&self) -> Cow<'_, str> {
default_name::<Self>()
}
}
}
-fn mir_const<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
+fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
// Unsafety check uses the raw mir, so make sure it is run
let _ = tcx.unsafety_check_result(def_id);
tcx.alloc_steal_mir(body)
}
-fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
+fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
if tcx.is_constructor(def_id) {
// There's no reason to run all of the MIR passes on constructors when
// we can just output the MIR we want directly. This also saves const
};
}
-fn mir_const_qualif<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> (u8, &'tcx BitSet<Local>) {
+fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet<Local>) {
// N.B., this `borrow()` is guaranteed to be valid (i.e., the value
// cannot yet be stolen), because `mir_validated()`, which steals
// from `mir_const(), forces this query to execute before
}
impl MirPass for SimplifyCfg {
- fn name<'a>(&'a self) -> Cow<'a, str> {
+ fn name(&self) -> Cow<'_, str> {
Cow::Borrowed(&self.label)
}
}
impl MirPass for SimplifyBranches {
- fn name<'a>(&'a self) -> Cow<'a, str> {
+ fn name(&self) -> Cow<'_, str> {
Cow::Borrowed(&self.label)
}
self.clear();
let mut finder = DefUseFinder {
- info: mem::replace(&mut self.info, IndexVec::new()),
+ info: mem::take(&mut self.info),
};
finder.visit_body(body);
self.info = finder.info
use super::pretty::dump_mir_def_ids;
/// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'tcx, W>(
- tcx: TyCtxt<'tcx>,
+pub fn write_mir_graphviz<W>(
+ tcx: TyCtxt<'_>,
single: Option<DefId>,
w: &mut W,
) -> io::Result<()>
/// Computes which local variables are live within the given function
/// `mir`, including drops.
-pub fn liveness_of_locals<'tcx>(
- body: &Body<'tcx>,
+pub fn liveness_of_locals(
+ body: &Body<'_>,
) -> LivenessResult {
let num_live_vars = body.local_decls.len();
let mut bits = LiveVarSet::new_empty(num_live_vars);
- // queue of things that need to be re-processed, and a set containing
- // the things currently in the queue
- let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_all(body.basic_blocks().len());
+ // The dirty queue contains the set of basic blocks whose entry sets have changed since they
+ // were last processed. At the start of the analysis, we initialize the queue in post-order to
+ // make it more likely that the entry set for a given basic block will have the effects of all
+ // its successors in the CFG applied before it is processed.
+ //
+ // FIXME(ecstaticmorse): Reverse post-order on the reverse CFG may generate a better iteration
+ // order when cycles are present, but the overhead of computing the reverse CFG may outweigh
+ // any benefits. Benchmark this and find out.
+ let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks().len());
+ for (bb, _) in traversal::postorder(body) {
+ dirty_queue.insert(bb);
+ }
+
+ // Add blocks which are not reachable from START_BLOCK to the work queue. These blocks will
+ // be processed after the ones added above.
+ for bb in body.basic_blocks().indices() {
+ dirty_queue.insert(bb);
+ }
let predecessors = body.predecessors();
}
}
-fn block<'tcx>(
- b: &BasicBlockData<'tcx>,
+fn block(
+ b: &BasicBlockData<'_>,
locals: usize,
) -> DefsUses {
let mut visitor = DefsUsesVisitor {
pub use self::graphviz::write_node_label as write_graphviz_node_label;
/// If possible, suggest replacing `ref` with `ref mut`.
-pub fn suggest_ref_mut<'tcx>(tcx: TyCtxt<'tcx>, binding_span: Span) -> Option<(String)> {
+pub fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<(String)> {
let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap();
if hi_src.starts_with("ref")
&& hi_src["ref".len()..].starts_with(Pattern_White_Space)
the relevant `fold_*()` method in `PlaceholderExpander`?");
}
- fn visit_fn_header(&mut self, header: &'a FnHeader) {
- if header.asyncness.node.is_async() && self.session.rust_2015() {
- struct_span_err!(self.session, header.asyncness.span, E0670,
- "`async fn` is not permitted in the 2015 edition").emit();
- }
- }
-
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
match ii.node {
ImplItemKind::Method(ref sig, _) => {
collector.print("HIR STATS");
}
-pub fn print_ast_stats<'v>(krate: &'v ast::Crate, title: &str) {
+pub fn print_ast_stats(krate: &ast::Crate, title: &str) {
let mut collector = StatCollector {
krate: None,
data: FxHashMap::default(),
use syntax::ast::Attribute;
use syntax::symbol::sym;
-pub fn test_layout<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn test_layout(tcx: TyCtxt<'_>) {
if tcx.features().rustc_attrs {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
tcx.hir()
impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
if let ItemKind::Ty(..) = item.node {
for attr in self.tcx.get_attrs(item_def_id).iter() {
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use]
cx: Context,
}
-fn check_mod_loops<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor {
sess: &tcx.sess,
hir_map: &tcx.hir(),
};
}
-fn const_is_rvalue_promotable_to_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn const_is_rvalue_promotable_to_static(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
assert!(def_id.is_local());
let hir_id = tcx.hir().as_local_hir_id(def_id)
tcx.rvalue_promotable_map(def_id).contains(&body_id.hir_id.local_id)
}
-fn rvalue_promotable_map<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ItemLocalSet {
+fn rvalue_promotable_map(tcx: TyCtxt<'_>, def_id: DefId) -> &ItemLocalSet {
let outer_def_id = tcx.closure_base_def_id(def_id);
if outer_def_id != def_id {
return tcx.rvalue_promotable_map(outer_def_id);
impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability {
let item_id = self.tcx.hir().body_owner(body_id);
- let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item_id);
+ let item_def_id = self.tcx.hir().local_def_id(item_id);
let outer_in_fn = self.in_fn;
let outer_tables = self.tables;
let nested_body_promotable = v.check_nested_body(body_id);
// Paths in constant contexts cannot refer to local variables,
// as there are none, and thus closures can't have upvars there.
- let closure_def_id = v.tcx.hir().local_def_id_from_hir_id(e.hir_id);
+ let closure_def_id = v.tcx.hir().local_def_id(e.hir_id);
if !v.tcx.upvars(closure_def_id).map_or(true, |v| v.is_empty()) {
NotPromotable
} else {
}
/// Finds the function marked with `#[plugin_registrar]`, if any.
-pub fn find_plugin_registrar<'tcx>(tcx: TyCtxt<'tcx>) -> Option<DefId> {
+pub fn find_plugin_registrar(tcx: TyCtxt<'_>) -> Option<DefId> {
tcx.plugin_registrar_fn(LOCAL_CRATE)
}
-fn plugin_registrar_fn<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Option<DefId> {
+fn plugin_registrar_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
assert_eq!(cnum, LOCAL_CRATE);
let mut finder = RegistrarFinder { registrars: Vec::new() };
0 => None,
1 => {
let (hir_id, _) = finder.registrars.pop().unwrap();
- Some(tcx.hir().local_def_id_from_hir_id(hir_id))
+ Some(tcx.hir().local_def_id(hir_id))
},
_ => {
let diagnostic = tcx.sess.diagnostic();
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
use syntax::ext::base::MacroExpanderFn;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::Symbol;
use syntax::ast;
use syntax::feature_gate::AttributeType;
use syntax_pos::Span;
///
/// Returns empty slice in case the plugin was loaded
/// with `--extra-plugins`
- pub fn args<'b>(&'b self) -> &'b [ast::NestedMetaItem] {
+ pub fn args(&self) -> &[ast::NestedMetaItem] {
self.args_hidden.as_ref().map(|v| &v[..]).unwrap_or(&[])
}
///
/// This is the most general hook into `libsyntax`'s expansion behavior.
pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: SyntaxExtension) {
- if name == sym::macro_rules {
- panic!("user-defined macros may not be named `macro_rules`");
- }
if extension.def_info.is_none() {
extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(in_band_lifetimes)]
let parent_hir_id = tcx.hir().get_parent_node(hir_id);
match tcx.hir().get(parent_hir_id) {
Node::Variant(..) => {
- let parent_did = tcx.hir().local_def_id_from_hir_id(parent_hir_id);
+ let parent_did = tcx.hir().local_def_id(parent_hir_id);
let (mut ctor_vis, mut span, mut descr) = def_id_visibility(
tcx, parent_did,
);
let adt_def = tcx.adt_def(tcx.hir().get_parent_did(hir_id));
- let ctor_did = tcx.hir().local_def_id_from_hir_id(
+ let ctor_did = tcx.hir().local_def_id(
vdata.ctor_hir_id().unwrap());
let variant = adt_def.variant_with_ctor_id(ctor_did);
hir_id: hir::HirId,
empty_tables: &'a ty::TypeckTables<'tcx>,
) -> &'a ty::TypeckTables<'tcx> {
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables }
}
-fn min<'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'tcx>) -> ty::Visibility {
+fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
}
trait VisibilityLike: Sized {
const MAX: Self;
const SHALLOW: bool = false;
- fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self;
+ fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self;
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
// associated types for which we can't determine visibility precisely.
- fn of_impl<'a, 'tcx>(
+ fn of_impl(
hir_id: hir::HirId,
- tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ tcx: TyCtxt<'_>,
+ access_levels: &AccessLevels,
) -> Self {
let mut find = FindMin { tcx, access_levels, min: Self::MAX };
- let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = tcx.hir().local_def_id(hir_id);
find.visit(tcx.type_of(def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref);
}
impl VisibilityLike for ty::Visibility {
const MAX: Self = ty::Visibility::Public;
- fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self {
+ fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx)
}
}
// both "shallow" version of its self type and "shallow" version of its trait if it exists
// (which require reaching the `DefId`s in them).
const SHALLOW: bool = true;
- fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self {
+ fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
cmp::min(if let Some(hir_id) = find.tcx.hir().as_local_hir_id(def_id) {
find.access_levels.map.get(&hir_id).cloned()
} else {
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
- item_def_id: self.tcx.hir().local_def_id_from_hir_id(item_id),
+ item_def_id: self.tcx.hir().local_def_id(item_id),
ev: self,
}
}
if let hir::ItemKind::Mod(m) = &item.node {
for item_id in m.item_ids.as_ref() {
let item = self.tcx.hir().expect_item(item_id.id);
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item_id.id);
+ let def_id = self.tcx.hir().local_def_id(item_id.id);
if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) { continue; }
if let hir::ItemKind::Use(..) = item.node {
self.update(item.hir_id, Some(AccessLevel::Exported));
// This code is here instead of in visit_item so that the
// crate module gets processed as well.
if self.prev_level.is_some() {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = self.tcx.hir().local_def_id(id);
if let Some(exports) = self.tcx.module_exports(def_id) {
for export in exports.iter() {
if export.vis == ty::Visibility::Public {
let module_did = ty::DefIdTree::parent(
self.tcx,
- self.tcx.hir().local_def_id_from_hir_id(md.hir_id)
+ self.tcx.hir().local_def_id(md.hir_id)
).unwrap();
let mut module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
let level = if md.vis.node.is_pub() { self.get(module_id) } else { None };
for id in &module.item_ids {
self.update(id.id, level);
}
- let def_id = self.tcx.hir().local_def_id_from_hir_id(module_id);
+ let def_id = self.tcx.hir().local_def_id(module_id);
if let Some(exports) = self.tcx.module_exports(def_id) {
for export in exports.iter() {
if let Some(hir_id) = self.tcx.hir().as_local_hir_id(export.res.def_id()) {
// Check types in item interfaces.
fn visit_item(&mut self, item: &'tcx hir::Item) {
let orig_current_item = mem::replace(&mut self.current_item,
- self.tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ self.tcx.hir().local_def_id(item.hir_id));
let orig_in_body = mem::replace(&mut self.in_body, false);
let orig_tables =
mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
SearchInterfaceForPrivateItemsVisitor {
tcx: self.tcx,
item_id,
- item_def_id: self.tcx.hir().local_def_id_from_hir_id(item_id),
+ item_def_id: self.tcx.hir().local_def_id(item_id),
span: self.tcx.hir().span(item_id),
required_visibility,
has_pub_restricted: self.has_pub_restricted,
};
}
-fn check_mod_privacy<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: DefId) {
let empty_tables = ty::TypeckTables::empty(None);
// Check privacy of names not checked in previous compilation stages.
intravisit::walk_mod(&mut visitor, module, hir_id);
}
-fn privacy_access_levels<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) -> &'tcx AccessLevels {
+fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels {
assert_eq!(krate, LOCAL_CRATE);
// Build up a set of all exported items in the AST. This is a set of all
tcx.arena.alloc(visitor.access_levels)
}
-fn check_private_in_public<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) {
+fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) {
assert_eq!(krate, LOCAL_CRATE);
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
+#![feature(mem_take)]
#![feature(nll)]
#![feature(rustc_diagnostic_macros)]
-#![feature(type_alias_enum_variants)]
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
pub use rustc::hir::def::{Namespace, PerNS};
///
/// 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>) {
+fn resolve_error(resolver: &Resolver<'_>,
+ span: Span,
+ resolution_error: ResolutionError<'_>) {
resolve_struct_error(resolver, span, resolution_error).emit();
}
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules;
-use syntax::feature_gate::{
- feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES,
-};
+use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
+use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
use syntax::symbol::{Symbol, kw, sym};
use syntax::visit::Visitor;
use syntax::util::lev_distance::find_best_match_for_name;
let res = self.resolve_macro_to_res_inner(path, kind, parent_scope, trace, force);
// Report errors and enforce feature gates for the resolved macro.
+ let features = self.session.features_untracked();
if res != Err(Determinacy::Undetermined) {
// Do not report duplicated errors on every undetermined resolution.
for segment in &path.segments {
if let Some(args) = &segment.args {
self.session.span_err(args.span(), "generic arguments in macro path");
}
+ if kind == MacroKind::Attr && !features.rustc_attrs &&
+ segment.ident.as_str().starts_with("rustc") {
+ let msg = "attributes starting with `rustc` are \
+ reserved for use by the `rustc` compiler";
+ emit_feature_err(
+ &self.session.parse_sess,
+ sym::rustc_attrs,
+ segment.ident.span,
+ GateIssue::Language,
+ msg,
+ );
+ }
}
}
}
Res::NonMacroAttr(attr_kind) => {
if kind == MacroKind::Attr {
- let features = self.session.features_untracked();
if attr_kind == NonMacroAttrKind::Custom {
assert!(path.segments.len() == 1);
- let name = path.segments[0].ident.as_str();
- if name.starts_with("rustc_") {
- if !features.rustc_attrs {
- let msg = "unless otherwise specified, attributes with the prefix \
- `rustc_` are reserved for internal compiler diagnostics";
- self.report_unknown_attribute(path.span, &name, msg,
- sym::rustc_attrs);
- }
- } else if !features.custom_attribute {
+ if !features.custom_attribute {
let msg = format!("The attribute `{}` is currently unknown to the \
compiler and may have meaning added to it in the \
future", path);
self.report_unknown_attribute(
path.span,
- &name,
+ &path.segments[0].ident.as_str(),
&msg,
sym::custom_attribute,
);
};
let macro_resolutions =
- mem::replace(&mut *module.multi_segment_macro_resolutions.borrow_mut(), Vec::new());
+ mem::take(&mut *module.multi_segment_macro_resolutions.borrow_mut());
for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions {
// FIXME: Path resolution will ICE if segment IDs present.
for seg in &mut path { seg.id = None; }
}
let macro_resolutions =
- mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
+ mem::take(&mut *module.single_segment_macro_resolutions.borrow_mut());
for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
&parent_scope, true, true, ident.span) {
}
}
- let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
+ let builtin_attrs = mem::take(&mut *module.builtin_attrs.borrow_mut());
for (ident, parent_scope) in builtin_attrs {
let _ = self.early_resolve_ident_in_lexical_scope(
ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
current_legacy_scope: &mut LegacyScope<'a>) {
self.local_macro_def_scopes.insert(item.id, self.current_module);
let ident = item.ident;
- if ident.name == sym::macro_rules {
- self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
- }
let def_id = self.definitions.local_def_id(item.id);
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
while self.indeterminate_imports.len() < prev_num_indeterminates {
prev_num_indeterminates = self.indeterminate_imports.len();
- for import in mem::replace(&mut self.indeterminate_imports, Vec::new()) {
+ for import in mem::take(&mut self.indeterminate_imports) {
match self.resolve_import(&import) {
true => self.determined_imports.push(import),
false => self.indeterminate_imports.push(import),
where
F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>),
{
- let item_def_id = self.tcx.hir().local_def_id(item_id);
+ let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id);
if self.tcx.has_typeck_tables(item_def_id) {
let tables = self.tcx.typeck_tables_of(item_def_id);
let old_tables = self.save_ctxt.tables;
attrs: &'l [Attribute],
) {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id)));
if !self.span.filter_generated(ident.span) {
let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt);
debug!("process_struct {:?} {:?}", item, item.span);
let name = item.ident.to_string();
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
let kind = match item.node {
ast::ItemKind::Struct(_, _) => DefKind::Struct,
self.process_generic_params(generics, "", item.id);
for impl_item in impl_items {
let map = &self.tcx.hir();
- self.process_impl_item(impl_item, map.local_def_id(item.id));
+ self.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id));
}
}
) {
let name = item.ident.to_string();
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
let mut val = name.clone();
if !generics.params.is_empty() {
val.push_str(&generic_params_to_string(&generics.params));
self.process_generic_params(generics, &qualname, item.id);
for method in methods {
let map = &self.tcx.hir();
- self.process_trait_item(method, map.local_def_id(item.id))
+ self.process_trait_item(method, map.local_def_id_from_node_id(item.id))
}
}
// FIXME do something with _bounds (for type refs)
let name = trait_item.ident.name.to_string();
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(trait_item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(trait_item.id)));
if !self.span.filter_generated(trait_item.ident.span) {
let span = self.span_from_span(trait_item.ident.span);
let access = access_from!(self.save_ctxt, root_item, hir_id);
// The parent `DefId` of a given use tree is always the enclosing item.
- let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id)
+ let parent = self.save_ctxt.tcx.hir().opt_local_def_id_from_node_id(id)
.and_then(|id| self.save_ctxt.tcx.parent(id))
.map(id_from_def_id);
};
// Make a comma-separated list of names of imported modules.
- let def_id = self.tcx.hir().local_def_id(id);
+ let def_id = self.tcx.hir().local_def_id_from_node_id(id);
let names = self.tcx.names_imported_by_glob_use(def_id);
let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();
assert_eq!(id, ast::CRATE_NODE_ID);
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id)));
let cm = self.tcx.sess.source_map();
let filename = cm.span_to_filename(span);
let name_span = item.ident.span;
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
- let parent = self.save_ctxt.tcx.hir().opt_local_def_id(item.id)
+ let parent = self.save_ctxt.tcx.hir().opt_local_def_id_from_node_id(item.id)
.and_then(|id| self.save_ctxt.tcx.parent(id))
.map(id_from_def_id);
self.dumper.import(
}
Ty(ref ty, ref ty_params) => {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
let value = ty_to_string(&ty);
if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span);
}
Existential(ref _bounds, ref ty_params) => {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
// FIXME do something with _bounds
let value = String::new();
if !self.span.filter_generated(item.ident.span) {
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(nll)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![allow(unused_attributes)]
pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
filter!(self.span_utils, item.ident.span);
match item.node {
ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
filter!(self.span_utils, item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::Function,
}
ast::ItemKind::Static(ref typ, ..) => {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
filter!(self.span_utils, item.ident.span);
}
ast::ItemKind::Const(ref typ, _) => {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
filter!(self.span_utils, item.ident.span);
let id = id_from_node_id(item.id, self);
}
ast::ItemKind::Mod(ref m) => {
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
let cm = self.tcx.sess.source_map();
let filename = cm.span_to_filename(m.inner);
ast::ItemKind::Enum(ref def, _) => {
let name = item.ident.to_string();
let qualname = format!("::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id)));
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
filter!(self.span_utils, item.ident.span);
let variants_str = def.variants
.iter()
if let Some(ident) = field.ident {
let name = ident.to_string();
let qualname = format!("::{}::{}",
- self.tcx.def_path_str(self.tcx.hir().local_def_id(scope)),
+ self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(scope)),
ident);
filter!(self.span_utils, ident.span);
- let def_id = self.tcx.hir().local_def_id(field.id);
+ let def_id = self.tcx.hir().local_def_id_from_node_id(field.id);
let typ = self.tcx.type_of(def_id).to_string();
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
let (qualname, parent_scope, decl_id, docs, attributes) =
- match self.tcx.impl_of_method(self.tcx.hir().local_def_id(id)) {
+ match self.tcx.impl_of_method(self.tcx.hir().local_def_id_from_node_id(id)) {
Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
Some(Node::Item(item)) => match item.node {
hir::ItemKind::Impl(.., ref ty, _) => {
);
}
},
- None => match self.tcx.trait_of_item(self.tcx.hir().local_def_id(id)) {
+ None => match self.tcx.trait_of_item(self.tcx.hir().local_def_id_from_node_id(id)) {
Some(def_id) => {
let mut docs = String::new();
let mut attrs = vec![];
}
fn id_from_node_id(id: NodeId, scx: &SaveContext<'_, '_>) -> rls_data::Id {
- let def_id = scx.tcx.hir().opt_local_def_id(id);
+ let def_id = scx.tcx.hir().opt_local_def_id_from_node_id(id);
def_id.map(|id| id_from_def_id(id)).unwrap_or_else(|| {
// Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId`
// out of the maximum u32 value. This will work unless you have *billions*
target
}
+const MAX_INT_REGS: usize = 6; // RDI, RSI, RDX, RCX, R8, R9
+const MAX_SSE_REGS: usize = 8; // XMM0-7
+
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
- let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
- let mut sse_regs = 8; // XMM0-7
+ let mut int_regs = MAX_INT_REGS;
+ let mut sse_regs = MAX_SSE_REGS;
let mut x86_64_ty = |arg: &mut ArgType<'a, Ty>, is_arg: bool| {
let mut cls_or_mem = classify_arg(cx, arg);
- let mut needed_int = 0;
- let mut needed_sse = 0;
if is_arg {
if let Ok(cls) = cls_or_mem {
+ let mut needed_int = 0;
+ let mut needed_sse = 0;
for &c in &cls {
match c {
Some(Class::Int) => needed_int += 1,
_ => {}
}
}
- if arg.layout.is_aggregate() && (int_regs < needed_int || sse_regs < needed_sse) {
- cls_or_mem = Err(Memory);
+ match (int_regs.checked_sub(needed_int), sse_regs.checked_sub(needed_sse)) {
+ (Some(left_int), Some(left_sse)) => {
+ int_regs = left_int;
+ sse_regs = left_sse;
+ }
+ _ => {
+ // Not enough registers for this argument, so it will be
+ // passed on the stack, but we only mark aggregates
+ // explicitly as indirect `byval` arguments, as LLVM will
+ // automatically put immediates on the stack itself.
+ if arg.layout.is_aggregate() {
+ cls_or_mem = Err(Memory);
+ }
+ }
}
}
}
} else {
// `sret` parameter thus one less integer register available
arg.make_indirect();
+ // NOTE(eddyb) return is handled first, so no registers
+ // should've been used yet.
+ assert_eq!(int_regs, MAX_INT_REGS);
int_regs -= 1;
}
}
Ok(ref cls) => {
// split into sized chunks passed individually
- int_regs -= needed_int;
- sse_regs -= needed_sse;
-
if arg.layout.is_aggregate() {
let size = arg.layout.size;
arg.cast_to(cast_target(cls, size))
#![feature(step_trait)]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use] extern crate log;
target_family: Some("windows".to_string()),
is_like_windows: true,
is_like_msvc: true,
+ // set VSLANG to 1033 can prevent link.exe from using
+ // language packs, and avoid generating Non-UTF-8 error
+ // messages if a link error occurred.
+ link_env: vec![("VSLANG".to_string(), "1033".to_string())],
pre_link_args: args,
crt_static_allows_dylibs: true,
crt_static_respected: true,
CanonicalVarValues,
OriginalQueryValues,
QueryResponse,
+ QueryRegionConstraints,
Certainty,
};
use rustc::traits::{
let solution = constrained_subst.unchecked_map(|cs| match ambiguous {
true => QueryResponse {
var_values: cs.subst.make_identity(self.tcx),
- region_constraints: Vec::new(),
+ region_constraints: QueryRegionConstraints::default(),
certainty: Certainty::Ambiguous,
value: (),
},
false => QueryResponse {
var_values: cs.subst,
- region_constraints: Vec::new(),
+ region_constraints: QueryRegionConstraints::default(),
// FIXME: restore this later once we get better at handling regions
// region_constraints: cs.constraints
use crate::generic_types;
use std::iter;
-crate fn wf_clause_for_raw_ptr<'tcx>(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Clauses<'tcx> {
+crate fn wf_clause_for_raw_ptr(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
let wf_clause = ProgramClause {
tcx.mk_clauses(iter::once(wf_clause))
}
-crate fn wf_clause_for_fn_ptr<'tcx>(
- tcx: TyCtxt<'tcx>,
+crate fn wf_clause_for_fn_ptr(
+ tcx: TyCtxt<'_>,
arity_and_output: usize,
variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi,
-) -> Clauses<'tcx> {
+) -> Clauses<'_> {
let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
let wf_clause = ProgramClause {
tcx.mk_clauses(iter::once(wf_clause))
}
-crate fn wf_clause_for_slice<'tcx>(tcx: TyCtxt<'tcx>) -> Clauses<'tcx> {
+crate fn wf_clause_for_slice(tcx: TyCtxt<'_>) -> Clauses<'_> {
let ty = generic_types::bound(tcx, 0);
let slice_ty = tcx.mk_slice(ty);
tcx.mk_clauses(iter::once(wf_clause))
}
-crate fn wf_clause_for_tuple<'tcx>(tcx: TyCtxt<'tcx>, arity: usize) -> Clauses<'tcx> {
+crate fn wf_clause_for_tuple(tcx: TyCtxt<'_>, arity: usize) -> Clauses<'_> {
let type_list = generic_types::type_list(tcx, arity);
let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
tcx.mk_clauses(iter::once(wf_clause))
}
-crate fn wf_clause_for_ref<'tcx>(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Clauses<'tcx> {
+crate fn wf_clause_for_ref(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
let region = tcx.mk_region(
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
);
tcx.mk_clauses(iter::once(wf_clause))
}
-crate fn wf_clause_for_fn_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+crate fn wf_clause_for_fn_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
let fn_def = generic_types::fn_def(tcx, def_id);
let wf_clause = ProgramClause {
}
/// Calculates the dtorck constraint for a type.
-crate fn adt_dtorck_constraint<'tcx>(
- tcx: TyCtxt<'tcx>,
+crate fn adt_dtorck_constraint(
+ tcx: TyCtxt<'_>,
def_id: DefId,
-) -> Result<DtorckConstraint<'tcx>, NoSolution> {
+) -> Result<DtorckConstraint<'_>, NoSolution> {
let def = tcx.adt_def(def_id);
let span = tcx.def_span(def_id);
debug!("dtorck_constraint: {:?}", def);
Ok(result)
}
-fn dedup_dtorck_constraint<'tcx>(c: &mut DtorckConstraint<'tcx>) {
+fn dedup_dtorck_constraint(c: &mut DtorckConstraint<'_>) {
let mut outlives = FxHashSet::default();
let mut dtorck_types = FxHashSet::default();
//! the guts are broken up into modules; see the comments in those modules.
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(crate_visibility_modifier)]
);
}
-crate fn environment<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Environment<'tcx> {
+crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> {
use super::{Lower, IntoFromEnvGoal};
use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
}
}
-crate fn program_clauses_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+crate fn program_clauses_for(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
// FIXME(eddyb) this should only be using `def_kind`.
match tcx.def_key(def_id).disambiguated_data.data {
DefPathData::TypeNs(..) => match tcx.def_kind(def_id) {
}
}
-fn program_clauses_for_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
// `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
// Rule Implemented-From-Env (see rustc guide)
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::bind(clause))))
}
-pub fn program_clauses_for_type_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+pub fn program_clauses_for_type_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
// Rule WellFormed-Type
//
// `struct Ty<P1..Pn> where WC1, ..., WCm`
tcx.mk_clauses(iter::once(well_formed_clause).chain(from_env_clauses))
}
-pub fn program_clauses_for_associated_type_def<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn program_clauses_for_associated_type_def(
+ tcx: TyCtxt<'_>,
item_id: DefId,
-) -> Clauses<'tcx> {
+) -> Clauses<'_> {
// Rule ProjectionEq-Placeholder
//
// ```
tcx.mk_clauses(clauses)
}
-pub fn program_clauses_for_associated_type_value<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn program_clauses_for_associated_type_value(
+ tcx: TyCtxt<'_>,
item_id: DefId,
-) -> Clauses<'tcx> {
+) -> Clauses<'_> {
// Rule Normalize-From-Impl (see rustc guide)
//
// ```
tcx.mk_clauses(iter::once(normalize_clause))
}
-pub fn dump_program_clauses<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn dump_program_clauses(tcx: TyCtxt<'_>) {
if !tcx.features().rustc_attrs {
return;
}
impl ClauseDumper<'tcx> {
fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(hir_id);
+ let def_id = self.tcx.hir().local_def_id(hir_id);
for attr in attrs {
let mut clauses = None;
use crate::hir::def::{CtorOf, Res, DefKind};
use crate::hir::def_id::DefId;
use crate::hir::HirVec;
+use crate::hir::ptr::P;
use crate::lint;
use crate::middle::lang_items::SizedTraitLangItem;
use crate::middle::resolve_lifetime as rl;
use smallvec::SmallVec;
use syntax::ast;
use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::ptr::P;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::symbol::sym;
use syntax_pos::{DUMMY_SP, Span, MultiSpan};
use std::iter;
use std::slice;
-use super::{check_type_alias_enum_variants_enabled};
use rustc_data_structures::fx::FxHashSet;
#[derive(Debug)]
});
if let Some(variant_def) = variant_def {
if permit_variants {
- check_type_alias_enum_variants_enabled(tcx, span);
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
} else {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item_id = tcx.hir().get_parent_node(hir_id);
- let item_def_id = tcx.hir().local_def_id_from_hir_id(item_id);
+ let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
tcx.mk_ty_param(index, tcx.hir().name(hir_id).as_interned_str())
self.res_to_ty(opt_self_ty, path, false)
}
hir::TyKind::Def(item_id, ref lifetimes) => {
- let did = tcx.hir().local_def_id_from_hir_id(item_id.id);
+ let did = tcx.hir().local_def_id(item_id.id);
self.impl_trait_ty_to_ty(did, lifetimes)
}
hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);
let tcx = self.tcx();
- let def_id = tcx.hir().local_def_id_from_hir_id(ast_const.hir_id);
+ let def_id = tcx.hir().local_def_id(ast_const.hir_id);
let mut const_ = ty::Const {
val: ConstValue::Unevaluated(
// parent item and construct a `ParamConst`.
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item_id = tcx.hir().get_parent_node(hir_id);
- let item_def_id = tcx.hir().local_def_id_from_hir_id(item_id);
+ let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
- let index = generics.param_def_id_to_index[&tcx.hir().local_def_id_from_hir_id(hir_id)];
+ let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)];
let name = tcx.hir().name(hir_id).as_interned_str();
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
}
use rustc::hir::{self, PatKind, Pat, ExprKind};
use rustc::hir::def::{Res, DefKind, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
+use rustc::hir::ptr::P;
use rustc::infer;
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::traits::{ObligationCause, ObligationCauseCode};
use rustc::ty::subst::Kind;
use syntax::ast;
use syntax::source_map::Spanned;
-use syntax::ptr::P;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::Span;
use syntax_pos::hygiene::CompilerDesugaringKind;
match ty.sty {
ty::Array(..) | ty::Slice(..) => {
err.help("the semantics of slice patterns changed \
- recently; see issue #23121");
+ recently; see issue #62254");
}
_ => {}
}
opt_kind, expected_sig
);
- let expr_def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
+ let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id);
let ClosureSignatures {
bound_sig,
use errors::DiagnosticBuilder;
use rustc::hir;
use rustc::hir::def_id::DefId;
+use rustc::hir::ptr::P;
use rustc::infer::{Coercion, InferResult, InferOk};
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use smallvec::{smallvec, SmallVec};
use std::ops::Deref;
use syntax::feature_gate;
-use syntax::ptr::P;
use syntax::symbol::sym;
use syntax_pos;
/// struct/enum definition for the nominal type itself (i.e.
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
-pub fn check_drop_impl<'tcx>(tcx: TyCtxt<'tcx>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
+pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
let dtor_self_type = tcx.type_of(drop_impl_did);
let dtor_predicates = tcx.predicates_of(drop_impl_did);
match dtor_self_type.sty {
use errors::{Applicability, DiagnosticBuilder};
use syntax::ast;
-use syntax::ptr::P;
use syntax::symbol::{Symbol, LocalInternedString, kw, sym};
use syntax::source_map::Span;
use syntax::util::lev_distance::find_best_match_for_name;
use rustc::hir;
use rustc::hir::{ExprKind, QPath};
use rustc::hir::def::{CtorKind, Res, DefKind};
+use rustc::hir::ptr::P;
use rustc::infer;
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::mir::interpret::GlobalId;
expr: &'tcx hir::Expr,
) -> Ty<'tcx> {
let tcx = self.tcx;
- let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
+ let count_def_id = tcx.hir().local_def_id(count.hir_id);
let count = if self.const_param_def_id(count).is_some() {
Ok(self.to_const(count, tcx.type_of(count_def_id)))
} else {
// If unresolved type isn't a ty_var then unresolved_type_span is None
self.fcx.need_type_info_err_in_generator(
self.kind,
- unresolved_type_span.unwrap_or(yield_data.span),
+ unresolved_type_span.unwrap_or(source_span),
unresolved_type,
)
.span_note(yield_data.span, &*note)
inputs: Vec<Ty<'tcx>>,
output: Ty<'tcx>,
) {
- let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = tcx.hir().local_def_id(it.hir_id);
match it.node {
hir::ForeignItemKind::Fn(..) => {}
/// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
/// and in libcore/intrinsics.rs
-pub fn check_intrinsic_type<'tcx>(tcx: TyCtxt<'tcx>, it: &hir::ForeignItem) {
+pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n)));
let name = it.ident.as_str();
"rustc_peek" => (1, vec![param(0)], param(0)),
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
"init" => (1, Vec::new(), param(0)),
- "uninit" => (1, Vec::new(), param(0)),
"forget" => (1, vec![param(0)], tcx.mk_unit()),
"transmute" => (2, vec![ param(0) ], param(1)),
"move_val_init" => {
}
/// Type-check `extern "platform-intrinsic" { ... }` functions.
-pub fn check_platform_intrinsic_type<'tcx>(tcx: TyCtxt<'tcx>, it: &hir::ForeignItem) {
+pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
let param = |n| {
let name = InternedString::intern(&format!("P{}", n));
tcx.mk_ty_param(n, name)
use syntax::ast;
use syntax_pos::Span;
-use crate::{check_type_alias_enum_variants_enabled};
use self::probe::{IsSuggestion, ProbeScope};
pub fn provide(providers: &mut ty::query::Providers<'_>) {
)?;
for import_id in &pick.import_ids {
- let import_def_id = self.tcx.hir().local_def_id_from_hir_id(*import_id);
+ let import_def_id = self.tcx.hir().local_def_id(*import_id);
debug!("used_trait_import: {:?}", import_def_id);
Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
.unwrap().insert(import_def_id);
tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
});
if let Some(variant_def) = variant_def {
- check_type_alias_enum_variants_enabled(tcx, span);
-
// Braced variants generate unusable names in value namespace (reserved for
// possible future use), so variants resolved as associated items may refer to
// them as well. It's ok to use the variant's id as a ctor id since an
self_ty, expr_id, ProbeScope::TraitsInScope)?;
debug!("resolve_ufcs: pick={:?}", pick);
for import_id in pick.import_ids {
- let import_def_id = tcx.hir().local_def_id_from_hir_id(import_id);
+ let import_def_id = tcx.hir().local_def_id(import_id);
debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
.unwrap().insert(import_def_id);
debug!("pick: actual search failed, assemble diagnotics");
- let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
+ let static_candidates = mem::take(&mut self.static_candidates);
let private_candidate = self.private_candidate.take();
- let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]);
+ let unsatisfied_predicates = mem::take(&mut self.unsatisfied_predicates);
// things failed, so lets look at all traits, for diagnostic purposes now:
self.reset();
}
/// Retrieves all traits in this crate and any dependent crates.
-pub fn all_traits<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<TraitInfo> {
+pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
}
/// Computes all traits in this crate and any dependent crates.
-fn compute_all_traits<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<DefId> {
+fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
use hir::itemlikevisit;
let mut traits = vec![];
match i.node {
hir::ItemKind::Trait(..) |
hir::ItemKind::TraitAlias(..) => {
- let def_id = self.map.local_def_id_from_hir_id(i.hir_id);
+ let def_id = self.map.local_def_id(i.hir_id);
self.traits.push(def_id);
}
_ => ()
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::ptr::P;
use crate::middle::lang_items;
use crate::namespace::Namespace;
use rustc::infer::{self, InferCtxt, InferOk, InferResult};
use syntax::ast;
use syntax::attr;
use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::ptr::P;
use syntax::source_map::{DUMMY_SP, original_sp};
use syntax::symbol::{kw, sym};
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
}
-pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_wf_new(tcx: TyCtxt<'_>) {
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
}
-fn check_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
}
-fn typeck_item_bodies<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) {
+fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) {
debug_assert!(crate_num == LOCAL_CRATE);
tcx.par_body_owners(|body_owner_def_id| {
tcx.ensure().typeck_tables_of(body_owner_def_id);
});
}
-fn check_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
wfcheck::check_item_well_formed(tcx, def_id);
}
-fn check_trait_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn check_trait_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
wfcheck::check_trait_item(tcx, def_id);
}
-fn check_impl_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn check_impl_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
wfcheck::check_impl_item(tcx, def_id);
}
};
}
-fn adt_destructor<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<ty::Destructor> {
+fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl)
}
/// may not succeed. In some cases where this function returns `None`
/// (notably closures), `typeck_tables(def_id)` would wind up
/// redirecting to the owning function.
-fn primary_body_of<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn primary_body_of(
+ tcx: TyCtxt<'_>,
id: hir::HirId,
-) -> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)> {
+) -> Option<(hir::BodyId, Option<&hir::FnDecl>)> {
match tcx.hir().get(id) {
Node::Item(item) => {
match item.node {
}
}
-fn has_typeck_tables<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// Closures' tables come from their outermost function,
// as they are part of the same "inference environment".
let outer_def_id = tcx.closure_base_def_id(def_id);
primary_body_of(tcx, id).is_some()
}
-fn used_trait_imports<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx DefIdSet {
+fn used_trait_imports(tcx: TyCtxt<'_>, def_id: DefId) -> &DefIdSet {
&*tcx.typeck_tables_of(def_id).used_trait_imports
}
-fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::TypeckTables<'tcx> {
+fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
// Closures' tables come from their outermost function,
// as they are part of the same "inference environment".
let outer_def_id = tcx.closure_base_def_id(def_id);
let revealed_ty = if tcx.features().impl_trait_in_bindings {
fcx.instantiate_opaque_types_from_value(
id,
- &expected_type
+ &expected_type,
+ body.value.span,
)
} else {
expected_type
tables
}
-fn check_abi<'tcx>(tcx: TyCtxt<'tcx>, span: Span, abi: Abi) {
+fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
if !tcx.sess.target.target.is_abi_supported(abi) {
struct_span_err!(tcx.sess, span, E0570,
"The ABI `{}` is not supported for the current target", abi).emit()
let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings {
self.fcx.instantiate_opaque_types_from_value(
self.parent_id,
- &o_ty
+ &o_ty,
+ ty.span,
)
} else {
o_ty
let declared_ret_ty = fn_sig.output();
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
- let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(fn_id, &declared_ret_ty);
+ let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(
+ fn_id,
+ &declared_ret_ty,
+ decl.output.span(),
+ );
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
fn_sig = fcx.tcx.mk_fn_sig(
fn_sig.inputs().iter().cloned(),
fcx.yield_ty = Some(yield_ty);
}
- let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir().local_def_id_from_hir_id(fn_id));
+ let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir().local_def_id(fn_id));
let outer_hir_id = fcx.tcx.hir().as_local_hir_id(outer_def_id).unwrap();
GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id, }.visit_body(body);
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
- if panic_impl_did == fcx.tcx.hir().local_def_id_from_hir_id(fn_id) {
+ if panic_impl_did == fcx.tcx.hir().local_def_id(fn_id) {
if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
// at this point we don't care if there are duplicate handlers or if the handler has
// the wrong signature as this value we'll be used when writing metadata and that
// Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() {
- if alloc_error_handler_did == fcx.tcx.hir().local_def_id_from_hir_id(fn_id) {
+ if alloc_error_handler_did == fcx.tcx.hir().local_def_id(fn_id) {
if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() {
if declared_ret_ty.sty != ty::Never {
fcx.tcx.sess.span_err(
(fcx, gen_ty)
}
-fn check_struct<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) {
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+fn check_struct(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
+ let def_id = tcx.hir().local_def_id(id);
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
check_packed(tcx, span, def_id);
}
-fn check_union<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) {
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
+ let def_id = tcx.hir().local_def_id(id);
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
debug!(
"check_item_type(it.hir_id={}, it.name={})",
it.hir_id,
- tcx.def_path_str(tcx.hir().local_def_id_from_hir_id(it.hir_id))
+ tcx.def_path_str(tcx.hir().local_def_id(it.hir_id))
);
let _indenter = indenter();
match it.node {
// Consts can play a role in type-checking, so they are included here.
hir::ItemKind::Static(..) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = tcx.hir().local_def_id(it.hir_id);
tcx.typeck_tables_of(def_id);
maybe_check_static_with_link_section(tcx, def_id, it.span);
}
hir::ItemKind::Const(..) => {
- tcx.typeck_tables_of(tcx.hir().local_def_id_from_hir_id(it.hir_id));
+ tcx.typeck_tables_of(tcx.hir().local_def_id(it.hir_id));
}
hir::ItemKind::Enum(ref enum_definition, _) => {
check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
hir::ItemKind::Fn(..) => {} // entirely within check_item_body
hir::ItemKind::Impl(.., ref impl_item_refs) => {
debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
- let impl_def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let impl_def_id = tcx.hir().local_def_id(it.hir_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
check_impl_items_against_trait(
tcx,
}
}
hir::ItemKind::Trait(..) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = tcx.hir().local_def_id(it.hir_id);
check_on_unimplemented(tcx, def_id, it);
}
hir::ItemKind::Struct(..) => {
check_union(tcx, it.hir_id, it.span);
}
hir::ItemKind::Existential(..) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = tcx.hir().local_def_id(it.hir_id);
let substs = InternalSubsts::identity_for_item(tcx, def_id);
check_opaque(tcx, def_id, substs, it.span);
}
hir::ItemKind::Ty(..) => {
- let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = tcx.hir().local_def_id(it.hir_id);
let pty_ty = tcx.type_of(def_id);
let generics = tcx.generics_of(def_id);
check_bounds_are_used(tcx, &generics, pty_ty);
}
} else {
for item in &m.items {
- let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(item.hir_id));
+ let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
if generics.params.len() - generics.own_counts().lifetimes != 0 {
let mut err = struct_span_err!(
tcx.sess,
}
}
-fn check_on_unimplemented<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, item: &hir::Item) {
- let item_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
+fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item) {
+ let item_def_id = tcx.hir().local_def_id(item.hir_id);
// an error would be reported if this fails.
let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id);
}
-fn report_forbidden_specialization<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn report_forbidden_specialization(
+ tcx: TyCtxt<'_>,
impl_item: &hir::ImplItem,
parent_impl: DefId,
) {
// and compatible with trait signature
for impl_item in impl_items() {
let ty_impl_item = tcx.associated_item(
- tcx.hir().local_def_id_from_hir_id(impl_item.hir_id));
+ tcx.hir().local_def_id(impl_item.hir_id));
let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id)
.find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) &&
tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id))
/// Checks whether a type can be represented in memory. In particular, it
/// identifies types that contain themselves without indirection through a
/// pointer, which would mean their size is unbounded.
-fn check_representable<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, item_def_id: DefId) -> bool {
+fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: DefId) -> bool {
let rty = tcx.type_of(item_def_id);
// Check that it is possible to represent this type. This call identifies
return true;
}
-pub fn check_simd<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
+pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
let t = tcx.type_of(def_id);
if let ty::Adt(def, substs) = t.sty {
if def.is_struct() {
}
}
-fn check_packed<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
+fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
let repr = tcx.adt_def(def_id).repr;
if repr.packed() {
for attr in tcx.get_attrs(def_id).iter() {
}
}
-fn check_packed_inner<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
+fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
let t = tcx.type_of(def_id);
if stack.contains(&def_id) {
debug!("check_packed_inner: {:?} is recursive", t);
err.emit();
}
-fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
+fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
let adt = tcx.adt_def(def_id);
if !adt.repr.transparent() {
return;
#[allow(trivial_numeric_casts)]
pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], id: hir::HirId) {
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
for v in vs {
if let Some(ref e) = v.node.disr_expr {
- tcx.typeck_tables_of(tcx.hir().local_def_id_from_hir_id(e.hir_id));
+ tcx.typeck_tables_of(tcx.hir().local_def_id(e.hir_id));
}
}
check_transparent(tcx, sp, def_id);
}
-fn report_unexpected_variant_res<'tcx>(tcx: TyCtxt<'tcx>, res: Res, span: Span, qpath: &QPath) {
+fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &QPath) {
span_err!(tcx.sess, span, E0533,
"expected unit struct/variant or constant, found {} `{}`",
res.descr(),
let tcx = self.tcx;
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item_id = tcx.hir().ty_param_owner(hir_id);
- let item_def_id = tcx.hir().local_def_id_from_hir_id(item_id);
+ let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
tcx.arena.alloc(ty::GenericPredicates {
&self,
parent_id: hir::HirId,
value: &T,
+ value_span: Span,
) -> T {
- let parent_def_id = self.tcx.hir().local_def_id_from_hir_id(parent_id);
+ let parent_def_id = self.tcx.hir().local_def_id(parent_id);
debug!("instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})",
parent_def_id,
value);
self.body_id,
self.param_env,
value,
+ value_span,
)
);
/// types from which we should derive implied bounds, if any.
pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
- let subject = self.tcx.hir().local_def_id_from_hir_id(item_id);
+ let subject = self.tcx.hir().local_def_id(item_id);
let mut rcx = RegionCtxt::new(
self,
RepeatingScope(item_id),
// This may change if abstract return types of some sort are
// implemented.
let tcx = self.tcx;
- let closure_def_id = tcx.hir().local_def_id_from_hir_id(closure_id);
+ let closure_def_id = tcx.hir().local_def_id(closure_id);
tcx.upvars(closure_def_id).iter().flat_map(|upvars| {
upvars
use crate::hir::def_id::DefId;
use rustc::traits::{self, ObligationCauseCode};
-use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
+use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::mir::interpret::ConstValue;
/// 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<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item = tcx.hir().expect_item(hir_id);
// won't be allowed unless there's an *explicit* implementation of `Send`
// for `T`
hir::ItemKind::Impl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
- let is_auto = tcx.impl_trait_ref(tcx.hir().local_def_id_from_hir_id(item.hir_id))
+ let is_auto = tcx.impl_trait_ref(tcx.hir().local_def_id(item.hir_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");
}
}
-pub fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let trait_item = tcx.hir().expect_trait_item(hir_id);
check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
}
-pub fn check_impl_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let impl_item = tcx.hir().expect_impl_item(hir_id);
check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
}
-fn check_associated_item<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn check_associated_item(
+ tcx: TyCtxt<'_>,
item_id: hir::HirId,
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_from_hir_id(item_id));
+ 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()),
for_id(tcx, item.hir_id, item.span)
}
-fn for_id<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'tcx> {
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> {
+ let def_id = tcx.hir().local_def_id(id);
CheckWfFcxBuilder {
inherited: Inherited::build(tcx, def_id),
id,
{
for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
let variants = lookup_fields(fcx);
- let def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = fcx.tcx.hir().local_def_id(item.hir_id);
let packed = fcx.tcx.adt_def(def_id).repr.packed();
for variant in &variants {
let needs_drop_copy = || {
packed && {
let ty = variant.fields.last().unwrap().ty;
- fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx)
- .map(|ty| ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)))
- .unwrap_or_else(|| {
+ let ty = fcx.tcx.erase_regions(&ty);
+ if ty.has_local_value() {
fcx_tcx.sess.delay_span_bug(
item.span, &format!("inference variables in {:?}", ty));
// Just treat unresolved type expression as if it needs drop.
true
- })
+ } else {
+ ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
+ }
}
};
let all_sized =
});
}
-fn check_trait<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) {
+fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item) {
debug!("check_trait: {:?}", item.hir_id);
- let trait_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let trait_def_id = tcx.hir().local_def_id(item.hir_id);
let trait_def = tcx.trait_def(trait_def_id);
if trait_def.is_marker {
});
}
-fn check_item_fn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) {
+fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item) {
for_item(tcx, item).with_fcx(|fcx, tcx| {
- let def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = fcx.tcx.hir().local_def_id(item.hir_id);
let sig = fcx.tcx.fn_sig(def_id);
let sig = fcx.normalize_associated_types_in(item.span, &sig);
let mut implied_bounds = vec![];
})
}
-fn check_item_type<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn check_item_type(
+ tcx: TyCtxt<'_>,
item_id: hir::HirId,
ty_span: Span,
allow_foreign_ty: bool,
debug!("check_item_type: {:?}", item_id);
for_id(tcx, item_id, ty_span).with_fcx(|fcx, gcx| {
- let ty = gcx.type_of(gcx.hir().local_def_id_from_hir_id(item_id));
+ let ty = gcx.type_of(gcx.hir().local_def_id(item_id));
let item_ty = fcx.normalize_associated_types_in(ty_span, &ty);
let mut forbid_unsized = true;
debug!("check_impl: {:?}", item);
for_item(tcx, item).with_fcx(|fcx, tcx| {
- let item_def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let item_def_id = fcx.tcx.hir().local_def_id(item.hir_id);
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
item: &hir::Item,
hir_generics: &hir::Generics,
) {
- let item_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let item_def_id = tcx.hir().local_def_id(item.hir_id);
let ty = tcx.type_of(item_def_id);
if tcx.has_error_field(ty) {
return;
}
}
-fn report_bivariance<'tcx>(tcx: TyCtxt<'tcx>, span: Span, param_name: ast::Name) {
+fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) {
let mut err = error_392(tcx, span, param_name);
let suggested_marker_id = tcx.lang_items().phantom_data();
/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
/// aren't true.
-fn check_false_global_bounds<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, id: hir::HirId) {
+fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
let empty_env = ty::ParamEnv::empty();
- let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = fcx.tcx.hir().local_def_id(id);
let predicates = fcx.tcx.predicates_of(def_id).predicates
.iter()
.map(|(p, _)| *p)
impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
fn visit_item(&self, i: &'tcx hir::Item) {
debug!("visit_item: {:?}", i);
- let def_id = self.tcx.hir().local_def_id_from_hir_id(i.hir_id);
+ let def_id = self.tcx.hir().local_def_id(i.hir_id);
self.tcx.ensure().check_item_well_formed(def_id);
}
fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem) {
debug!("visit_trait_item: {:?}", trait_item);
- let def_id = self.tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
self.tcx.ensure().check_trait_item_well_formed(def_id);
}
fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem) {
debug!("visit_impl_item: {:?}", impl_item);
- let def_id = self.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(impl_item.hir_id);
self.tcx.ensure().check_impl_item_well_formed(def_id);
}
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
let fields = struct_def.fields().iter().map(|field| {
- let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id_from_hir_id(field.hir_id));
+ let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.hir_id));
let field_ty = self.normalize_associated_types_in(field.span,
&field_ty);
+ let field_ty = self.resolve_vars_if_possible(&field_ty);
+ debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
AdtField { ty: field_ty, span: field.span }
})
.collect();
}
}
-fn error_392<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn error_392(
+ tcx: TyCtxt<'_>,
span: Span,
param_name: ast::Name,
-) -> DiagnosticBuilder<'tcx> {
+) -> DiagnosticBuilder<'_> {
let mut err = struct_span_err!(tcx.sess, span, E0392,
"parameter `{}` is never used", param_name);
err.span_label(span, "unused parameter");
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn resolve_type_vars_in_body(&self, body: &'tcx hir::Body) -> &'tcx ty::TypeckTables<'tcx> {
let item_id = self.tcx.hir().body_owner(body.id());
- let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item_id);
+ let item_def_id = self.tcx.hir().local_def_id(item_id);
// This attribute causes us to dump some writeback information
// in the form of errors, which is uSymbolfor unit tests.
}
fn visit_free_region_map(&mut self) {
- let free_region_map = self.tcx()
- .lift_to_global(&self.fcx.tables.borrow().free_region_map);
- let free_region_map = free_region_map.expect("all regions in free-region-map are global");
- self.tables.free_region_map = free_region_map;
+ self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
+ debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value()));
}
fn visit_user_provided_tys(&mut self) {
local_id,
};
- let c_ty = if let Some(c_ty) = self.tcx().lift_to_global(c_ty) {
- c_ty
- } else {
+ if cfg!(debug_assertions) && c_ty.has_local_value() {
span_bug!(
hir_id.to_span(self.fcx.tcx),
- "writeback: `{:?}` missing from the global type context",
+ "writeback: `{:?}` is a local value",
c_ty
);
};
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() {
- let c_sig = if let Some(c_sig) = self.tcx().lift_to_global(c_sig) {
- c_sig
- } else {
+ if cfg!(debug_assertions) && c_sig.has_local_value() {
span_bug!(
self.fcx.tcx.hir().span_if_local(def_id).unwrap(),
- "writeback: `{:?}` missing from the global type context",
+ "writeback: `{:?}` is a local value",
c_sig
);
};
}
}
- if let Some(substs) = self.tcx().lift_to_global(&opaque_defn.substs) {
+ if !opaque_defn.substs.has_local_value() {
let new = ty::ResolvedOpaqueTy {
concrete_type: definition_ty,
- substs,
+ substs: opaque_defn.substs,
};
let old = self.tables
} else {
self.tcx().sess.delay_span_bug(
span,
- "cannot lift `opaque_defn` substs to global type context",
+ "`opaque_defn` is a local value",
);
}
}
}
}
- fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T::Lifted
+ fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T
where
- T: TypeFoldable<'tcx> + ty::Lift<'tcx>,
+ T: TypeFoldable<'tcx>,
{
let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
- if let Some(lifted) = self.tcx().lift_to_global(&x) {
- lifted
- } else {
+ if cfg!(debug_assertions) && x.has_local_value() {
span_bug!(
span.to_span(self.fcx.tcx),
- "writeback: `{:?}` missing from the global type context",
+ "writeback: `{:?}` is a local value",
x
);
}
+ x
}
}
use rustc_data_structures::fx::FxHashMap;
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_crate(tcx: TyCtxt<'_>) {
let mut used_trait_imports = DefIdSet::default();
for &body_id in tcx.hir().krate().bodies.keys() {
let item_def_id = tcx.hir().body_owner_def_id(body_id);
impl CheckVisitor<'tcx> {
fn check_import(&self, id: hir::HirId, span: Span) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = self.tcx.hir().local_def_id(id);
if !self.tcx.maybe_unused_trait_import(def_id) {
return;
}
}
}
-fn unused_crates_lint<'tcx>(tcx: TyCtxt<'tcx>) {
+fn unused_crates_lint(tcx: TyCtxt<'_>) {
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
// Collect first the crates that are completely unused. These we
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if let hir::ItemKind::ExternCrate(orig_name) = item.node {
- let extern_crate_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let extern_crate_def_id = self.tcx.hir().local_def_id(item.hir_id);
self.crates_to_lint.push(
ExternCrateToLint {
def_id: extern_crate_def_id,
use hir::Node;
use rustc::hir::{self, ItemKind};
-pub fn check_trait<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) {
+pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
Checker { tcx, trait_def_id }
.check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
.check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
{
if Some(self.trait_def_id) == trait_def_id {
for &impl_id in self.tcx.hir().trait_impls(self.trait_def_id) {
- let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(impl_id);
+ let impl_def_id = self.tcx.hir().local_def_id(impl_id);
f(self.tcx, impl_def_id);
}
}
}
}
-fn visit_implementation_of_drop<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
+fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) {
if let ty::Adt(..) = tcx.type_of(impl_did).sty {
/* do nothing */
} else {
}
}
-fn visit_implementation_of_copy<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
+fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) {
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
let impl_hir_id = if let Some(n) = tcx.hir().as_local_hir_id(impl_did) {
}
}
-fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
+fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}",
impl_did);
if impl_did.is_local() {
//! `tcx.inherent_impls(def_id)`). That value, however,
//! is computed by selecting an idea from this table.
-use rustc::dep_graph::DepKind;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use syntax_pos::Span;
/// On-demand query: yields a map containing all types mapped to their inherent impls.
-pub fn crate_inherent_impls<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn crate_inherent_impls(
+ tcx: TyCtxt<'_>,
crate_num: CrateNum,
-) -> &'tcx CrateInherentImpls {
+) -> &CrateInherentImpls {
assert_eq!(crate_num, LOCAL_CRATE);
let krate = tcx.hir().krate();
}
/// On-demand query: yields a vector of the inherent impls for a specific type.
-pub fn inherent_impls<'tcx>(tcx: TyCtxt<'tcx>, ty_def_id: DefId) -> &'tcx [DefId] {
+pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
assert!(ty_def_id.is_local());
- // NB. Until we adopt the red-green dep-tracking algorithm (see
- // [the plan] for details on that), we do some hackery here to get
- // the dependencies correct. Basically, we use a `with_ignore` to
- // read the result we want. If we didn't have the `with_ignore`,
- // we would wind up with a dependency on the entire crate, which
- // we don't want. Then we go and add dependencies on all the impls
- // in the result (which is what we wanted).
- //
- // The result is a graph with an edge from `Hir(I)` for every impl
- // `I` defined on some type `T` to `CoherentInherentImpls(T)`,
- // thus ensuring that if any of those impls change, the set of
- // inherent impls is considered dirty.
- //
- // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4
-
- let result = tcx.dep_graph.with_ignore(|| {
- let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
- match crate_map.inherent_impls.get(&ty_def_id) {
- Some(v) => &v[..],
- None => &[],
- }
- });
-
- for &impl_def_id in &result[..] {
- let def_path_hash = tcx.def_path_hash(impl_def_id);
- tcx.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
+ let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
+ match crate_map.inherent_impls.get(&ty_def_id) {
+ Some(v) => &v[..],
+ None => &[],
}
-
- result
}
struct InherentCollect<'tcx> {
_ => return
};
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
let self_ty = self.tcx.type_of(def_id);
let lang_items = self.tcx.lang_items();
match self_ty.sty {
// Add the implementation to the mapping from implementation to base
// type def ID, if there is a base type for this implementation and
// the implementation does not have any associated traits.
- let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
vec.push(impl_def_id);
} else {
use rustc::traits::{self, IntercrateMode};
use rustc::ty::TyCtxt;
-pub fn crate_inherent_impls_overlap_check<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) {
+pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
assert_eq!(crate_num, LOCAL_CRATE);
let krate = tcx.hir().krate();
krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
hir::ItemKind::Struct(..) |
hir::ItemKind::Trait(..) |
hir::ItemKind::Union(..) => {
- let type_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let type_def_id = self.tcx.hir().local_def_id(item.hir_id);
self.check_for_overlapping_inherent_impls(type_def_id);
}
_ => {}
mod orphan;
mod unsafety;
-fn check_impl<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
- let impl_def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+fn check_impl(tcx: TyCtxt<'_>, hir_id: HirId) {
+ let impl_def_id = tcx.hir().local_def_id(hir_id);
// If there are no traits, then this implementation must have a
// base type.
};
}
-fn coherent_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
let impls = tcx.hir().trait_impls(def_id);
for &impl_id in impls {
check_impl(tcx, impl_id);
builtin::check_trait(tcx, def_id);
}
-pub fn check_coherence<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_coherence(tcx: TyCtxt<'_>) {
for &trait_def_id in tcx.hir().krate().trait_impls.keys() {
tcx.ensure().coherent_trait(trait_def_id);
}
/// same type. Likewise, no two inherent impls for a given type
/// constructor provide a method with the same name.
fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
- let impl_def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+ let impl_def_id = tcx.hir().local_def_id(hir_id);
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_def_id = trait_ref.def_id;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir;
-pub fn check<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check(tcx: TyCtxt<'_>) {
let mut orphan = OrphanChecker { tcx };
tcx.hir().krate().visit_all_item_likes(&mut orphan);
}
/// to prevent inundating the user with a bunch of similar error
/// reports.
fn visit_item(&mut self, item: &hir::Item) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.tcx.hir().local_def_id(item.hir_id);
// "Trait" impl
if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node {
debug!("coherence2::orphan check: trait impl {}",
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::{self, Unsafety};
-pub fn check<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check(tcx: TyCtxt<'_>) {
let mut unsafety = UnsafetyChecker { tcx };
tcx.hir().krate().visit_all_item_likes(&mut unsafety);
}
unsafety: hir::Unsafety,
polarity: hir::ImplPolarity)
{
- let local_did = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let local_did = self.tcx.hir().local_def_id(item.hir_id);
if let Some(trait_ref) = self.tcx.impl_trait_ref(local_did) {
let trait_def = self.tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|generics| {
///////////////////////////////////////////////////////////////////////////
// Main entry point
-fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
&mut CollectItemTypesVisitor { tcx }.as_deep_visitor()
hir::GenericParamKind::Type {
default: Some(_), ..
} => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ let def_id = self.tcx.hir().local_def_id(param.hir_id);
self.tcx.type_of(def_id);
}
hir::GenericParamKind::Type { .. } => {}
hir::GenericParamKind::Const { .. } => {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ let def_id = self.tcx.hir().local_def_id(param.hir_id);
self.tcx.type_of(def_id);
}
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if let hir::ExprKind::Closure(..) = expr.node {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
+ let def_id = self.tcx.hir().local_def_id(expr.hir_id);
self.tcx.generics_of(def_id);
self.tcx.type_of(def_id);
}
}
}
-fn type_param_predicates<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn type_param_predicates(
+ tcx: TyCtxt<'_>,
(item_def_id, def_id): (DefId, DefId),
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
use rustc::hir::*;
// In the AST, bounds can derive from two places. Either
let param_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let param_owner = tcx.hir().ty_param_owner(param_id);
- let param_owner_def_id = tcx.hir().local_def_id_from_hir_id(param_owner);
+ let param_owner_def_id = tcx.hir().local_def_id(param_owner);
let generics = tcx.generics_of(param_owner_def_id);
let index = generics.param_def_id_to_index[&def_id];
let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id).as_interned_str());
/// parameter with ID `param_id`. We use this so as to avoid running
/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
/// conversion of the type to avoid inducing unnecessary cycles.
-fn is_param<'tcx>(tcx: TyCtxt<'tcx>, ast_ty: &hir::Ty, param_id: hir::HirId) -> bool {
+fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty, param_id: hir::HirId) -> bool {
if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
match path.res {
Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => {
- def_id == tcx.hir().local_def_id_from_hir_id(param_id)
+ def_id == tcx.hir().local_def_id(param_id)
}
_ => false,
}
}
}
-fn convert_item<'tcx>(tcx: TyCtxt<'tcx>, item_id: hir::HirId) {
+fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
let it = tcx.hir().expect_item(item_id);
debug!("convert: item {} with id {}", it.ident, it.hir_id);
- let def_id = tcx.hir().local_def_id_from_hir_id(item_id);
+ let def_id = tcx.hir().local_def_id(item_id);
match it.node {
// These don't define types.
hir::ItemKind::ExternCrate(_)
| hir::ItemKind::GlobalAsm(_) => {}
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for item in &foreign_mod.items {
- let def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = tcx.hir().local_def_id(item.hir_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
tcx.predicates_of(def_id);
for f in struct_def.fields() {
- let def_id = tcx.hir().local_def_id_from_hir_id(f.hir_id);
+ let def_id = tcx.hir().local_def_id(f.hir_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
}
}
-fn convert_trait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_id: hir::HirId) {
+fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
let trait_item = tcx.hir().expect_trait_item(trait_item_id);
- let def_id = tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
+ let def_id = tcx.hir().local_def_id(trait_item.hir_id);
tcx.generics_of(def_id);
match trait_item.node {
tcx.predicates_of(def_id);
}
-fn convert_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item_id: hir::HirId) {
- let def_id = tcx.hir().local_def_id_from_hir_id(impl_item_id);
+fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
+ let def_id = tcx.hir().local_def_id(impl_item_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
}
}
-fn convert_variant_ctor<'tcx>(tcx: TyCtxt<'tcx>, ctor_id: hir::HirId) {
- let def_id = tcx.hir().local_def_id_from_hir_id(ctor_id);
+fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) {
+ let def_id = tcx.hir().local_def_id(ctor_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
prev_discr = Some(
if let Some(ref e) = variant.node.disr_expr {
- let expr_did = tcx.hir().local_def_id_from_hir_id(e.hir_id);
+ let expr_did = tcx.hir().local_def_id(e.hir_id);
def.eval_explicit_discr(tcx, expr_did)
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
Some(discr)
);
for f in variant.node.data.fields() {
- let def_id = tcx.hir().local_def_id_from_hir_id(f.hir_id);
+ let def_id = tcx.hir().local_def_id(f.hir_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
}
}
-fn convert_variant<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn convert_variant(
+ tcx: TyCtxt<'_>,
variant_did: Option<DefId>,
ctor_did: Option<DefId>,
ident: Ident,
.fields()
.iter()
.map(|f| {
- let fid = tcx.hir().local_def_id_from_hir_id(f.hir_id);
+ let fid = tcx.hir().local_def_id(f.hir_id);
let dup_span = seen_fields.get(&f.ident.modern()).cloned();
if let Some(prev_span) = dup_span {
struct_span_err!(
)
}
-fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AdtDef {
+fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
use rustc::hir::*;
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let variants = def.variants
.iter()
.map(|v| {
- let variant_did = Some(tcx.hir().local_def_id_from_hir_id(v.node.id));
+ let variant_did = Some(tcx.hir().local_def_id(v.node.id));
let ctor_did = v.node.data.ctor_hir_id()
- .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+ .map(|hir_id| tcx.hir().local_def_id(hir_id));
let discr = if let Some(ref e) = v.node.disr_expr {
distance_from_explicit = 0;
- ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
+ ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.hir_id))
} else {
ty::VariantDiscr::Relative(distance_from_explicit)
};
ItemKind::Struct(ref def, _) => {
let variant_did = None;
let ctor_did = def.ctor_hir_id()
- .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+ .map(|hir_id| tcx.hir().local_def_id(hir_id));
let variants = std::iter::once(convert_variant(
tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def,
ItemKind::Union(ref def, _) => {
let variant_did = None;
let ctor_did = def.ctor_hir_id()
- .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+ .map(|hir_id| tcx.hir().local_def_id(hir_id));
let variants = std::iter::once(convert_variant(
tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def,
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
-fn super_predicates_of<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn super_predicates_of(
+ tcx: TyCtxt<'_>,
trait_def_id: DefId,
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
debug!("super_predicates(trait_def_id={:?})", trait_def_id);
let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id).unwrap();
})
}
-fn trait_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::TraitDef {
+fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item = tcx.hir().expect_item(hir_id);
}
}
-fn generics_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::Generics {
+fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
use rustc::hir::*;
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) |
Node::Ctor(..) | Node::Field(_) => {
let parent_id = tcx.hir().get_parent_item(hir_id);
- Some(tcx.hir().local_def_id_from_hir_id(parent_id))
+ Some(tcx.hir().local_def_id(parent_id))
}
Node::Expr(&hir::Expr {
node: hir::ExprKind::Closure(..),
opt_self = Some(ty::GenericParamDef {
index: 0,
name: kw::SelfUpper.as_interned_str(),
- def_id: tcx.hir().local_def_id_from_hir_id(param_id),
+ def_id: tcx.hir().local_def_id(param_id),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
.map(|(i, param)| ty::GenericParamDef {
name: param.name.ident().as_interned_str(),
index: own_start + i as u32,
- def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
+ def_id: tcx.hir().local_def_id(param.hir_id),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Lifetime,
}),
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
name: param.name.ident().as_interned_str(),
- def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
+ def_id: tcx.hir().local_def_id(param.hir_id),
pure_wrt_drop: param.pure_wrt_drop,
kind,
};
})
}
-fn report_assoc_ty_on_inherent_impl<'tcx>(tcx: TyCtxt<'tcx>, span: Span) {
+fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
span_err!(
tcx.sess,
span,
);
}
-fn type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
+fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
checked_type_of(tcx, def_id, true).unwrap()
}
///
/// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
/// you'd better just call [`type_of`] directly.
-pub fn checked_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fail: bool) -> Option<Ty<'tcx>> {
+pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<'_>> {
use rustc::hir::*;
let hir_id = match tcx.hir().as_local_hir_id(def_id) {
None
}
}
- Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(path),
+ Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(&**path),
_ => None,
};
})
}
-fn find_existential_constraints<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
+fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
use rustc::hir::{ImplItem, Item, TraitItem};
debug!("find_existential_constraints({:?})", def_id);
intravisit::NestedVisitorMap::All(&self.tcx.hir())
}
fn visit_item(&mut self, it: &'tcx Item) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = self.tcx.hir().local_def_id(it.hir_id);
// The existential type itself or its children are not within its reveal scope.
if def_id != self.def_id {
self.check(def_id);
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = self.tcx.hir().local_def_id(it.hir_id);
// The existential type itself or its children are not within its reveal scope.
if def_id != self.def_id {
self.check(def_id);
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
- let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
+ let def_id = self.tcx.hir().local_def_id(it.hir_id);
self.check(def_id);
intravisit::walk_trait_item(self, it);
}
}
}
-fn fn_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
use rustc::hir::*;
use rustc::hir::Node::*;
let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id));
let inputs = data.fields()
.iter()
- .map(|f| tcx.type_of(tcx.hir().local_def_id_from_hir_id(f.hir_id)));
+ .map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id)));
ty::Binder::bind(tcx.mk_fn_sig(
inputs,
ty,
}
}
-fn impl_trait_ref<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<ty::TraitRef<'tcx>> {
+fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id);
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
}
}
-fn impl_polarity<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> hir::ImplPolarity {
+fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
match tcx.hir().expect_item(hir_id).node {
hir::ItemKind::Impl(_, polarity, ..) => polarity,
/// Returns a list of type predicates for the definition with ID `def_id`, including inferred
/// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
/// inferred constraints concerning which regions outlive other regions.
-fn predicates_defined_on<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn predicates_defined_on(
+ tcx: TyCtxt<'_>,
def_id: DefId,
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
debug!("predicates_defined_on({:?})", def_id);
let mut result = tcx.explicit_predicates_of(def_id);
debug!(
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
/// `Self: Trait` predicates for traits.
-fn predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
+fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::GenericPredicates<'_> {
let mut result = tcx.predicates_defined_on(def_id);
if tcx.is_trait(def_id) {
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
/// N.B., this does not include any implied/inferred constraints.
-fn explicit_predicates_of<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn explicit_predicates_of(
+ tcx: TyCtxt<'_>,
def_id: DefId,
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
use rustc::hir::*;
use rustc_data_structures::fx::FxHashSet;
let mut index = parent_count + has_own_self as u32;
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
- def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
+ def_id: tcx.hir().local_def_id(param.hir_id),
index,
name: param.name.ident().as_interned_str(),
}));
};
let assoc_ty =
- tcx.mk_projection(tcx.hir().local_def_id_from_hir_id(trait_item.hir_id),
+ tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id),
self_trait_ref.substs);
let bounds = AstConv::compute_bounds(
fty
}
-fn is_foreign_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
match tcx.hir().get_if_local(def_id) {
Some(Node::ForeignItem(..)) => true,
Some(_) => false,
}
}
-fn static_mutability<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<hir::Mutability> {
+fn static_mutability(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::Mutability> {
match tcx.hir().get_if_local(def_id) {
Some(Node::Item(&hir::Item {
node: hir::ItemKind::Static(_, mutbl, _), ..
}
}
-fn linkage_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Linkage {
+fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage {
use rustc::mir::mono::Linkage::*;
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
}
}
-fn codegen_fn_attrs<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> CodegenFnAttrs {
+fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
let attrs = tcx.get_attrs(id);
let mut codegen_fn_attrs = CodegenFnAttrs::new();
/// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
/// // ^ 'a is unused and appears in assoc type, error
/// ```
-pub fn impl_wf_check<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn impl_wf_check(tcx: TyCtxt<'_>) {
// We will tag this as part of the WF check -- logically, it is,
// but it's one that we must perform earlier than the rest of
// WfCheck.
for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id(module));
+ tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id_from_node_id(module));
}
}
-fn check_mod_impl_wf<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,
&mut ImplWfCheck { tcx }
impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.node {
- let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
enforce_impl_params_are_constrained(self.tcx,
impl_def_id,
impl_item_refs);
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
}
-fn enforce_impl_params_are_constrained<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn enforce_impl_params_are_constrained(
+ tcx: TyCtxt<'_>,
impl_def_id: DefId,
impl_item_refs: &[hir::ImplItemRef],
) {
// Disallow unconstrained lifetimes, but only if they appear in assoc types.
let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter()
- .map(|item_ref| tcx.hir().local_def_id_from_hir_id(item_ref.id.hir_id))
+ .map(|item_ref| tcx.hir().local_def_id(item_ref.id.hir_id))
.filter(|&def_id| {
let item = tcx.associated_item(def_id);
item.kind == ty::AssocKind::Type && item.defaultness.has_value()
}
/// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct<'tcx>(tcx: TyCtxt<'tcx>, impl_item_refs: &[hir::ImplItemRef]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
let mut seen_type_items = FxHashMap::default();
let mut seen_value_items = FxHashMap::default();
for impl_item_ref in impl_item_refs {
#![feature(slice_patterns)]
#![feature(never_type)]
#![feature(inner_deref)]
+#![feature(mem_take)]
#![recursion_limit="256"]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#[macro_use] extern crate log;
use rustc::middle;
use rustc::session;
use rustc::util::common::ErrorReported;
-use rustc::session::config::{EntryFnType, nightly_options};
+use rustc::session::config::EntryFnType;
use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt};
ty: Ty<'tcx>,
}
-fn check_type_alias_enum_variants_enabled<'tcx>(tcx: TyCtxt<'tcx>, span: Span) {
- if !tcx.features().type_alias_enum_variants {
- let mut err = tcx.sess.struct_span_err(
- span,
- "enum variants on type aliases are experimental"
- );
- if nightly_options::is_nightly_build() {
- help!(&mut err,
- "add `#![feature(type_alias_enum_variants)]` to the \
- crate attributes to enable");
- }
- err.emit();
- }
-}
-
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl, abi: Abi, span: Span) {
if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
let mut err = struct_span_err!(tcx.sess, span, E0045,
})
}
-fn check_main_fn_ty<'tcx>(tcx: TyCtxt<'tcx>, main_def_id: DefId) {
+fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
let main_span = tcx.def_span(main_def_id);
let main_t = tcx.type_of(main_def_id);
}
}
-fn check_start_fn_ty<'tcx>(tcx: TyCtxt<'tcx>, start_def_id: DefId) {
+fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
let start_span = tcx.def_span(start_def_id);
let start_t = tcx.type_of(start_def_id);
}
}
-fn check_for_entry_fn<'tcx>(tcx: TyCtxt<'tcx>) {
+fn check_for_entry_fn(tcx: TyCtxt<'_>) {
match tcx.entry_fn(LOCAL_CRATE) {
Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
impl_wf_check::provide(providers);
}
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> {
+pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
tcx.sess.profiler(|p| p.start_activity("type-check crate"));
// this ensures that later parts of type checking can assume that items
tcx.sess.track_errors(|| {
time(tcx.sess, "type collecting", || {
for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
+ tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id_from_node_id(module));
}
});
})?;
time(tcx.sess, "item-types checking", || {
for &module in tcx.hir().krate().modules.keys() {
- tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
+ tcx.ensure().check_mod_item_types(tcx.hir().local_def_id_from_node_id(module));
}
});
// def-ID that will be used to determine the traits/predicates in
// scope. This is derived from the enclosing item-like thing.
let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
- let env_def_id = tcx.hir().local_def_id_from_hir_id(env_node_id);
+ let env_def_id = tcx.hir().local_def_id(env_node_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
astconv::AstConv::ast_ty_to_ty(&item_cx, hir_ty)
// def-ID that will be used to determine the traits/predicates in
// scope. This is derived from the enclosing item-like thing.
let env_hir_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
- let env_def_id = tcx.hir().local_def_id_from_hir_id(env_hir_id);
+ let env_def_id = tcx.hir().local_def_id(env_hir_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
let mut bounds = Bounds::default();
let (principal, _) = AstConv::instantiate_poly_trait_ref_inner(
impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
- let item_did = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let item_did = self.tcx.hir().local_def_id(item.hir_id);
debug!("InferVisitor::visit_item(item={:?})", item_did);
};
}
-fn inferred_outlives_of<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn inferred_outlives_of(
+ tcx: TyCtxt<'_>,
item_def_id: DefId,
-) -> &'tcx [ty::Predicate<'tcx>] {
+) -> &[ty::Predicate<'_>] {
let id = tcx
.hir()
.as_local_hir_id(item_def_id)
}
}
-fn inferred_outlives_crate<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn inferred_outlives_crate(
+ tcx: TyCtxt<'_>,
crate_num: CrateNum,
-) -> &'tcx CratePredicatesMap<'tcx> {
+) -> &CratePredicatesMap<'_> {
assert_eq!(crate_num, LOCAL_CRATE);
// Compute a map from each struct/enum/union S to the **explicit**
use rustc::ty::TyCtxt;
use syntax::symbol::sym;
-pub fn test_inferred_outlives<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
tcx.hir()
.krate()
.visit_all_item_likes(&mut OutlivesTest { tcx });
impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
// For unit testing: check for a special "rustc_outlives"
// attribute and report an error with various results if found.
}
}
-fn is_free_region<'tcx>(tcx: TyCtxt<'tcx>, region: Region<'_>) -> bool {
+fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool {
// First, screen for regions that might appear in a type header.
match region {
// These correspond to `T: 'a` relationships:
impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn visit_node_helper(&mut self, id: hir::HirId) {
let tcx = self.terms_cx.tcx;
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
self.build_constraints_for_item(def_id);
}
};
}
-fn crate_variances<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx CrateVariancesMap<'tcx> {
+fn crate_variances(tcx: TyCtxt<'_>, crate_num: CrateNum) -> &CrateVariancesMap<'_> {
assert_eq!(crate_num, LOCAL_CRATE);
let mut arena = arena::TypedArena::default();
let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena);
tcx.arena.alloc(solve::solve_constraints(constraints_cx))
}
-fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> &'tcx [ty::Variance] {
+fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
let id = tcx.hir().as_local_hir_id(item_def_id).expect("expected local def-id");
let unsupported = || {
// Variance not relevant.
let solutions = &self.solutions;
self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
let generics = tcx.generics_of(def_id);
let count = generics.count();
impl<'a, 'tcx> TermsContext<'a, 'tcx> {
fn add_inferreds_for_item(&mut self, id: hir::HirId) {
let tcx = self.tcx;
- let def_id = tcx.hir().local_def_id_from_hir_id(id);
+ let def_id = tcx.hir().local_def_id(id);
let count = tcx.generics_of(def_id).count();
if count == 0 {
use rustc::ty::TyCtxt;
use syntax::symbol::sym;
-pub fn test_variance<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn test_variance(tcx: TyCtxt<'_>) {
tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx });
}
impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
// For unit testing: check for a special "rustc_variance"
// attribute and report an error with various results if found.
use crate::html::escape::Escape;
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Cfg {
/// Accepts all configurations.
True,
use rustc::hir;
use rustc::hir::def::{CtorKind, DefKind, Res};
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::ptr::P;
use rustc::ty::subst::{InternalSubsts, SubstsRef, UnpackedKind};
use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
use rustc::ty::fold::TypeFolder;
use syntax::attr;
use syntax::ext::base::MacroKind;
use syntax::source_map::{dummy_spanned, Spanned};
-use syntax::ptr::P;
use syntax::symbol::{Symbol, kw, sym};
use syntax::symbol::InternedString;
use syntax_pos::{self, Pos, FileName};
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct ExternalCrate {
pub name: String,
pub src: FileName,
hir::ItemKind::Mod(_) => {
as_primitive(Res::Def(
DefKind::Mod,
- cx.tcx.hir().local_def_id_from_hir_id(id.id),
+ cx.tcx.hir().local_def_id(id.id),
))
}
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() => {
as_primitive(path.res).map(|(_, prim, attrs)| {
// Pretend the primitive is local.
- (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs)
+ (cx.tcx.hir().local_def_id(id.id), prim, attrs)
})
}
_ => None
hir::ItemKind::Mod(_) => {
as_keyword(Res::Def(
DefKind::Mod,
- cx.tcx.hir().local_def_id_from_hir_id(id.id),
+ cx.tcx.hir().local_def_id(id.id),
))
}
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() => {
as_keyword(path.res).map(|(_, prim, attrs)| {
- (cx.tcx.hir().local_def_id_from_hir_id(id.id), prim, attrs)
+ (cx.tcx.hir().local_def_id(id.id), prim, attrs)
})
}
_ => None
/// Anything with a source location and set of attributes and, optionally, a
/// name. That is, anything that can be documented. This doesn't correspond
/// directly to the AST's concept of an item; it's a strict superset.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone)]
pub struct Item {
/// Stringified span
pub source: Span,
impl Item {
/// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found.
- pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
+ pub fn doc_value(&self) -> Option<&str> {
self.attrs.doc_value()
}
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub enum ItemEnum {
ExternCrateItem(String, Option<String>),
ImportItem(Import),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Module {
pub items: Vec<Item>,
pub is_crate: bool,
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_node_id(self.id),
inner: ModuleItem(Module {
is_crate: self.is_crate,
items,
pub trait AttributesExt {
/// Finds an attribute as List and returns the list of attributes nested inside.
- fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a>;
+ fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
}
impl AttributesExt for [ast::Attribute] {
- fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> {
+ fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
ListAttributesIter {
attrs: self.iter(),
current_list: Vec::new().into_iter(),
/// Included files are kept separate from inline doc comments so that proper line-number
/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
/// kept separate because of issue #42760.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum DocFragment {
/// A doc fragment created from a `///` or `//!` doc comment.
SugaredDoc(usize, syntax_pos::Span, String),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
+#[derive(Clone, Debug, Default)]
pub struct Attributes {
pub doc_strings: Vec<DocFragment>,
pub other_attrs: Vec<ast::Attribute>,
/// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found.
- pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
+ pub fn doc_value(&self) -> Option<&str> {
self.doc_strings.first().map(|s| s.as_str())
}
}
impl AttributesExt for Attributes {
- fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> {
+ fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
self.other_attrs.lists(name)
}
}
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum GenericBound {
TraitBound(PolyTrait, hir::TraitBoundModifier),
Outlives(Lifetime),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Lifetime(String);
impl Lifetime {
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum GenericParamDefKind {
Lifetime,
Type {
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct GenericParamDef {
pub name: String,
}
hir::GenericParamKind::Type { ref default, synthetic } => {
(self.name.ident().name.clean(cx), GenericParamDefKind::Type {
- did: cx.tcx.hir().local_def_id_from_hir_id(self.hir_id),
+ did: cx.tcx.hir().local_def_id(self.hir_id),
bounds: self.bounds.clean(cx),
default: default.clean(cx),
synthetic: synthetic,
}
hir::GenericParamKind::Const { ref ty } => {
(self.name.ident().name.clean(cx), GenericParamDefKind::Const {
- did: cx.tcx.hir().local_def_id_from_hir_id(self.hir_id),
+ did: cx.tcx.hir().local_def_id(self.hir_id),
ty: ty.clean(cx),
})
}
}
// maybe use a Generic enum and use Vec<Generic>?
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
pub struct Generics {
pub params: Vec<GenericParamDef>,
pub where_predicates: Vec<WherePredicate>,
(all_types.into_iter().collect(), ret_types)
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Method {
pub generics: Generics,
pub decl: FnDecl,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct TyMethod {
pub header: hir::FnHeader,
pub decl: FnDecl,
pub ret_types: Vec<Type>,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Function {
pub decl: FnDecl,
pub generics: Generics,
(self.generics.clean(cx), (self.decl, self.body).clean(cx))
});
- let did = cx.tcx.hir().local_def_id_from_hir_id(self.id);
+ let did = cx.tcx.hir().local_def_id(self.id);
let constness = if cx.tcx.is_min_const_fn(did) {
hir::Constness::Const
} else {
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct FnDecl {
pub inputs: Arguments,
pub output: FunctionRetTy,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Arguments {
pub values: Vec<Argument>,
}
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Argument {
pub type_: Type,
pub name: String,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Debug)]
pub enum SelfTy {
SelfValue,
SelfBorrowed(Option<Lifetime>, Mutability),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum FunctionRetTy {
Return(Type),
DefaultReturn,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Trait {
pub auto: bool,
pub unsafety: hir::Unsafety,
name: Some(self.name.clean(cx)),
attrs: attrs,
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct TraitAlias {
pub generics: Generics,
pub bounds: Vec<GenericBound>,
name: Some(self.name.clean(cx)),
attrs,
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
AssocTypeItem(bounds.clean(cx), default.clean(cx))
}
};
- let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
+ let local_did = cx.tcx.hir().local_def_id(self.hir_id);
Item {
name: Some(self.ident.name.clean(cx)),
attrs: self.attrs.clean(cx),
generics: Generics::default(),
}, true),
};
- let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
+ let local_did = cx.tcx.hir().local_def_id(self.hir_id);
Item {
name: Some(self.ident.name.clean(cx)),
source: self.span.clean(cx),
}
/// A trait reference, which may have higher ranked lifetimes.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct PolyTrait {
pub trait_: Type,
pub generic_params: Vec<GenericParamDef>,
/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
/// importantly, it does not preserve mutability or boxes.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum Type {
/// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
ResolvedPath {
Array(Box<Type>, String),
Never,
CVarArgs,
- Unique(Box<Type>),
RawPointer(Mutability, Box<Type>),
BorrowedRef {
lifetime: Option<Lifetime>,
ImplTrait(Vec<GenericBound>),
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
pub enum PrimitiveType {
Isize, I8, I16, I32, I64, I128,
Usize, U8, U16, U32, U64, U128,
CVarArgs,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
+#[derive(Clone, Copy, Debug)]
pub enum TypeKind {
Enum,
Function,
Struct,
Union,
Trait,
- Variant,
Typedef,
Foreign,
Macro,
}
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
TyKind::Array(ref ty, ref length) => {
- let def_id = cx.tcx.hir().local_def_id_from_hir_id(length.hir_id);
+ let def_id = cx.tcx.hir().local_def_id(length.hir_id);
let param_env = cx.tcx.param_env(def_id);
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
let cid = GlobalId {
if let Some(lt) = lifetime.cloned() {
if !lt.is_elided() {
let lt_def_id =
- cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ cx.tcx.hir().local_def_id(param.hir_id);
lt_substs.insert(lt_def_id, lt.clean(cx));
}
}
}
hir::GenericParamKind::Type { ref default, .. } => {
let ty_param_def_id =
- cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let type_ = generic_args.args.iter().find_map(|arg| {
match arg {
}
hir::GenericParamKind::Const { .. } => {
let const_param_def_id =
- cx.tcx.hir().local_def_id_from_hir_id(param.hir_id);
+ cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let const_ = generic_args.args.iter().find_map(|arg| {
match arg {
ty::FnPtr(_) => {
let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
let sig = ty.fn_sig(cx.tcx);
+ let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
BareFunction(box BareFunctionDecl {
unsafety: sig.unsafety(),
generic_params: Vec::new(),
- decl: (cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
+ decl: (local_def_id, sig).clean(cx),
abi: sig.abi(),
})
}
impl Clean<Item> for hir::StructField {
fn clean(&self, cx: &DocContext<'_>) -> Item {
- let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
+ let local_did = cx.tcx.hir().local_def_id(self.hir_id);
Item {
name: Some(self.ident.name).clean(cx),
}
}
-#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Visibility {
Public,
Inherited,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Struct {
pub struct_type: doctree::StructType,
pub generics: Generics,
pub fields_stripped: bool,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Union {
pub struct_type: doctree::StructType,
pub generics: Generics,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
/// This is a more limited form of the standard Struct, different in that
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct VariantStruct {
pub struct_type: doctree::StructType,
pub fields: Vec<Item>,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Enum {
pub variants: IndexVec<VariantIdx, Item>,
pub generics: Generics,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Variant {
pub kind: VariantKind,
}
visibility: None,
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
inner: VariantItem(Variant {
kind: self.def.clean(cx),
}),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub enum VariantKind {
CLike,
Tuple(Vec<Type>),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Span {
pub filename: FileName,
pub loline: usize,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Path {
pub global: bool,
pub res: Res,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum GenericArg {
Lifetime(Lifetime),
Type(Type),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum GenericArgs {
AngleBracketed {
args: Vec<GenericArg>,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct PathSegment {
pub name: String,
pub args: GenericArgs,
}
Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
- Type::Unique(inner_ty) => Type::Unique(Box::new(strip_type(*inner_ty))),
Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
Type::BorrowedRef { lifetime, mutability, type_ } => {
Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Typedef {
pub type_: Type,
pub generics: Generics,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Existential {
pub bounds: Vec<GenericBound>,
pub generics: Generics,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct BareFunctionDecl {
pub unsafety: hir::Unsafety,
pub generic_params: Vec<GenericParamDef>,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Static {
pub type_: Type,
pub mutability: Mutability,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Constant {
pub type_: Type,
pub expr: String,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
pub enum Mutability {
Mutable,
Immutable,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Copy, Debug, Hash)]
pub enum ImplPolarity {
Positive,
Negative,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Impl {
pub unsafety: hir::Unsafety,
pub generics: Generics,
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(ast::CRATE_NODE_ID),
+ def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID),
visibility: self.vis.clean(cx),
stability: None,
deprecation: None,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub enum Import {
// use source as str;
Simple(String, ImportSource),
Glob(ImportSource)
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct ImportSource {
pub path: Path,
pub did: Option<DefId>,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Macro {
pub source: String,
pub imported_from: Option<String>,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct ProcMacro {
pub kind: MacroKind,
pub helpers: Vec<String>,
visibility: Some(Public),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
+ def_id: cx.tcx.hir().local_def_id(self.id),
inner: ProcMacroItem(ProcMacro {
kind: self.kind,
helpers: self.helpers.clean(cx),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Stability {
pub level: stability::StabilityLevel,
pub feature: Option<String>,
pub issue: Option<u32>,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
pub struct Deprecation {
pub since: Option<String>,
pub note: Option<String>,
/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
-#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TypeBinding {
pub name: String,
pub kind: TypeBindingKind,
}
-#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum TypeBindingKind {
Equality {
ty: Type,
where
F: FnOnce() -> R,
{
- let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
+ let old_bounds = mem::take(&mut *cx.impl_trait_bounds.borrow_mut());
let r = f();
assert!(cx.impl_trait_bounds.borrow().is_empty());
*cx.impl_trait_bounds.borrow_mut() = old_bounds;
for param in &mut params {
match param.kind {
clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
- *bounds = ty_bounds(mem::replace(bounds, Vec::new()));
+ *bounds = ty_bounds(mem::take(bounds));
}
_ => panic!("expected only type parameters"),
}
// to the map from defid -> hirid
let access_levels = AccessLevels {
map: access_levels.map.iter()
- .map(|(&k, &v)| (tcx.hir().local_def_id_from_hir_id(k), v))
+ .map(|(&k, &v)| (tcx.hir().local_def_id(k), v))
.collect()
};
use syntax::ast::{Name, NodeId};
use syntax::attr;
use syntax::ext::base::MacroKind;
-use syntax::ptr::P;
use syntax_pos::{self, Span};
use rustc::hir;
use rustc::hir::def_id::CrateNum;
+use rustc::hir::ptr::P;
pub struct Module<'hir> {
pub name: Option<Name>,
}
}
-#[derive(Debug, Clone, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Debug, Clone, Copy)]
pub enum StructType {
/// A braced struct
Plain,
}
}
}
- clean::Unique(..) => {
- panic!("should have been cleaned")
- }
}
}
clean::TypeKind::Module => ItemType::Module,
clean::TypeKind::Static => ItemType::Static,
clean::TypeKind::Const => ItemType::Constant,
- clean::TypeKind::Variant => ItemType::Variant,
clean::TypeKind::Typedef => ItemType::Typedef,
clean::TypeKind::Foreign => ItemType::ForeignType,
clean::TypeKind::Macro => ItemType::Macro,
deref_trait_did,
deref_mut_trait_did,
owned_box_did,
- masked_crates: mem::replace(&mut krate.masked_crates, Default::default()),
+ masked_crates: mem::take(&mut krate.masked_crates),
param_names: external_param_names,
aliases: Default::default(),
};
s
}
-fn shorter<'a>(s: Option<&'a str>) -> String {
+fn shorter(s: Option<&str>) -> String {
match s {
Some(s) => s.lines()
.skip_while(|s| s.chars().all(|c| c.is_whitespace()))
clean::Type::Array(ty, _) => {
work.push_back(*ty);
},
- clean::Type::Unique(ty) => {
- work.push_back(*ty);
- },
clean::Type::RawPointer(_, ty) => {
work.push_back(*ty);
},
max-width: 100%;
}
+li {
+ position: relative;
+}
+
.source .content {
margin-top: 50px;
max-width: none;
/// Push a level `level` heading into the appropriate place in the
/// hierarchy, returning a string containing the section number in
/// `<num>.<num>.<num>` format.
- pub fn push<'a>(&'a mut self, level: u32, name: String, id: String) -> &'a str {
+ pub fn push(&mut self, level: u32, name: String, id: String) -> &str {
assert!(level >= 1);
// collapse all previous sections into their parents until we
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
#![feature(drain_filter)]
#![feature(inner_deref)]
#![feature(never_type)]
+#![feature(mem_take)]
#![recursion_limit="256"]
#[macro_use] extern crate log;
extern crate rustc_errors as errors;
-extern crate serialize as rustc_serialize; // used by deriving
-
use std::default::Default;
use std::env;
use std::panic;
use crate::test::{TestOptions, Collector};
/// Separate any lines at the start of the file that begin with `# ` or `%`.
-fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
+fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
let mut metadata = Vec::new();
let mut count = 0;
use crate::fold::{DocFolder};
use crate::passes::Pass;
-use std::mem::replace;
+use std::mem::take;
pub const COLLAPSE_DOCS: Pass = Pass {
name: "collapse-docs",
let mut docs = vec![];
let mut last_frag: Option<DocFragment> = None;
- for frag in replace(doc_strings, vec![]) {
+ for frag in take(doc_strings) {
if let Some(mut curr_frag) = last_frag.take() {
let curr_kind = curr_frag.kind();
let new_kind = frag.kind();
// doesn't work with it anyway, so pull them from the HIR map instead
for &trait_did in cx.all_traits.iter() {
for &impl_node in cx.tcx.hir().trait_impls(trait_did) {
- let impl_did = cx.tcx.hir().local_def_id_from_hir_id(impl_node);
+ let impl_did = cx.tcx.hir().local_def_id(impl_node);
inline::build_impl(cx, impl_did, &mut new_items);
}
}
prog.push_str(everything_else);
} else {
let returns_result = everything_else.trim_end().ends_with("(())");
- let returns_option = everything_else.trim_end().ends_with("Some(())");
let (main_pre, main_post) = if returns_result {
- (if returns_option {
- "fn main() { fn _inner() -> Option<()> {"
- } else {
- "fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {"
- },
+ ("fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {",
"}\n_inner().unwrap() }")
} else {
("fn main() {\n", "\n}")
}
fn stability(&self, id: hir::HirId) -> Option<attr::Stability> {
- self.cx.tcx.hir().opt_local_def_id_from_hir_id(id)
+ self.cx.tcx.hir().opt_local_def_id(id)
.and_then(|def_id| self.cx.tcx.lookup_stability(def_id)).cloned()
}
fn deprecation(&self, id: hir::HirId) -> Option<attr::Deprecation> {
- self.cx.tcx.hir().opt_local_def_id_from_hir_id(id)
+ self.cx.tcx.hir().opt_local_def_id(id)
.and_then(|def_id| self.cx.tcx.lookup_deprecation(def_id))
}
let ident = renamed.unwrap_or(item.ident);
if item.vis.node.is_pub() {
- let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
self.store_path(def_id);
}
_ if self.inlining && !item.vis.node.is_pub() => {}
hir::ItemKind::GlobalAsm(..) => {}
hir::ItemKind::ExternCrate(orig_name) => {
- let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
om.extern_crates.push(ExternCrate {
cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id)
.unwrap_or(LOCAL_CRATE),
Macro {
- def_id: self.cx.tcx.hir().local_def_id_from_hir_id(def.hir_id),
+ def_id: self.cx.tcx.hir().local_def_id(def.hir_id),
attrs: &def.attrs,
name: renamed.unwrap_or(def.name),
whence: def.span,
/// If the Json value is an Object, returns the value associated with the provided key.
/// Otherwise, returns None.
- pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
+ pub fn find(&self, key: &str) -> Option<&Json> {
match *self {
Json::Object(ref map) => map.get(key),
_ => None
/// If the Json value is an Object, performs a depth-first search until
/// a value associated with the provided key is found. If no value is found
/// or the Json value is not an Object, returns `None`.
- pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
+ pub fn search(&self, key: &str) -> Option<&Json> {
match self {
&Json::Object(ref map) => {
match map.get(key) {
use realstd::collections::CollectionAllocErr::*;
use realstd::usize;
+ // https://github.com/rust-lang/rust/issues/62301
+ fn _assert_hashmap_is_unwind_safe() {
+ fn assert_unwind_safe<T: crate::panic::UnwindSafe>() {}
+ assert_unwind_safe::<HashMap<(), crate::cell::UnsafeCell<()>>>();
+ }
+
#[test]
fn test_zero_capacities() {
type HM = HashMap<i32, i32>;
/// Like `write`, except that it writes from a slice of buffers.
///
- /// Data is copied to from each buffer in order, with the final buffer
+ /// Data is copied from each buffer in order, with the final buffer
/// read from possibly being only partially consumed. This method must
/// behave as a call to `write` with the buffers concatenated would.
///
where R: Read, W: Write
{
let mut buf = unsafe {
+ #[allow(deprecated)]
let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized();
reader.initializer().initialize(&mut buf);
buf
#![feature(libc)]
#![feature(link_args)]
#![feature(linkage)]
+#![feature(mem_take)]
#![feature(needs_panic_runtime)]
#![feature(never_type)]
#![feature(nll)]
use crate::any::Any;
use crate::cell::UnsafeCell;
+use crate::collections;
use crate::fmt;
use crate::future::Future;
use crate::pin::Pin;
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
+// https://github.com/rust-lang/rust/issues/62301
+#[stable(feature = "hashbrown", since = "1.36.0")]
+impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S>
+ where K: UnwindSafe, V: UnwindSafe, S: UnwindSafe {}
+
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> Deref for AssertUnwindSafe<T> {
type Target = T;
HOOK_LOCK.write_unlock();
if let Hook::Custom(ptr) = old_hook {
- Box::from_raw(ptr);
+ #[allow(unused_must_use)] {
+ Box::from_raw(ptr);
+ }
}
}
}
unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
- let contents = mem::replace(self.fill(), String::new());
+ let contents = mem::take(self.fill());
Box::into_raw(Box::new(contents))
}
assert_eq!(out, "foobar\n");
}
-
- #[test]
- #[cfg_attr(target_os = "android", ignore)]
- #[cfg(unix)]
- fn uid_works() {
- use crate::os::unix::prelude::*;
-
- let mut p = Command::new("/bin/sh")
- .arg("-c").arg("true")
- .uid(unsafe { libc::getuid() })
- .gid(unsafe { libc::getgid() })
- .spawn().unwrap();
- assert!(p.wait().unwrap().success());
- }
-
- #[test]
- #[cfg_attr(target_os = "android", ignore)]
- #[cfg(unix)]
- fn uid_to_root_fails() {
- use crate::os::unix::prelude::*;
-
- // if we're already root, this isn't a valid test. Most of the bots run
- // as non-root though (android is an exception).
- if unsafe { libc::getuid() == 0 } { return }
- assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
- }
-
#[test]
#[cfg_attr(target_os = "android", ignore)]
fn test_process_status() {
new_guard
}
-fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool {
+fn abort_selection<T>(guard: &mut MutexGuard<'_, State<T>>) -> bool {
match mem::replace(&mut guard.blocker, NoneBlocked) {
NoneBlocked => true,
BlockedSender(token) => {
// needs to be careful to destroy the data *outside* of the lock to
// prevent deadlock.
let _data = if guard.cap != 0 {
- mem::replace(&mut guard.buf.buf, Vec::new())
+ mem::take(&mut guard.buf.buf)
} else {
Vec::new()
};
+#![allow(deprecated)] // mem::uninitialized
+
use crate::io::ErrorKind;
use crate::mem;
/// }
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
- pub fn incoming<'a>(&'a self) -> Incoming<'a> {
+ pub fn incoming(&self) -> Incoming<'_> {
Incoming { listener: self }
}
}
pub fn hashmap_random_keys() -> (u64, u64) {
fn rdrand64() -> u64 {
unsafe {
- let mut ret: u64 = crate::mem::uninitialized();
+ let mut ret: u64 = 0;
for _ in 0..10 {
if crate::arch::x86_64::_rdrand64_step(&mut ret) == 1 {
return ret;
}
}
- fn address<'a>(&'a self) -> AddressKind<'a> {
+ fn address(&self) -> AddressKind<'_> {
let len = self.len as usize - sun_path_offset(&self.addr);
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
/// }
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
- pub fn incoming<'a>(&'a self) -> Incoming<'a> {
+ pub fn incoming(&self) -> Incoming<'_> {
Incoming { listener: self }
}
}
}
}
-pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
+pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
match v.iter().position(|c| *c == 0) {
// don't include the 0
Some(i) => &v[..i],
b == b'\\'
}
-pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix<'a>> {
+pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
use crate::path::Prefix::*;
unsafe {
// The unsafety here stems from converting between &OsStr and &[u8]
// If anything here fails, there's not really much we can do, so we leak
// the buffer/OVERLAPPED pointers to ensure we're at least memory safe.
if self.pipe.cancel_io().is_err() || self.result().is_err() {
- let buf = mem::replace(self.dst, Vec::new());
+ let buf = mem::take(self.dst);
let overlapped = Box::new(unsafe { mem::zeroed() });
let overlapped = mem::replace(&mut self.overlapped, overlapped);
mem::forget((buf, overlapped));
p.join(path)
}
- pub fn path<'a>(&'a self) -> &'a Path {
+ pub fn path(&self) -> &Path {
let TempDir(ref p) = *self;
p
}
}
pub fn is_known_lint_tool(m_item: Ident) -> bool {
- ["clippy"].contains(&m_item.as_str().as_ref())
+ [sym::clippy, sym::rustc].contains(&m_item.name)
}
impl NestedMetaItem {
})
}
-pub fn find_by_name<'a>(attrs: &'a [Attribute], name: Symbol) -> Option<&'a Attribute> {
+pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> {
attrs.iter().find(|attr| attr.check_name(name))
}
-pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: Symbol)
- -> impl Iterator<Item = &'a Attribute> {
+pub fn filter_by_name(attrs: &[Attribute], name: Symbol)
+ -> impl Iterator<Item=&Attribute> {
attrs.iter().filter(move |attr| attr.check_name(name))
}
use crate::parse::token;
use crate::parse::parser::Parser;
use crate::ptr::P;
-use crate::symbol::Symbol;
-use crate::symbol::{kw, sym};
+use crate::symbol::{sym, Symbol};
use crate::tokenstream::{TokenStream, TokenTree};
use crate::visit::{self, Visitor};
use crate::util::map_in_place::MapInPlace;
pub enum InvocationKind {
Bang {
mac: ast::Mac,
- ident: Option<Ident>,
span: Span,
},
Attr {
} else {
self.resolve_imports();
if undetermined_invocations.is_empty() { break }
- invocations = mem::replace(&mut undetermined_invocations, Vec::new());
+ invocations = mem::take(&mut undetermined_invocations);
force = !mem::replace(&mut progress, false);
continue
};
ext: &SyntaxExtension)
-> Option<AstFragment> {
let kind = invoc.fragment_kind;
- let (mac, ident, span) = match invoc.kind {
- InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
+ let (mac, span) = match invoc.kind {
+ InvocationKind::Bang { mac, span } => (mac, span),
_ => unreachable!(),
};
let path = &mac.node.path;
- let ident = ident.unwrap_or_else(|| Ident::invalid());
let validate = |this: &mut Self| {
// feature-gate the macro invocation
if let Some((feature, issue)) = ext.unstable_feature {
}
}
- if ident.name != kw::Invalid {
- 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));
- }
Ok(())
};
}
SyntaxExtensionKind::Bang(expander) => {
- if ident.name != kw::Invalid {
- let msg =
- format!("macro {}! expects no ident argument, given '{}'", path, ident);
- self.cx.span_err(path.span, &msg);
- self.cx.trace_macros_diag();
- kind.dummy(span)
- } else {
- self.gate_proc_macro_expansion_kind(span, kind);
- let tok_result = expander.expand(self.cx, span, mac.node.stream());
- let result = self.parse_ast_fragment(tok_result, kind, path, span);
- self.gate_proc_macro_expansion(span, &result);
- result
- }
+ self.gate_proc_macro_expansion_kind(span, kind);
+ let tok_result = expander.expand(self.cx, span, mac.node.stream());
+ let result = self.parse_ast_fragment(tok_result, kind, path, span);
+ self.gate_proc_macro_expansion(span, &result);
+ result
}
};
}
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
- self.collect(kind, InvocationKind::Bang { mac, ident: None, span })
+ self.collect(kind, InvocationKind::Bang { mac, span })
}
fn collect_attr(&mut self,
ast::ItemKind::Mac(..) => {
self.check_attributes(&item.attrs);
item.and_then(|item| match item.node {
- ItemKind::Mac(mac) => {
- self.collect(AstFragmentKind::Items, InvocationKind::Bang {
- mac,
- ident: Some(item.ident),
- span: item.span,
- }).make_items()
- }
+ ItemKind::Mac(mac) => self.collect(
+ AstFragmentKind::Items, InvocationKind::Bang { mac, span: item.span }
+ ).make_items(),
_ => unreachable!(),
})
}
}
fn enable_custom_inner_attributes(&self) -> bool {
- self.features.map_or(false, |features| {
- features.custom_inner_attributes || features.custom_attribute || features.rustc_attrs
- })
+ self.features.map_or(false, |features| features.custom_inner_attributes)
}
}
/// # Returns
///
/// The parsed non-terminal.
-fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> Nonterminal {
+fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
if name == sym::tt {
return token::NtTT(p.parse_token_tree());
}
quoted::TokenTree::Delimited(mut span, delimited) => {
span = span.apply_mark(cx.current_expansion.mark);
stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
- result_stack.push(mem::replace(&mut result, Vec::new()));
+ result_stack.push(mem::take(&mut result));
}
// Nothing much to do here. Just push the token to the result, being careful to
use errors::{Applicability, DiagnosticBuilder, Handler};
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lock;
use rustc_target::spec::abi::Abi;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use log::debug;
(active, nll, "1.0.0", Some(43234), None),
// Allows using slice patterns.
- (active, slice_patterns, "1.0.0", Some(23121), None),
+ (active, slice_patterns, "1.0.0", Some(62254), None),
// Allows the definition of `const` functions with some advanced features.
(active, const_fn, "1.2.0", Some(57563), None),
// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
(active, lint_reasons, "1.31.0", Some(54503), None),
- // Allows paths to enum variants on type aliases.
- (active, type_alias_enum_variants, "1.31.0", Some(49683), None),
-
// Allows exhaustive integer pattern matching on `usize` and `isize`.
(active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
// Allows explicit discriminants on non-unit enum variants.
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
+ // Allows `impl Trait` with multiple unrelated lifetimes.
+ (active, member_constraints, "1.37.0", Some(61977), None),
+
+ // Allows `async || body` closures.
+ (active, async_closure, "1.37.0", Some(62290), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
(removed, allocator, "1.0.0", None, None, None),
(removed, simd, "1.0.0", Some(27731), None,
Some("removed in favor of `#[repr(simd)]`")),
- (removed, advanced_slice_patterns, "1.0.0", Some(23121), None,
+ (removed, advanced_slice_patterns, "1.0.0", Some(62254), None,
Some("merged into `#![feature(slice_patterns)]`")),
(removed, macro_reexport, "1.0.0", Some(29638), None,
Some("subsumed by `pub use`")),
(accepted, extern_crate_self, "1.34.0", Some(56409), None),
// Allows arbitrary delimited token streams in non-macro attributes.
(accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None),
+ // Allows paths to enum variants on type aliases including `Self`.
+ (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None),
// Allows using `#[repr(align(X))]` on enums with equivalent semantics
// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`.
(accepted, repr_align_enum, "1.37.0", Some(57996), None),
attribute is just used for rustc unit \
tests and will never be stable",
cfg_fn!(rustc_attrs))),
+ (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "the `#[rustc_dump_env_program_clauses]` \
+ attribute is just used for rustc unit \
+ tests and will never be stable",
+ cfg_fn!(rustc_attrs))),
+ (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "the `#[rustc_object_lifetime_default]` \
+ attribute is just used for rustc unit \
+ tests and will never be stable",
+ cfg_fn!(rustc_attrs))),
(sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable,
sym::rustc_attrs,
"the `#[rustc_test_marker]` attribute \
"internal implementation detail",
cfg_fn!(rustc_attrs))),
+ (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
+ (sym::rustc_doc_only_macro, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
+ (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
+ (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
(sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable,
sym::rustc_attrs,
"used by the test suite",
}
debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
return;
+ } else {
+ for segment in &attr.path.segments {
+ if segment.ident.as_str().starts_with("rustc") {
+ let msg = "attributes starting with `rustc` are \
+ reserved for use by the `rustc` compiler";
+ gate_feature!(self, rustc_attrs, segment.ident.span, msg);
+ }
+ }
}
for &(n, ty) in self.plugin_attributes {
if attr.path == n {
return;
}
}
- if !attr::is_known(attr) {
- if attr.name_or_empty().as_str().starts_with("rustc_") {
- let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
- are reserved for internal compiler diagnostics";
- gate_feature!(self, rustc_attrs, attr.span, msg);
- } else if !is_macro {
- // Only run the custom attribute lint during regular feature gate
- // checking. Macro gating runs before the plugin attributes are
- // registered, so we skip this in that case.
- let msg = format!("The attribute `{}` is currently unknown to the compiler and \
- may have meaning added to it in the future", attr.path);
- gate_feature!(self, custom_attribute, attr.span, &msg);
- }
+ if !is_macro && !attr::is_known(attr) {
+ // Only run the custom attribute lint during regular feature gate
+ // checking. Macro gating runs before the plugin attributes are
+ // registered, so we skip this in that case.
+ let msg = format!("The attribute `{}` is currently unknown to the compiler and \
+ may have meaning added to it in the future", attr.path);
+ gate_feature!(self, custom_attribute, attr.span, &msg);
}
}
}
"labels on blocks are unstable");
}
}
- ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
- gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
- }
ast::ExprKind::Async(..) => {
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
}
features
}
+fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
+ vec.borrow().iter().for_each(f);
+}
+
pub fn check_crate(krate: &ast::Crate,
sess: &ParseSess,
features: &Features,
plugin_attributes,
};
- sess
- .param_attr_spans
- .borrow()
- .iter()
- .for_each(|span| gate_feature!(
- &ctx,
- param_attrs,
- *span,
- "attributes on function parameters are unstable"
- ));
-
- sess
- .let_chains_spans
- .borrow()
- .iter()
- .for_each(|span| gate_feature!(
- &ctx,
- let_chains,
- *span,
- "`let` expressions in this position are experimental"
- ));
+ for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
+ &ctx,
+ param_attrs,
+ *span,
+ "attributes on function parameters are unstable"
+ ));
+
+ for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
+ &ctx,
+ let_chains,
+ *span,
+ "`let` expressions in this position are experimental"
+ ));
+
+ for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
+ &ctx,
+ async_closure,
+ *span,
+ "async closures are unstable"
+ ));
let visitor = &mut PostExpansionVisitor {
context: &ctx,
test(attr(deny(warnings))))]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(bind_by_move_pattern_guards)]
+#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(const_transmute)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
+#![feature(mem_take)]
#![feature(nll)]
#![feature(rustc_attrs)]
#![feature(rustc_diagnostic_macros)]
#[cfg(test)]
mod tests {
- use std::io;
use crate::ast::{self, Ident};
use crate::util::parser_testing::{string_to_crate, matches_codepattern};
use crate::print::pprust;
// this version doesn't care about getting comments or docstrings in.
fn fake_print_crate(s: &mut pprust::State<'_>,
- krate: &ast::Crate) -> io::Result<()> {
+ krate: &ast::Crate) {
s.print_mod(&krate.module, &krate.attrs)
}
let sum_with_parens = pprust::to_string(|s| {
use crate::print::pprust::PrintState;
- s.s.word("&")?;
- s.print_opt_lifetime(lifetime)?;
- s.print_mutability(mut_ty.mutbl)?;
- s.popen()?;
- s.print_type(&mut_ty.ty)?;
- s.print_type_bounds(" +", &bounds)?;
+ s.s.word("&");
+ s.print_opt_lifetime(lifetime);
+ s.print_mutability(mut_ty.mutbl);
+ s.popen();
+ s.print_type(&mut_ty.ty);
+ s.print_type_bounds(" +", &bounds);
s.pclose()
});
err.span_suggestion(
Ok(ret_val)
}
- /// Immutably extract string if found at current position with given delimiters
- fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<String> {
- let mut pos = self.pos;
- let mut idx = self.src_index(pos);
- let mut ch = char_at(&self.src, idx);
- if ch != from_ch {
- return None;
- }
- pos = pos + Pos::from_usize(ch.len_utf8());
- let start_pos = pos;
- idx = self.src_index(pos);
- while idx < self.end_src_index {
- ch = char_at(&self.src, idx);
- if ch == to_ch {
- return Some(self.src[self.src_index(start_pos)..self.src_index(pos)].to_string());
- }
- pos = pos + Pos::from_usize(ch.len_utf8());
- idx = self.src_index(pos);
- }
- return None;
- }
-
fn try_real_token(&mut self) -> Result<Token, ()> {
let mut t = self.try_next_token()?;
loop {
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
param_attr_spans: Lock::new(Vec::new()),
let_chains_spans: Lock::new(Vec::new()),
+ async_closure_spans: Lock::new(Vec::new()),
}
}
// Characters and their corresponding confusables were collected from
// http://www.unicode.org/Public/security/10.0.0/confusables.txt
-use syntax_pos::{Span, Pos, NO_EXPANSION};
-use errors::{Applicability, DiagnosticBuilder};
use super::StringReader;
+use errors::{Applicability, DiagnosticBuilder};
+use syntax_pos::{Pos, Span, NO_EXPANSION};
+#[rustfmt::skip] // for line breaks
const UNICODE_ARRAY: &[(char, &str, char)] = &[
('
', "Line Separator", ' '),
('
', "Paragraph Separator", ' '),
('〉', "Right-Pointing Angle Bracket", '>'),
('〉', "Right Angle Bracket", '>'),
('》', "Right Double Angle Bracket", '>'),
- ('>', "Fullwidth Greater-Than Sign", '>'), ];
-
+ ('>', "Fullwidth Greater-Than Sign", '>'),
+];
const ASCII_ARRAY: &[(char, &str)] = &[
(' ', "Space"),
('+', "Plus Sign"),
('<', "Less-Than Sign"),
('=', "Equals Sign"),
- ('>', "Greater-Than Sign"), ];
-
-crate fn check_for_substitution<'a>(reader: &StringReader<'a>,
- ch: char,
- err: &mut DiagnosticBuilder<'a>) -> bool {
- UNICODE_ARRAY
- .iter()
- .find(|&&(c, _, _)| c == ch)
- .map(|&(_, u_name, ascii_char)| {
- let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
- match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
- Some(&(ascii_char, ascii_name)) => {
- // special help suggestion for "directed" double quotes
- if let Some(s) = reader.peek_delimited('“', '”') {
- let msg = format!("Unicode characters '“' (Left Double Quotation Mark) and \
- '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
- ascii_char, ascii_name);
- err.span_suggestion(
- Span::new(reader.pos, reader.next_pos + Pos::from_usize(s.len()) +
- Pos::from_usize('”'.len_utf8()), NO_EXPANSION),
- &msg,
- format!("\"{}\"", s),
- Applicability::MaybeIncorrect);
- } else {
- let msg =
- format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
- ch, u_name, ascii_char, ascii_name);
- err.span_suggestion(
- span,
- &msg,
- ascii_char.to_string(),
- Applicability::MaybeIncorrect);
- }
- true
- },
- None => {
- let msg = format!("substitution character not found for '{}'", ch);
- reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
- false
- }
+ ('>', "Greater-Than Sign"),
+];
+
+crate fn check_for_substitution<'a>(
+ reader: &StringReader<'a>,
+ ch: char,
+ err: &mut DiagnosticBuilder<'a>,
+) -> bool {
+ let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) {
+ Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char),
+ None => return false,
+ };
+
+ let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
+
+ let ascii_name = match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
+ Some((_ascii_char, ascii_name)) => ascii_name,
+ None => {
+ let msg = format!("substitution character not found for '{}'", ch);
+ reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
+ return false
+ },
+ };
+
+ // special help suggestion for "directed" double quotes
+ if let Some(s) = reader.peek_delimited('“', '”') {
+ let msg = format!(
+ "Unicode characters '“' (Left Double Quotation Mark) and \
+ '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
+ ascii_char, ascii_name
+ );
+ err.span_suggestion(
+ Span::new(
+ reader.pos,
+ reader.next_pos + Pos::from_usize(s.len()) + Pos::from_usize('”'.len_utf8()),
+ NO_EXPANSION,
+ ),
+ &msg,
+ format!("\"{}\"", s),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ let msg = format!(
+ "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
+ ch, u_name, ascii_char, ascii_name
+ );
+ err.span_suggestion(
+ span,
+ &msg,
+ ascii_char.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ true
+}
+
+impl StringReader<'_> {
+ /// Immutably extract string if found at current position with given delimiters
+ fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<&str> {
+ let tail = &self.src[self.src_index(self.pos)..];
+ let mut chars = tail.chars();
+ let first_char = chars.next()?;
+ if first_char != from_ch {
+ return None;
}
- }).unwrap_or(false)
+ let last_char_idx = chars.as_str().find(to_ch)?;
+ Some(&chars.as_str()[..last_char_idx])
+ }
}
pub param_attr_spans: Lock<Vec<Span>>,
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
pub let_chains_spans: Lock<Vec<Span>>,
+ // Places where `async || ..` exprs were used and should be feature gated.
+ pub async_closure_spans: Lock<Vec<Span>>,
}
impl ParseSess {
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
param_attr_spans: Lock::new(Vec::new()),
let_chains_spans: Lock::new(Vec::new()),
+ async_closure_spans: Lock::new(Vec::new()),
}
}
};
let sugg = pprust::to_string(|s| {
use crate::print::pprust::PrintState;
- s.popen()?;
- s.print_expr(&e)?;
- s.s.word( ".")?;
- s.print_usize(float.trunc() as usize)?;
- s.pclose()?;
- s.s.word(".")?;
+ s.popen();
+ s.print_expr(&e);
+ s.s.word( ".");
+ s.print_usize(float.trunc() as usize);
+ s.pclose();
+ s.s.word(".");
s.s.word(fstr.splitn(2, ".").last().unwrap().to_string())
});
err.span_suggestion(
-> PResult<'a, P<Expr>>
{
let lo = self.token.span;
+
let movability = if self.eat_keyword(kw::Static) {
Movability::Static
} else {
Movability::Movable
};
+
let asyncness = if self.token.span.rust_2018() {
self.parse_asyncness()
} else {
IsAsync::NotAsync
};
- let capture_clause = if self.eat_keyword(kw::Move) {
- CaptureBy::Value
- } else {
- CaptureBy::Ref
- };
+ if asyncness.is_async() {
+ // Feature gate `async ||` closures.
+ self.sess.async_closure_spans.borrow_mut().push(self.prev_span);
+ }
+
+ let capture_clause = self.parse_capture_clause();
let decl = self.parse_fn_block_decl()?;
let decl_hi = self.prev_span;
let body = match decl.output {
attrs))
}
- // `else` token already eaten
+ /// `else` token already eaten
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
if self.eat_keyword(kw::If) {
return self.parse_if_expr(ThinVec::new());
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
}
- // parse `loop {...}`, `loop` token already eaten
+ /// Parse `loop {...}`, `loop` token already eaten.
fn parse_loop_expr(&mut self, opt_label: Option<Label>,
span_lo: Span,
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
}
- /// Parses an `async move {...}` expression.
- pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
- -> PResult<'a, P<Expr>>
- {
- let span_lo = self.token.span;
- self.expect_keyword(kw::Async)?;
- let capture_clause = if self.eat_keyword(kw::Move) {
+ /// Parse an optional `move` prefix to a closure lke construct.
+ fn parse_capture_clause(&mut self) -> CaptureBy {
+ if self.eat_keyword(kw::Move) {
CaptureBy::Value
} else {
CaptureBy::Ref
- };
+ }
+ }
+
+ /// Parses an `async move? {...}` expression.
+ pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+ let span_lo = self.token.span;
+ self.expect_keyword(kw::Async)?;
+ let capture_clause = self.parse_capture_clause();
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
Ok(self.mk_expr(
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
-> PResult<'a, Option<P<Item>>> {
let token_lo = self.token.span;
- let (ident, def) = match self.token.kind {
- token::Ident(name, false) if name == kw::Macro => {
- self.bump();
- let ident = self.parse_ident()?;
- let tokens = if self.check(&token::OpenDelim(token::Brace)) {
- match self.parse_token_tree() {
- TokenTree::Delimited(_, _, tts) => tts,
- _ => unreachable!(),
- }
- } else if self.check(&token::OpenDelim(token::Paren)) {
- let args = self.parse_token_tree();
- let body = if self.check(&token::OpenDelim(token::Brace)) {
- self.parse_token_tree()
- } else {
- self.unexpected()?;
- unreachable!()
- };
- TokenStream::new(vec![
- args.into(),
- TokenTree::token(token::FatArrow, token_lo.to(self.prev_span)).into(),
- body.into(),
- ])
+ let (ident, def) = if self.eat_keyword(kw::Macro) {
+ let ident = self.parse_ident()?;
+ let tokens = if self.check(&token::OpenDelim(token::Brace)) {
+ match self.parse_token_tree() {
+ TokenTree::Delimited(_, _, tts) => tts,
+ _ => unreachable!(),
+ }
+ } else if self.check(&token::OpenDelim(token::Paren)) {
+ let args = self.parse_token_tree();
+ let body = if self.check(&token::OpenDelim(token::Brace)) {
+ self.parse_token_tree()
} else {
self.unexpected()?;
unreachable!()
};
+ TokenStream::new(vec![
+ args.into(),
+ TokenTree::token(token::FatArrow, token_lo.to(self.prev_span)).into(),
+ body.into(),
+ ])
+ } else {
+ self.unexpected()?;
+ unreachable!()
+ };
- (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
- }
- token::Ident(name, _) if name == sym::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);
- self.bump();
- self.bump();
-
- let ident = self.parse_ident()?;
- let (delim, tokens) = self.expect_delimited_token_tree()?;
- if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
- self.report_invalid_macro_expansion_item();
- }
+ (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
+ } else if self.check_keyword(sym::macro_rules) &&
+ self.look_ahead(1, |t| *t == token::Not) &&
+ self.look_ahead(2, |t| t.is_ident()) {
+ let prev_span = self.prev_span;
+ self.complain_if_pub_macro(&vis.node, prev_span);
+ self.bump();
+ self.bump();
- (ident, ast::MacroDef { tokens, legacy: true })
+ let ident = self.parse_ident()?;
+ let (delim, tokens) = self.expect_delimited_token_tree()?;
+ if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+ self.report_invalid_macro_expansion_item();
}
- _ => return Ok(None),
+
+ (ident, ast::MacroDef { tokens, legacy: true })
+ } else {
+ return Ok(None);
};
let span = lo.to(self.prev_span);
!self.is_existential_type_decl() &&
!self.is_auto_trait_item() &&
!self.is_async_fn() {
- let pth = self.parse_path(PathStyle::Expr)?;
+ let path = self.parse_path(PathStyle::Expr)?;
if !self.eat(&token::Not) {
let expr = if self.check(&token::OpenDelim(token::Brace)) {
- self.parse_struct_expr(lo, pth, ThinVec::new())?
+ self.parse_struct_expr(lo, path, ThinVec::new())?
} else {
let hi = self.prev_span;
- self.mk_expr(lo.to(hi), ExprKind::Path(None, pth), ThinVec::new())
+ self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new())
};
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
}));
}
- // it's a macro invocation
- let id = match self.token.kind {
- token::OpenDelim(_) => Ident::invalid(), // no special identifier
- _ => self.parse_ident()?,
- };
-
- // check that we're pointing at delimiters (need to check
- // again after the `if`, because of `parse_ident`
- // consuming more tokens).
- match self.token.kind {
- token::OpenDelim(_) => {}
- _ => {
- // we only expect an ident if we didn't parse one
- // above.
- let ident_str = if id.name == kw::Invalid {
- "identifier, "
- } else {
- ""
- };
- let tok_str = self.this_token_descr();
- let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}",
- ident_str,
- tok_str));
- err.span_label(self.token.span, format!("expected {}`(` or `{{`", ident_str));
- return Err(err)
- },
- }
-
let (delim, tts) = self.expect_delimited_token_tree()?;
let hi = self.prev_span;
MacStmtStyle::NoBraces
};
- if id.name == kw::Invalid {
- let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
- let node = if delim == MacDelimiter::Brace ||
- self.token == token::Semi || self.token == token::Eof {
- StmtKind::Mac(P((mac, style, attrs.into())))
- }
- // We used to incorrectly stop parsing macro-expanded statements here.
- // If the next token will be an error anyway but could have parsed with the
- // earlier behavior, stop parsing here and emit a warning to avoid breakage.
- else if macro_legacy_warnings &&
- self.token.can_begin_expr() &&
- match self.token.kind {
- // These can continue an expression, so we can't stop parsing and warn.
- token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
- token::BinOp(token::Minus) | token::BinOp(token::Star) |
- token::BinOp(token::And) | token::BinOp(token::Or) |
- token::AndAnd | token::OrOr |
- token::DotDot | token::DotDotDot | token::DotDotEq => false,
- _ => true,
- } {
- self.warn_missing_semicolon();
- StmtKind::Mac(P((mac, style, attrs.into())))
- } else {
- let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
- let e = self.maybe_recover_from_bad_qpath(e, true)?;
- let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
- let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
- StmtKind::Expr(e)
- };
- Stmt {
- id: ast::DUMMY_NODE_ID,
- span: lo.to(hi),
- node,
- }
+ let mac = respan(lo.to(hi), Mac_ { path, tts, delim });
+ let node = if delim == MacDelimiter::Brace ||
+ self.token == token::Semi || self.token == token::Eof {
+ StmtKind::Mac(P((mac, style, attrs.into())))
+ }
+ // We used to incorrectly stop parsing macro-expanded statements here.
+ // If the next token will be an error anyway but could have parsed with the
+ // earlier behavior, stop parsing here and emit a warning to avoid breakage.
+ else if macro_legacy_warnings &&
+ self.token.can_begin_expr() &&
+ match self.token.kind {
+ // These can continue an expression, so we can't stop parsing and warn.
+ token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
+ token::BinOp(token::Minus) | token::BinOp(token::Star) |
+ token::BinOp(token::And) | token::BinOp(token::Or) |
+ token::AndAnd | token::OrOr |
+ token::DotDot | token::DotDotDot | token::DotDotEq => false,
+ _ => true,
+ } {
+ self.warn_missing_semicolon();
+ StmtKind::Mac(P((mac, style, attrs.into())))
} else {
- // if it has a special ident, it's definitely an item
- //
- // Require a semicolon or braces.
- if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
- self.report_invalid_macro_expansion_item();
- }
- let span = lo.to(hi);
- Stmt {
- id: ast::DUMMY_NODE_ID,
- span,
- node: StmtKind::Item({
- self.mk_item(
- span, id /*id is good here*/,
- ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
- respan(lo, VisibilityKind::Inherited),
- attrs)
- }),
- }
+ let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
+ let e = self.maybe_recover_from_bad_qpath(e, true)?;
+ let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+ let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+ StmtKind::Expr(e)
+ };
+ Stmt {
+ id: ast::DUMMY_NODE_ID,
+ span: lo.to(hi),
+ node,
}
} else {
// FIXME: Bad copy of attrs
}
let sugg = pprust::to_string(|s| {
use crate::print::pprust::{PrintState, INDENT_UNIT};
- s.ibox(INDENT_UNIT)?;
- s.bopen()?;
- s.print_stmt(&stmt)?;
+ s.ibox(INDENT_UNIT);
+ s.bopen();
+ s.print_stmt(&stmt);
s.bclose_maybe_open(stmt.span, INDENT_UNIT, false)
});
e.span_suggestion(
{
let is_const_fn = self.eat_keyword(kw::Const);
let const_span = self.prev_span;
- let unsafety = self.parse_unsafety();
let asyncness = self.parse_asyncness();
+ if let IsAsync::Async { .. } = asyncness {
+ self.ban_async_in_2015(self.prev_span);
+ }
let asyncness = respan(self.prev_span, asyncness);
+ let unsafety = self.parse_unsafety();
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
item_,
visibility,
maybe_append(attrs, extra_attrs));
- if self.token.span.rust_2015() {
- self.diagnostic().struct_span_err_with_code(
- async_span,
- "`async fn` is not permitted in the 2015 edition",
- DiagnosticId::Error("E0670".into())
- ).emit();
- }
+ self.ban_async_in_2015(async_span);
return Ok(Some(item));
}
}
self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
}
+ /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
+ fn ban_async_in_2015(&self, async_span: Span) {
+ if async_span.rust_2015() {
+ self.diagnostic()
+ .struct_span_err_with_code(
+ async_span,
+ "`async fn` is not permitted in the 2015 edition",
+ DiagnosticId::Error("E0670".into())
+ )
+ .emit();
+ }
+ }
+
/// Parses a foreign item.
crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
maybe_whole!(self, NtForeignItem, |ni| ni);
let mac_lo = self.token.span;
// item macro.
- let pth = self.parse_path(PathStyle::Mod)?;
+ let path = self.parse_path(PathStyle::Mod)?;
self.expect(&token::Not)?;
-
- // a 'special' identifier (like what `macro_rules!` uses)
- // is optional. We should eventually unify invoc syntax
- // and remove this.
- let id = if self.token.is_ident() {
- self.parse_ident()?
- } else {
- Ident::invalid() // no special identifier
- };
- // eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
let hi = self.prev_span;
- let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
- let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
+ let mac = respan(mac_lo.to(hi), Mac_ { path, tts, delim });
+ let item =
+ self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs);
return Ok(Some(item));
}
!(self.is_async_fn() && self.token.span.rust_2015()) {
let prev_span = self.prev_span;
let lo = self.token.span;
- let pth = self.parse_path(PathStyle::Mod)?;
+ let path = self.parse_path(PathStyle::Mod)?;
- if pth.segments.len() == 1 {
+ if path.segments.len() == 1 {
if !self.eat(&token::Not) {
return Err(self.missing_assoc_item_kind_err(item_kind, prev_span));
}
self.expect(&token::Semi)?;
}
- Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim })))
+ Ok(Some(respan(lo.to(self.prev_span), Mac_ { path, tts, delim })))
} else {
Ok(None)
}
let mut tokens = Vec::new();
let prev_collecting = match self.token_cursor.frame.last_token {
LastToken::Collecting(ref mut list) => {
- Some(mem::replace(list, Vec::new()))
+ Some(mem::take(list))
}
LastToken::Was(ref mut last) => {
tokens.extend(last.take());
// Pull out the tokens that we've collected from the call to `f` above.
let mut collected_tokens = match *last_token {
- LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
+ LastToken::Collecting(ref mut v) => mem::take(v),
LastToken::Was(_) => panic!("our vector went away?"),
};
use std::collections::VecDeque;
use std::fmt;
-use std::io;
use std::borrow::Cow;
use log::debug;
}
impl Token {
- pub fn is_eof(&self) -> bool {
+ crate fn is_eof(&self) -> bool {
match *self {
Token::Eof => true,
_ => false,
}
#[derive(Copy, Clone)]
-pub enum PrintStackBreak {
+crate enum PrintStackBreak {
Fits,
Broken(Breaks),
}
#[derive(Copy, Clone)]
-pub struct PrintStackElem {
+crate struct PrintStackElem {
offset: isize,
pbreak: PrintStackBreak
}
const SIZE_INFINITY: isize = 0xffff;
-pub fn mk_printer<'a>(out: Box<dyn io::Write+'a>, linewidth: usize) -> Printer<'a> {
+pub fn mk_printer(out: &mut String) -> Printer<'_> {
+ let linewidth = 78;
// Yes 55, it makes the ring buffers big enough to never fall behind.
let n: usize = 55 * linewidth;
debug!("mk_printer {}", linewidth);
}
pub struct Printer<'a> {
- out: Box<dyn io::Write+'a>,
+ out: &'a mut String,
buf_max_len: usize,
/// Width of lines we're constrained to
margin: isize,
}
}
-const SPACES: [u8; 128] = [b' '; 128];
-
impl<'a> Printer<'a> {
pub fn last_token(&mut self) -> Token {
self.buf[self.right].token.clone()
self.buf[self.right].token = t;
}
- fn pretty_print_eof(&mut self) -> io::Result<()> {
+ fn pretty_print_eof(&mut self) {
if !self.scan_stack.is_empty() {
self.check_stack(0);
- self.advance_left()?;
+ self.advance_left();
}
self.indent(0);
- Ok(())
}
- fn pretty_print_begin(&mut self, b: BeginToken) -> io::Result<()> {
+ fn pretty_print_begin(&mut self, b: BeginToken) {
if self.scan_stack.is_empty() {
self.left_total = 1;
self.right_total = 1;
self.buf[self.right] = BufEntry { token: Token::Begin(b), size: -self.right_total };
let right = self.right;
self.scan_push(right);
- Ok(())
}
- fn pretty_print_end(&mut self) -> io::Result<()> {
+ fn pretty_print_end(&mut self) {
if self.scan_stack.is_empty() {
debug!("pp End/print Vec<{},{}>", self.left, self.right);
- self.print_end()
+ self.print_end();
} else {
debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
self.advance_right();
self.buf[self.right] = BufEntry { token: Token::End, size: -1 };
let right = self.right;
self.scan_push(right);
- Ok(())
}
}
- fn pretty_print_break(&mut self, b: BreakToken) -> io::Result<()> {
+ fn pretty_print_break(&mut self, b: BreakToken) {
if self.scan_stack.is_empty() {
self.left_total = 1;
self.right_total = 1;
self.scan_push(right);
self.buf[self.right] = BufEntry { token: Token::Break(b), size: -self.right_total };
self.right_total += b.blank_space;
- Ok(())
}
- fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> {
+ fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) {
if self.scan_stack.is_empty() {
debug!("pp String('{}')/print Vec<{},{}>",
s, self.left, self.right);
- self.print_string(s, len)
+ self.print_string(s, len);
} else {
debug!("pp String('{}')/buffer Vec<{},{}>",
s, self.left, self.right);
self.advance_right();
self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
self.right_total += len;
- self.check_stream()
+ self.check_stream();
}
}
- pub fn check_stream(&mut self) -> io::Result<()> {
+ crate fn check_stream(&mut self) {
debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}",
self.left, self.right, self.left_total, self.right_total);
if self.right_total - self.left_total > self.space {
let scanned = self.scan_pop_bottom();
self.buf[scanned].size = SIZE_INFINITY;
}
- self.advance_left()?;
+ self.advance_left();
if self.left != self.right {
- self.check_stream()?;
+ self.check_stream();
}
}
- Ok(())
}
- pub fn scan_push(&mut self, x: usize) {
+ crate fn scan_push(&mut self, x: usize) {
debug!("scan_push {}", x);
self.scan_stack.push_front(x);
}
- pub fn scan_pop(&mut self) -> usize {
+ crate fn scan_pop(&mut self) -> usize {
self.scan_stack.pop_front().unwrap()
}
- pub fn scan_top(&mut self) -> usize {
+ crate fn scan_top(&mut self) -> usize {
*self.scan_stack.front().unwrap()
}
- pub fn scan_pop_bottom(&mut self) -> usize {
+ crate fn scan_pop_bottom(&mut self) -> usize {
self.scan_stack.pop_back().unwrap()
}
- pub fn advance_right(&mut self) {
+ crate fn advance_right(&mut self) {
self.right += 1;
self.right %= self.buf_max_len;
// Extend the buf if necessary.
assert_ne!(self.right, self.left);
}
- pub fn advance_left(&mut self) -> io::Result<()> {
+ crate fn advance_left(&mut self) {
debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
self.left, self.buf[self.left].size);
_ => 0
};
- self.print(left, left_size)?;
+ self.print(left, left_size);
self.left_total += len;
left_size = self.buf[self.left].size;
}
-
- Ok(())
}
- pub fn check_stack(&mut self, k: isize) {
+ crate fn check_stack(&mut self, k: isize) {
if !self.scan_stack.is_empty() {
let x = self.scan_top();
match self.buf[x].token {
}
}
- pub fn print_newline(&mut self, amount: isize) -> io::Result<()> {
+ crate fn print_newline(&mut self, amount: isize) {
debug!("NEWLINE {}", amount);
- let ret = writeln!(self.out);
+ self.out.push('\n');
self.pending_indentation = 0;
self.indent(amount);
- ret
}
- pub fn indent(&mut self, amount: isize) {
+ crate fn indent(&mut self, amount: isize) {
debug!("INDENT {}", amount);
self.pending_indentation += amount;
}
- pub fn get_top(&mut self) -> PrintStackElem {
+ crate fn get_top(&mut self) -> PrintStackElem {
match self.print_stack.last() {
Some(el) => *el,
None => PrintStackElem {
}
}
- pub fn print_begin(&mut self, b: BeginToken, l: isize) -> io::Result<()> {
+ crate fn print_begin(&mut self, b: BeginToken, l: isize) {
if l > self.space {
let col = self.margin - self.space + b.offset;
debug!("print Begin -> push broken block at col {}", col);
pbreak: PrintStackBreak::Fits
});
}
- Ok(())
}
- pub fn print_end(&mut self) -> io::Result<()> {
+ crate fn print_end(&mut self) {
debug!("print End -> pop End");
let print_stack = &mut self.print_stack;
assert!(!print_stack.is_empty());
print_stack.pop().unwrap();
- Ok(())
}
- pub fn print_break(&mut self, b: BreakToken, l: isize) -> io::Result<()> {
+ crate fn print_break(&mut self, b: BreakToken, l: isize) {
let top = self.get_top();
match top.pbreak {
PrintStackBreak::Fits => {
debug!("print Break({}) in fitting block", b.blank_space);
self.space -= b.blank_space;
self.indent(b.blank_space);
- Ok(())
}
PrintStackBreak::Broken(Breaks::Consistent) => {
debug!("print Break({}+{}) in consistent block",
top.offset, b.offset);
- let ret = self.print_newline(top.offset + b.offset);
+ self.print_newline(top.offset + b.offset);
self.space = self.margin - (top.offset + b.offset);
- ret
}
PrintStackBreak::Broken(Breaks::Inconsistent) => {
if l > self.space {
debug!("print Break({}+{}) w/ newline in inconsistent",
top.offset, b.offset);
- let ret = self.print_newline(top.offset + b.offset);
+ self.print_newline(top.offset + b.offset);
self.space = self.margin - (top.offset + b.offset);
- ret
} else {
debug!("print Break({}) w/o newline in inconsistent",
b.blank_space);
self.indent(b.blank_space);
self.space -= b.blank_space;
- Ok(())
}
}
}
}
- pub fn print_string(&mut self, s: Cow<'static, str>, len: isize) -> io::Result<()> {
+ crate fn print_string(&mut self, s: Cow<'static, str>, len: isize) {
debug!("print String({})", s);
// assert!(len <= space);
self.space -= len;
//
// write!(self.out, "{: >n$}", "", n = self.pending_indentation as usize)?;
//
- // But that is significantly slower than using `SPACES`. This code is
- // sufficiently hot, and indents can get sufficiently large, that the
- // difference is significant on some workloads.
- let spaces_len = SPACES.len() as isize;
- while self.pending_indentation >= spaces_len {
- self.out.write_all(&SPACES)?;
- self.pending_indentation -= spaces_len;
- }
- if self.pending_indentation > 0 {
- self.out.write_all(&SPACES[0..self.pending_indentation as usize])?;
- self.pending_indentation = 0;
- }
-
- write!(self.out, "{}", s)
+ // But that is significantly slower. This code is sufficiently hot, and indents can get
+ // sufficiently large, that the difference is significant on some workloads.
+ self.out.reserve(self.pending_indentation as usize);
+ self.out.extend(std::iter::repeat(' ').take(self.pending_indentation as usize));
+ self.pending_indentation = 0;
+ self.out.push_str(&s);
}
- pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
+ crate fn print(&mut self, token: Token, l: isize) {
debug!("print {} {} (remaining line space={})", token, l,
self.space);
debug!("{}", buf_str(&self.buf,
Token::Break(b) => self.print_break(b, l),
Token::String(s, len) => {
assert_eq!(len, l);
- self.print_string(s, len)
+ self.print_string(s, len);
}
Token::Eof => panic!(), // Eof should never get here.
}
// Convenience functions to talk to the printer.
/// "raw box"
- pub fn rbox(&mut self, indent: usize, b: Breaks) -> io::Result<()> {
+ crate fn rbox(&mut self, indent: usize, b: Breaks) {
self.pretty_print_begin(BeginToken {
offset: indent as isize,
breaks: b
}
/// Inconsistent breaking box
- pub fn ibox(&mut self, indent: usize) -> io::Result<()> {
+ crate fn ibox(&mut self, indent: usize) {
self.rbox(indent, Breaks::Inconsistent)
}
/// Consistent breaking box
- pub fn cbox(&mut self, indent: usize) -> io::Result<()> {
+ pub fn cbox(&mut self, indent: usize) {
self.rbox(indent, Breaks::Consistent)
}
- pub fn break_offset(&mut self, n: usize, off: isize) -> io::Result<()> {
+ pub fn break_offset(&mut self, n: usize, off: isize) {
self.pretty_print_break(BreakToken {
offset: off,
blank_space: n as isize
})
}
- pub fn end(&mut self) -> io::Result<()> {
+ crate fn end(&mut self) {
self.pretty_print_end()
}
- pub fn eof(&mut self) -> io::Result<()> {
+ pub fn eof(&mut self) {
self.pretty_print_eof()
}
- pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) -> io::Result<()> {
+ pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) {
let s = wrd.into();
let len = s.len() as isize;
self.pretty_print_string(s, len)
}
- fn spaces(&mut self, n: usize) -> io::Result<()> {
+ fn spaces(&mut self, n: usize) {
self.break_offset(n, 0)
}
- pub fn zerobreak(&mut self) -> io::Result<()> {
+ crate fn zerobreak(&mut self) {
self.spaces(0)
}
- pub fn space(&mut self) -> io::Result<()> {
+ pub fn space(&mut self) {
self.spaces(1)
}
- pub fn hardbreak(&mut self) -> io::Result<()> {
+ pub fn hardbreak(&mut self) {
self.spaces(SIZE_INFINITY as usize)
}
pub fn hardbreak_tok_offset(off: isize) -> Token {
Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
}
-
- pub fn hardbreak_tok() -> Token {
- Self::hardbreak_tok_offset(0)
- }
}
use syntax_pos::{DUMMY_SP, FileName};
use std::borrow::Cow;
-use std::io::{self, Write, Read};
-use std::vec;
+use std::io::Read;
pub enum AnnNode<'a> {
Ident(&'a ast::Ident),
}
pub trait PpAnn {
- fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> { Ok(()) }
- fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> { Ok(()) }
+ fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) { }
+ fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) { }
}
#[derive(Copy, Clone)]
is_expanded: bool
}
-fn rust_printer<'a>(writer: Box<dyn Write+'a>, ann: &'a dyn PpAnn) -> State<'a> {
- State {
- s: pp::mk_printer(writer, DEFAULT_COLUMNS),
- cm: None,
- comments: None,
- cur_cmnt: 0,
- boxes: Vec::new(),
- ann,
- is_expanded: false
- }
-}
-
-pub const INDENT_UNIT: usize = 4;
-
-pub const DEFAULT_COLUMNS: usize = 78;
+crate const INDENT_UNIT: usize = 4;
/// Requires you to pass an input filename and reader so that
/// it can scan the input text for comments to copy forward.
krate: &ast::Crate,
filename: FileName,
input: &mut dyn Read,
- out: Box<dyn Write+'a>,
+ out: &mut String,
ann: &'a dyn PpAnn,
- is_expanded: bool) -> io::Result<()> {
+ is_expanded: bool) {
let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
if is_expanded && std_inject::injected_crate_name().is_some() {
let list = attr::mk_list_item(
DUMMY_SP, ast::Ident::with_empty_ctxt(sym::feature), vec![pi_nested]);
let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), list);
- s.print_attribute(&fake_attr)?;
+ s.print_attribute(&fake_attr);
// #![no_std]
let no_std_meta = attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::no_std));
let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), no_std_meta);
- s.print_attribute(&fake_attr)?;
+ s.print_attribute(&fake_attr);
}
- s.print_mod(&krate.module, &krate.attrs)?;
- s.print_remaining_comments()?;
+ s.print_mod(&krate.module, &krate.attrs);
+ s.print_remaining_comments();
s.s.eof()
}
sess: &ParseSess,
filename: FileName,
input: &mut dyn Read,
- out: Box<dyn Write+'a>,
+ out: &'a mut String,
ann: &'a dyn PpAnn,
is_expanded: bool) -> State<'a> {
let comments = comments::gather_comments(sess, filename, input);
}
pub fn new(cm: &'a SourceMap,
- out: Box<dyn Write+'a>,
+ out: &'a mut String,
ann: &'a dyn PpAnn,
comments: Option<Vec<comments::Comment>>,
is_expanded: bool) -> State<'a> {
State {
- s: pp::mk_printer(out, DEFAULT_COLUMNS),
+ s: pp::mk_printer(out),
cm: Some(cm),
comments,
cur_cmnt: 0,
}
pub fn to_string<F>(f: F) -> String where
- F: FnOnce(&mut State<'_>) -> io::Result<()>,
+ F: FnOnce(&mut State<'_>),
{
- let mut wr = Vec::new();
+ let mut wr = String::new();
{
- let ann = NoAnn;
- let mut printer = rust_printer(Box::new(&mut wr), &ann);
- f(&mut printer).unwrap();
- printer.s.eof().unwrap();
+ let mut printer = State {
+ s: pp::mk_printer(&mut wr),
+ cm: None,
+ comments: None,
+ cur_cmnt: 0,
+ boxes: Vec::new(),
+ ann: &NoAnn,
+ is_expanded: false
+ };
+ f(&mut printer);
+ printer.s.eof();
}
- String::from_utf8(wr).unwrap()
+ wr
}
fn binop_to_string(op: BinOpToken) -> &'static str {
token_kind_to_string(&token.kind)
}
-pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
+crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
match *nt {
token::NtExpr(ref e) => expr_to_string(e),
token::NtMeta(ref e) => meta_item_to_string(e),
generics: &ast::Generics)
-> String {
to_string(|s| {
- s.head("")?;
+ s.head("");
s.print_fn(decl, header, Some(name),
- generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited))?;
- s.end()?; // Close the head box
- s.end() // Close the outer box
+ generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited));
+ s.end(); // Close the head box
+ s.end(); // Close the outer box
})
}
pub fn block_to_string(blk: &ast::Block) -> String {
to_string(|s| {
// containing cbox, will be closed by print-block at }
- s.cbox(INDENT_UNIT)?;
+ s.cbox(INDENT_UNIT);
// head-ibox, will be closed by print-block after {
- s.ibox(0)?;
+ s.ibox(0);
s.print_block(blk)
})
}
fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
fn cur_cmnt(&mut self) -> &mut usize;
- fn word_space<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
- self.writer().word(w)?;
+ fn word_space<S: Into<Cow<'static, str>>>(&mut self, w: S) {
+ self.writer().word(w);
self.writer().space()
}
- fn popen(&mut self) -> io::Result<()> { self.writer().word("(") }
+ fn popen(&mut self) { self.writer().word("(") }
- fn pclose(&mut self) -> io::Result<()> { self.writer().word(")") }
+ fn pclose(&mut self) { self.writer().word(")") }
fn is_begin(&mut self) -> bool {
match self.writer().last_token() {
self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
}
- fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
+ fn hardbreak_if_not_bol(&mut self) {
if !self.is_bol() {
- self.writer().hardbreak()?
+ self.writer().hardbreak()
}
- Ok(())
}
// "raw box"
- fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
+ fn rbox(&mut self, u: usize, b: pp::Breaks) {
self.boxes().push(b);
self.writer().rbox(u, b)
}
- fn ibox(&mut self, u: usize) -> io::Result<()> {
+ fn ibox(&mut self, u: usize) {
self.boxes().push(pp::Breaks::Inconsistent);
- self.writer().ibox(u)
+ self.writer().ibox(u);
}
- fn end(&mut self) -> io::Result<()> {
+ fn end(&mut self) {
self.boxes().pop().unwrap();
self.writer().end()
}
- fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()>
- where F: FnMut(&mut Self, &T) -> io::Result<()>,
+ fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F)
+ where F: FnMut(&mut Self, &T),
{
- self.rbox(0, b)?;
+ self.rbox(0, b);
let mut first = true;
for elt in elts {
- if first { first = false; } else { self.word_space(",")?; }
- op(self, elt)?;
+ if first { first = false; } else { self.word_space(","); }
+ op(self, elt);
}
- self.end()
+ self.end();
}
- fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
+ fn maybe_print_comment(&mut self, pos: BytePos) {
while let Some(ref cmnt) = self.next_comment() {
if cmnt.pos < pos {
- self.print_comment(cmnt)?;
+ self.print_comment(cmnt);
} else {
break
}
}
- Ok(())
}
fn print_comment(&mut self,
- cmnt: &comments::Comment) -> io::Result<()> {
- let r = match cmnt.style {
+ cmnt: &comments::Comment) {
+ match cmnt.style {
comments::Mixed => {
assert_eq!(cmnt.lines.len(), 1);
- self.writer().zerobreak()?;
- self.writer().word(cmnt.lines[0].clone())?;
+ self.writer().zerobreak();
+ self.writer().word(cmnt.lines[0].clone());
self.writer().zerobreak()
}
comments::Isolated => {
- self.hardbreak_if_not_bol()?;
+ self.hardbreak_if_not_bol();
for line in &cmnt.lines {
// Don't print empty lines because they will end up as trailing
// whitespace
if !line.is_empty() {
- self.writer().word(line.clone())?;
+ self.writer().word(line.clone());
}
- self.writer().hardbreak()?;
+ self.writer().hardbreak();
}
- Ok(())
}
comments::Trailing => {
if !self.is_bol() {
- self.writer().word(" ")?;
+ self.writer().word(" ");
}
if cmnt.lines.len() == 1 {
- self.writer().word(cmnt.lines[0].clone())?;
+ self.writer().word(cmnt.lines[0].clone());
self.writer().hardbreak()
} else {
- self.ibox(0)?;
+ self.ibox(0);
for line in &cmnt.lines {
if !line.is_empty() {
- self.writer().word(line.clone())?;
+ self.writer().word(line.clone());
}
- self.writer().hardbreak()?;
+ self.writer().hardbreak();
}
- self.end()
+ self.end();
}
}
comments::BlankLine => {
_ => false
};
if is_semi || self.is_begin() || self.is_end() {
- self.writer().hardbreak()?;
+ self.writer().hardbreak();
}
- self.writer().hardbreak()
- }
- };
- match r {
- Ok(()) => {
- *self.cur_cmnt() = *self.cur_cmnt() + 1;
- Ok(())
+ self.writer().hardbreak();
}
- Err(e) => Err(e),
}
+ *self.cur_cmnt() = *self.cur_cmnt() + 1;
}
fn next_comment(&mut self) -> Option<comments::Comment> {
}
}
- fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
- self.maybe_print_comment(lit.span.lo())?;
+ fn print_literal(&mut self, lit: &ast::Lit) {
+ self.maybe_print_comment(lit.span.lo());
self.writer().word(literal_to_string(lit.token))
}
fn print_string(&mut self, st: &str,
- style: ast::StrStyle) -> io::Result<()> {
+ style: ast::StrStyle) {
let st = match style {
ast::StrStyle::Cooked => {
(format!("\"{}\"", st.escape_debug()))
}
fn print_inner_attributes(&mut self,
- attrs: &[ast::Attribute]) -> io::Result<()> {
+ attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
}
fn print_inner_attributes_no_trailing_hardbreak(&mut self,
attrs: &[ast::Attribute])
- -> io::Result<()> {
+ {
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
}
fn print_outer_attributes(&mut self,
- attrs: &[ast::Attribute]) -> io::Result<()> {
+ attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
}
fn print_inner_attributes_inline(&mut self,
- attrs: &[ast::Attribute]) -> io::Result<()> {
+ attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
}
fn print_outer_attributes_inline(&mut self,
- attrs: &[ast::Attribute]) -> io::Result<()> {
+ attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
}
attrs: &[ast::Attribute],
kind: ast::AttrStyle,
is_inline: bool,
- trailing_hardbreak: bool) -> io::Result<()> {
+ trailing_hardbreak: bool) {
let mut count = 0;
for attr in attrs {
if attr.style == kind {
- self.print_attribute_inline(attr, is_inline)?;
+ self.print_attribute_inline(attr, is_inline);
if is_inline {
- self.nbsp()?;
+ self.nbsp();
}
count += 1;
}
}
if count > 0 && trailing_hardbreak && !is_inline {
- self.hardbreak_if_not_bol()?;
+ self.hardbreak_if_not_bol();
}
- Ok(())
}
- fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> {
+ fn print_attribute_path(&mut self, path: &ast::Path) {
for (i, segment) in path.segments.iter().enumerate() {
if i > 0 {
- self.writer().word("::")?
+ self.writer().word("::");
}
if segment.ident.name != kw::PathRoot {
if segment.ident.name == kw::DollarCrate {
- self.print_dollar_crate(segment.ident)?;
+ self.print_dollar_crate(segment.ident);
} else {
- self.writer().word(segment.ident.as_str().to_string())?;
+ self.writer().word(segment.ident.as_str().to_string());
}
}
}
- Ok(())
}
- fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
+ fn print_attribute(&mut self, attr: &ast::Attribute) {
self.print_attribute_inline(attr, false)
}
fn print_attribute_inline(&mut self, attr: &ast::Attribute,
- is_inline: bool) -> io::Result<()> {
+ is_inline: bool) {
if !is_inline {
- self.hardbreak_if_not_bol()?;
+ self.hardbreak_if_not_bol();
}
- self.maybe_print_comment(attr.span.lo())?;
+ self.maybe_print_comment(attr.span.lo());
if attr.is_sugared_doc {
- self.writer().word(attr.value_str().unwrap().as_str().to_string())?;
+ self.writer().word(attr.value_str().unwrap().as_str().to_string());
self.writer().hardbreak()
} else {
match attr.style {
- ast::AttrStyle::Inner => self.writer().word("#![")?,
- ast::AttrStyle::Outer => self.writer().word("#[")?,
+ ast::AttrStyle::Inner => self.writer().word("#!["),
+ ast::AttrStyle::Outer => self.writer().word("#["),
}
if let Some(mi) = attr.meta() {
- self.print_meta_item(&mi)?
+ self.print_meta_item(&mi);
} else {
- self.print_attribute_path(&attr.path)?;
- self.writer().space()?;
- self.print_tts(attr.tokens.clone())?;
+ self.print_attribute_path(&attr.path);
+ self.writer().space();
+ self.print_tts(attr.tokens.clone());
}
- self.writer().word("]")
+ self.writer().word("]");
}
}
- fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()> {
+ fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
match item {
ast::NestedMetaItem::MetaItem(ref mi) => {
self.print_meta_item(mi)
}
}
- fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
- self.ibox(INDENT_UNIT)?;
+ fn print_meta_item(&mut self, item: &ast::MetaItem) {
+ self.ibox(INDENT_UNIT);
match item.node {
- ast::MetaItemKind::Word => self.print_attribute_path(&item.path)?,
+ ast::MetaItemKind::Word => self.print_attribute_path(&item.path),
ast::MetaItemKind::NameValue(ref value) => {
- self.print_attribute_path(&item.path)?;
- self.writer().space()?;
- self.word_space("=")?;
- self.print_literal(value)?;
+ self.print_attribute_path(&item.path);
+ self.writer().space();
+ self.word_space("=");
+ self.print_literal(value);
}
ast::MetaItemKind::List(ref items) => {
- self.print_attribute_path(&item.path)?;
- self.popen()?;
+ self.print_attribute_path(&item.path);
+ self.popen();
self.commasep(Consistent,
&items[..],
- |s, i| s.print_meta_list_item(i))?;
- self.pclose()?;
+ |s, i| s.print_meta_list_item(i));
+ self.pclose();
}
}
- self.end()
+ self.end();
}
/// This doesn't deserve to be called "pretty" printing, but it should be
/// appropriate macro, transcribe back into the grammar we just parsed from,
/// and then pretty-print the resulting AST nodes (so, e.g., we print
/// expression arguments as expressions). It can be done! I think.
- fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> {
+ fn print_tt(&mut self, tt: tokenstream::TokenTree) {
match tt {
TokenTree::Token(ref token) => {
- self.writer().word(token_to_string(&token))?;
+ self.writer().word(token_to_string(&token));
match token.kind {
token::DocComment(..) => {
self.writer().hardbreak()
}
- _ => Ok(())
+ _ => {}
}
}
TokenTree::Delimited(_, delim, tts) => {
- self.writer().word(token_kind_to_string(&token::OpenDelim(delim)))?;
- self.writer().space()?;
- self.print_tts(tts)?;
- self.writer().space()?;
+ self.writer().word(token_kind_to_string(&token::OpenDelim(delim)));
+ self.writer().space();
+ self.print_tts(tts);
+ self.writer().space();
self.writer().word(token_kind_to_string(&token::CloseDelim(delim)))
},
}
}
- fn print_tts(&mut self, tts: tokenstream::TokenStream) -> io::Result<()> {
- self.ibox(0)?;
+ fn print_tts(&mut self, tts: tokenstream::TokenStream) {
+ self.ibox(0);
for (i, tt) in tts.into_trees().enumerate() {
if i != 0 {
- self.writer().space()?;
+ self.writer().space();
}
- self.print_tt(tt)?;
+ self.print_tt(tt);
}
- self.end()
+ self.end();
}
- fn space_if_not_bol(&mut self) -> io::Result<()> {
- if !self.is_bol() { self.writer().space()?; }
- Ok(())
+ fn space_if_not_bol(&mut self) {
+ if !self.is_bol() { self.writer().space(); }
}
- fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") }
+ fn nbsp(&mut self) { self.writer().word(" ") }
// AST pretty-printer is used as a fallback for turning AST structures into token streams for
// proc macros. Additionally, proc macros may stringify their input and expect it survive the
// its hygiene data, most importantly name of the crate it refers to.
// As a result we print `$crate` as `crate` if it refers to the local crate
// and as `::other_crate_name` if it refers to some other crate.
- fn print_dollar_crate(&mut self, ident: ast::Ident) -> io::Result<()> {
+ fn print_dollar_crate(&mut self, ident: ast::Ident) {
let name = ident.span.ctxt().dollar_crate_name();
if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() {
- self.writer().word("::")?;
+ self.writer().word("::");
}
self.writer().word(name.as_str().to_string())
}
}
impl<'a> State<'a> {
- pub fn cbox(&mut self, u: usize) -> io::Result<()> {
+ pub fn cbox(&mut self, u: usize) {
self.boxes.push(pp::Breaks::Consistent);
- self.s.cbox(u)
+ self.s.cbox(u);
}
- pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
- self.s.word(w)?;
+ crate fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) {
+ self.s.word(w);
self.nbsp()
}
- pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
+ crate fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
let w = w.into();
// outer-box is consistent
- self.cbox(INDENT_UNIT)?;
+ self.cbox(INDENT_UNIT);
// head-box is inconsistent
- self.ibox(w.len() + 1)?;
+ self.ibox(w.len() + 1);
// keyword that starts the head
if !w.is_empty() {
- self.word_nbsp(w)?;
+ self.word_nbsp(w);
}
- Ok(())
}
- pub fn bopen(&mut self) -> io::Result<()> {
- self.s.word("{")?;
- self.end() // close the head-box
+ crate fn bopen(&mut self) {
+ self.s.word("{");
+ self.end(); // close the head-box
}
- pub fn bclose_(&mut self, span: syntax_pos::Span,
- indented: usize) -> io::Result<()> {
+ crate fn bclose_(&mut self, span: syntax_pos::Span,
+ indented: usize) {
self.bclose_maybe_open(span, indented, true)
}
- pub fn bclose_maybe_open(&mut self, span: syntax_pos::Span,
- indented: usize, close_box: bool) -> io::Result<()> {
- self.maybe_print_comment(span.hi())?;
- self.break_offset_if_not_bol(1, -(indented as isize))?;
- self.s.word("}")?;
+ crate fn bclose_maybe_open(&mut self, span: syntax_pos::Span,
+ indented: usize, close_box: bool) {
+ self.maybe_print_comment(span.hi());
+ self.break_offset_if_not_bol(1, -(indented as isize));
+ self.s.word("}");
if close_box {
- self.end()?; // close the outer-box
+ self.end(); // close the outer-box
}
- Ok(())
}
- pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> {
+ crate fn bclose(&mut self, span: syntax_pos::Span) {
self.bclose_(span, INDENT_UNIT)
}
- pub fn in_cbox(&self) -> bool {
- match self.boxes.last() {
- Some(&last_box) => last_box == pp::Breaks::Consistent,
- None => false
- }
- }
-
- pub fn break_offset_if_not_bol(&mut self, n: usize,
- off: isize) -> io::Result<()> {
+ crate fn break_offset_if_not_bol(&mut self, n: usize,
+ off: isize) {
if !self.is_bol() {
self.s.break_offset(n, off)
} else {
// break into the previous hardbreak.
self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off));
}
- Ok(())
}
}
// Synthesizes a comment that was not textually present in the original source
// file.
- pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
- self.s.word("/*")?;
- self.s.space()?;
- self.s.word(text)?;
- self.s.space()?;
+ pub fn synth_comment(&mut self, text: String) {
+ self.s.word("/*");
+ self.s.space();
+ self.s.word(text);
+ self.s.space();
self.s.word("*/")
}
- pub fn commasep_cmnt<T, F, G>(&mut self,
+ crate fn commasep_cmnt<T, F, G>(&mut self,
b: Breaks,
elts: &[T],
mut op: F,
- mut get_span: G) -> io::Result<()> where
- F: FnMut(&mut State<'_>, &T) -> io::Result<()>,
+ mut get_span: G) where
+ F: FnMut(&mut State<'_>, &T),
G: FnMut(&T) -> syntax_pos::Span,
{
- self.rbox(0, b)?;
+ self.rbox(0, b);
let len = elts.len();
let mut i = 0;
for elt in elts {
- self.maybe_print_comment(get_span(elt).hi())?;
- op(self, elt)?;
+ self.maybe_print_comment(get_span(elt).hi());
+ op(self, elt);
i += 1;
if i < len {
- self.s.word(",")?;
+ self.s.word(",");
self.maybe_print_trailing_comment(get_span(elt),
- Some(get_span(&elts[i]).hi()))?;
- self.space_if_not_bol()?;
+ Some(get_span(&elts[i]).hi()));
+ self.space_if_not_bol();
}
}
- self.end()
+ self.end();
}
- pub fn commasep_exprs(&mut self, b: Breaks,
- exprs: &[P<ast::Expr>]) -> io::Result<()> {
+ crate fn commasep_exprs(&mut self, b: Breaks,
+ exprs: &[P<ast::Expr>]) {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
}
- pub fn print_mod(&mut self, _mod: &ast::Mod,
- attrs: &[ast::Attribute]) -> io::Result<()> {
- self.print_inner_attributes(attrs)?;
+ crate fn print_mod(&mut self, _mod: &ast::Mod,
+ attrs: &[ast::Attribute]) {
+ self.print_inner_attributes(attrs);
for item in &_mod.items {
- self.print_item(item)?;
+ self.print_item(item);
}
- Ok(())
}
- pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
- attrs: &[ast::Attribute]) -> io::Result<()> {
- self.print_inner_attributes(attrs)?;
+ crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
+ attrs: &[ast::Attribute]) {
+ self.print_inner_attributes(attrs);
for item in &nmod.items {
- self.print_foreign_item(item)?;
+ self.print_foreign_item(item);
}
- Ok(())
}
- pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
+ crate fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) {
if let Some(lt) = *lifetime {
- self.print_lifetime(lt)?;
- self.nbsp()?;
+ self.print_lifetime(lt);
+ self.nbsp();
}
- Ok(())
}
- pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) -> io::Result<()> {
+ crate fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
match generic_arg {
GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
GenericArg::Type(ty) => self.print_type(ty),
}
}
- pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
- self.maybe_print_comment(ty.span.lo())?;
- self.ibox(0)?;
+ crate fn print_type(&mut self, ty: &ast::Ty) {
+ self.maybe_print_comment(ty.span.lo());
+ self.ibox(0);
match ty.node {
ast::TyKind::Slice(ref ty) => {
- self.s.word("[")?;
- self.print_type(ty)?;
- self.s.word("]")?;
+ self.s.word("[");
+ self.print_type(ty);
+ self.s.word("]");
}
ast::TyKind::Ptr(ref mt) => {
- self.s.word("*")?;
+ self.s.word("*");
match mt.mutbl {
- ast::Mutability::Mutable => self.word_nbsp("mut")?,
- ast::Mutability::Immutable => self.word_nbsp("const")?,
+ ast::Mutability::Mutable => self.word_nbsp("mut"),
+ ast::Mutability::Immutable => self.word_nbsp("const"),
}
- self.print_type(&mt.ty)?;
+ self.print_type(&mt.ty);
}
ast::TyKind::Rptr(ref lifetime, ref mt) => {
- self.s.word("&")?;
- self.print_opt_lifetime(lifetime)?;
- self.print_mt(mt)?;
+ self.s.word("&");
+ self.print_opt_lifetime(lifetime);
+ self.print_mt(mt);
}
ast::TyKind::Never => {
- self.s.word("!")?;
+ self.s.word("!");
},
ast::TyKind::Tup(ref elts) => {
- self.popen()?;
+ self.popen();
self.commasep(Inconsistent, &elts[..],
- |s, ty| s.print_type(ty))?;
+ |s, ty| s.print_type(ty));
if elts.len() == 1 {
- self.s.word(",")?;
+ self.s.word(",");
}
- self.pclose()?;
+ self.pclose();
}
ast::TyKind::Paren(ref typ) => {
- self.popen()?;
- self.print_type(typ)?;
- self.pclose()?;
+ self.popen();
+ self.print_type(typ);
+ self.pclose();
}
ast::TyKind::BareFn(ref f) => {
self.print_ty_fn(f.abi,
f.unsafety,
&f.decl,
None,
- &f.generic_params)?;
+ &f.generic_params);
}
ast::TyKind::Path(None, ref path) => {
- self.print_path(path, false, 0)?;
+ self.print_path(path, false, 0);
}
ast::TyKind::Path(Some(ref qself), ref path) => {
- self.print_qpath(path, qself, false)?
+ self.print_qpath(path, qself, false)
}
ast::TyKind::TraitObject(ref bounds, syntax) => {
let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" };
- self.print_type_bounds(prefix, &bounds[..])?;
+ self.print_type_bounds(prefix, &bounds[..]);
}
ast::TyKind::ImplTrait(_, ref bounds) => {
- self.print_type_bounds("impl", &bounds[..])?;
+ self.print_type_bounds("impl", &bounds[..]);
}
ast::TyKind::Array(ref ty, ref length) => {
- self.s.word("[")?;
- self.print_type(ty)?;
- self.s.word("; ")?;
- self.print_expr(&length.value)?;
- self.s.word("]")?;
+ self.s.word("[");
+ self.print_type(ty);
+ self.s.word("; ");
+ self.print_expr(&length.value);
+ self.s.word("]");
}
ast::TyKind::Typeof(ref e) => {
- self.s.word("typeof(")?;
- self.print_expr(&e.value)?;
- self.s.word(")")?;
+ self.s.word("typeof(");
+ self.print_expr(&e.value);
+ self.s.word(")");
}
ast::TyKind::Infer => {
- self.s.word("_")?;
+ self.s.word("_");
}
ast::TyKind::Err => {
- self.popen()?;
- self.s.word("/*ERROR*/")?;
- self.pclose()?;
+ self.popen();
+ self.s.word("/*ERROR*/");
+ self.pclose();
}
ast::TyKind::ImplicitSelf => {
- self.s.word("Self")?;
+ self.s.word("Self");
}
ast::TyKind::Mac(ref m) => {
- self.print_mac(m)?;
+ self.print_mac(m);
}
ast::TyKind::CVarArgs => {
- self.s.word("...")?;
+ self.s.word("...");
}
}
- self.end()
+ self.end();
}
- pub fn print_foreign_item(&mut self,
- item: &ast::ForeignItem) -> io::Result<()> {
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(item.span.lo())?;
- self.print_outer_attributes(&item.attrs)?;
+ crate fn print_foreign_item(&mut self,
+ item: &ast::ForeignItem) {
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(item.span.lo());
+ self.print_outer_attributes(&item.attrs);
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
- self.head("")?;
+ self.head("");
self.print_fn(decl, ast::FnHeader::default(),
Some(item.ident),
- generics, &item.vis)?;
- self.end()?; // end head-ibox
- self.s.word(";")?;
- self.end() // end the outer fn box
+ generics, &item.vis);
+ self.end(); // end head-ibox
+ self.s.word(";");
+ self.end(); // end the outer fn box
}
ast::ForeignItemKind::Static(ref t, m) => {
- self.head(visibility_qualified(&item.vis, "static"))?;
+ self.head(visibility_qualified(&item.vis, "static"));
if m == ast::Mutability::Mutable {
- self.word_space("mut")?;
+ self.word_space("mut");
}
- self.print_ident(item.ident)?;
- self.word_space(":")?;
- self.print_type(t)?;
- self.s.word(";")?;
- self.end()?; // end the head-ibox
- self.end() // end the outer cbox
+ self.print_ident(item.ident);
+ self.word_space(":");
+ self.print_type(t);
+ self.s.word(";");
+ self.end(); // end the head-ibox
+ self.end(); // end the outer cbox
}
ast::ForeignItemKind::Ty => {
- self.head(visibility_qualified(&item.vis, "type"))?;
- self.print_ident(item.ident)?;
- self.s.word(";")?;
- self.end()?; // end the head-ibox
- self.end() // end the outer cbox
+ self.head(visibility_qualified(&item.vis, "type"));
+ self.print_ident(item.ident);
+ self.s.word(";");
+ self.end(); // end the head-ibox
+ self.end(); // end the outer cbox
}
ast::ForeignItemKind::Macro(ref m) => {
- self.print_mac(m)?;
+ self.print_mac(m);
match m.node.delim {
- MacDelimiter::Brace => Ok(()),
+ MacDelimiter::Brace => {},
_ => self.s.word(";")
}
}
ty: &ast::Ty,
default: Option<&ast::Expr>,
vis: &ast::Visibility)
- -> io::Result<()>
{
- self.s.word(visibility_qualified(vis, ""))?;
- self.word_space("const")?;
- self.print_ident(ident)?;
- self.word_space(":")?;
- self.print_type(ty)?;
+ self.s.word(visibility_qualified(vis, ""));
+ self.word_space("const");
+ self.print_ident(ident);
+ self.word_space(":");
+ self.print_type(ty);
if let Some(expr) = default {
- self.s.space()?;
- self.word_space("=")?;
- self.print_expr(expr)?;
+ self.s.space();
+ self.word_space("=");
+ self.print_expr(expr);
}
self.s.word(";")
}
ident: ast::Ident,
bounds: Option<&ast::GenericBounds>,
ty: Option<&ast::Ty>)
- -> io::Result<()> {
- self.word_space("type")?;
- self.print_ident(ident)?;
+ {
+ self.word_space("type");
+ self.print_ident(ident);
if let Some(bounds) = bounds {
- self.print_type_bounds(":", bounds)?;
+ self.print_type_bounds(":", bounds);
}
if let Some(ty) = ty {
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(ty)?;
+ self.s.space();
+ self.word_space("=");
+ self.print_type(ty);
}
self.s.word(";")
}
/// Pretty-print an item
- pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(item.span.lo())?;
- self.print_outer_attributes(&item.attrs)?;
- self.ann.pre(self, AnnNode::Item(item))?;
+ crate fn print_item(&mut self, item: &ast::Item) {
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(item.span.lo());
+ self.print_outer_attributes(&item.attrs);
+ self.ann.pre(self, AnnNode::Item(item));
match item.node {
ast::ItemKind::ExternCrate(orig_name) => {
- self.head(visibility_qualified(&item.vis, "extern crate"))?;
+ self.head(visibility_qualified(&item.vis, "extern crate"));
if let Some(orig_name) = orig_name {
- self.print_name(orig_name)?;
- self.s.space()?;
- self.s.word("as")?;
- self.s.space()?;
+ self.print_name(orig_name);
+ self.s.space();
+ self.s.word("as");
+ self.s.space();
}
- self.print_ident(item.ident)?;
- self.s.word(";")?;
- self.end()?; // end inner head-block
- self.end()?; // end outer head-block
+ self.print_ident(item.ident);
+ self.s.word(";");
+ self.end(); // end inner head-block
+ self.end(); // end outer head-block
}
ast::ItemKind::Use(ref tree) => {
- self.head(visibility_qualified(&item.vis, "use"))?;
- self.print_use_tree(tree)?;
- self.s.word(";")?;
- self.end()?; // end inner head-block
- self.end()?; // end outer head-block
+ self.head(visibility_qualified(&item.vis, "use"));
+ self.print_use_tree(tree);
+ self.s.word(";");
+ self.end(); // end inner head-block
+ self.end(); // end outer head-block
}
ast::ItemKind::Static(ref ty, m, ref expr) => {
- self.head(visibility_qualified(&item.vis, "static"))?;
+ self.head(visibility_qualified(&item.vis, "static"));
if m == ast::Mutability::Mutable {
- self.word_space("mut")?;
+ self.word_space("mut");
}
- self.print_ident(item.ident)?;
- self.word_space(":")?;
- self.print_type(ty)?;
- self.s.space()?;
- self.end()?; // end the head-ibox
+ self.print_ident(item.ident);
+ self.word_space(":");
+ self.print_type(ty);
+ self.s.space();
+ self.end(); // end the head-ibox
- self.word_space("=")?;
- self.print_expr(expr)?;
- self.s.word(";")?;
- self.end()?; // end the outer cbox
+ self.word_space("=");
+ self.print_expr(expr);
+ self.s.word(";");
+ self.end(); // end the outer cbox
}
ast::ItemKind::Const(ref ty, ref expr) => {
- self.head(visibility_qualified(&item.vis, "const"))?;
- self.print_ident(item.ident)?;
- self.word_space(":")?;
- self.print_type(ty)?;
- self.s.space()?;
- self.end()?; // end the head-ibox
-
- self.word_space("=")?;
- self.print_expr(expr)?;
- self.s.word(";")?;
- self.end()?; // end the outer cbox
+ self.head(visibility_qualified(&item.vis, "const"));
+ self.print_ident(item.ident);
+ self.word_space(":");
+ self.print_type(ty);
+ self.s.space();
+ self.end(); // end the head-ibox
+
+ self.word_space("=");
+ self.print_expr(expr);
+ self.s.word(";");
+ self.end(); // end the outer cbox
}
ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => {
- self.head("")?;
+ self.head("");
self.print_fn(
decl,
header,
Some(item.ident),
param_names,
&item.vis
- )?;
- self.s.word(" ")?;
- self.print_block_with_attrs(body, &item.attrs)?;
+ );
+ self.s.word(" ");
+ self.print_block_with_attrs(body, &item.attrs);
}
ast::ItemKind::Mod(ref _mod) => {
- self.head(visibility_qualified(&item.vis, "mod"))?;
- self.print_ident(item.ident)?;
+ self.head(visibility_qualified(&item.vis, "mod"));
+ self.print_ident(item.ident);
if _mod.inline || self.is_expanded {
- self.nbsp()?;
- self.bopen()?;
- self.print_mod(_mod, &item.attrs)?;
- self.bclose(item.span)?;
+ self.nbsp();
+ self.bopen();
+ self.print_mod(_mod, &item.attrs);
+ self.bclose(item.span);
} else {
- self.s.word(";")?;
- self.end()?; // end inner head-block
- self.end()?; // end outer head-block
+ self.s.word(";");
+ self.end(); // end inner head-block
+ self.end(); // end outer head-block
}
}
ast::ItemKind::ForeignMod(ref nmod) => {
- self.head("extern")?;
- self.word_nbsp(nmod.abi.to_string())?;
- self.bopen()?;
- self.print_foreign_mod(nmod, &item.attrs)?;
- self.bclose(item.span)?;
+ self.head("extern");
+ self.word_nbsp(nmod.abi.to_string());
+ self.bopen();
+ self.print_foreign_mod(nmod, &item.attrs);
+ self.bclose(item.span);
}
ast::ItemKind::GlobalAsm(ref ga) => {
- self.head(visibility_qualified(&item.vis, "global_asm!"))?;
- self.s.word(ga.asm.as_str().to_string())?;
- self.end()?;
+ self.head(visibility_qualified(&item.vis, "global_asm!"));
+ self.s.word(ga.asm.as_str().to_string());
+ self.end();
}
ast::ItemKind::Ty(ref ty, ref generics) => {
- self.head(visibility_qualified(&item.vis, "type"))?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
- self.end()?; // end the inner ibox
-
- self.print_where_clause(&generics.where_clause)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(ty)?;
- self.s.word(";")?;
- self.end()?; // end the outer ibox
+ self.head(visibility_qualified(&item.vis, "type"));
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
+ self.end(); // end the inner ibox
+
+ self.print_where_clause(&generics.where_clause);
+ self.s.space();
+ self.word_space("=");
+ self.print_type(ty);
+ self.s.word(";");
+ self.end(); // end the outer ibox
}
ast::ItemKind::Existential(ref bounds, ref generics) => {
- self.head(visibility_qualified(&item.vis, "existential type"))?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
- self.end()?; // end the inner ibox
+ self.head(visibility_qualified(&item.vis, "existential type"));
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
+ self.end(); // end the inner ibox
- self.print_where_clause(&generics.where_clause)?;
- self.s.space()?;
- self.print_type_bounds(":", bounds)?;
- self.s.word(";")?;
- self.end()?; // end the outer ibox
+ self.print_where_clause(&generics.where_clause);
+ self.s.space();
+ self.print_type_bounds(":", bounds);
+ self.s.word(";");
+ self.end(); // end the outer ibox
}
ast::ItemKind::Enum(ref enum_definition, ref params) => {
self.print_enum_def(
item.ident,
item.span,
&item.vis
- )?;
+ );
}
ast::ItemKind::Struct(ref struct_def, ref generics) => {
- self.head(visibility_qualified(&item.vis, "struct"))?;
- self.print_struct(struct_def, generics, item.ident, item.span, true)?;
+ self.head(visibility_qualified(&item.vis, "struct"));
+ self.print_struct(struct_def, generics, item.ident, item.span, true);
}
ast::ItemKind::Union(ref struct_def, ref generics) => {
- self.head(visibility_qualified(&item.vis, "union"))?;
- self.print_struct(struct_def, generics, item.ident, item.span, true)?;
+ self.head(visibility_qualified(&item.vis, "union"));
+ self.print_struct(struct_def, generics, item.ident, item.span, true);
}
ast::ItemKind::Impl(unsafety,
polarity,
ref opt_trait,
ref ty,
ref impl_items) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_defaultness(defaultness)?;
- self.print_unsafety(unsafety)?;
- self.word_nbsp("impl")?;
+ self.head("");
+ self.print_visibility(&item.vis);
+ self.print_defaultness(defaultness);
+ self.print_unsafety(unsafety);
+ self.word_nbsp("impl");
if !generics.params.is_empty() {
- self.print_generic_params(&generics.params)?;
- self.s.space()?;
+ self.print_generic_params(&generics.params);
+ self.s.space();
}
if polarity == ast::ImplPolarity::Negative {
- self.s.word("!")?;
+ self.s.word("!");
}
if let Some(ref t) = *opt_trait {
- self.print_trait_ref(t)?;
- self.s.space()?;
- self.word_space("for")?;
+ self.print_trait_ref(t);
+ self.s.space();
+ self.word_space("for");
}
- self.print_type(ty)?;
- self.print_where_clause(&generics.where_clause)?;
+ self.print_type(ty);
+ self.print_where_clause(&generics.where_clause);
- self.s.space()?;
- self.bopen()?;
- self.print_inner_attributes(&item.attrs)?;
+ self.s.space();
+ self.bopen();
+ self.print_inner_attributes(&item.attrs);
for impl_item in impl_items {
- self.print_impl_item(impl_item)?;
+ self.print_impl_item(impl_item);
}
- self.bclose(item.span)?;
+ self.bclose(item.span);
}
ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.print_unsafety(unsafety)?;
- self.print_is_auto(is_auto)?;
- self.word_nbsp("trait")?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
+ self.head("");
+ self.print_visibility(&item.vis);
+ self.print_unsafety(unsafety);
+ self.print_is_auto(is_auto);
+ self.word_nbsp("trait");
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
- self.s.space()?;
- self.word_space("for ?")?;
- self.print_trait_ref(&ptr.trait_ref)?;
+ self.s.space();
+ self.word_space("for ?");
+ self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b.clone());
}
}
- self.print_type_bounds(":", &real_bounds[..])?;
- self.print_where_clause(&generics.where_clause)?;
- self.s.word(" ")?;
- self.bopen()?;
+ self.print_type_bounds(":", &real_bounds[..]);
+ self.print_where_clause(&generics.where_clause);
+ self.s.word(" ");
+ self.bopen();
for trait_item in trait_items {
- self.print_trait_item(trait_item)?;
+ self.print_trait_item(trait_item);
}
- self.bclose(item.span)?;
+ self.bclose(item.span);
}
ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
- self.head("")?;
- self.print_visibility(&item.vis)?;
- self.word_nbsp("trait")?;
- self.print_ident(item.ident)?;
- self.print_generic_params(&generics.params)?;
+ self.head("");
+ self.print_visibility(&item.vis);
+ self.word_nbsp("trait");
+ self.print_ident(item.ident);
+ self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
- self.s.space()?;
- self.word_space("for ?")?;
- self.print_trait_ref(&ptr.trait_ref)?;
+ self.s.space();
+ self.word_space("for ?");
+ self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b.clone());
}
}
- self.nbsp()?;
- self.print_type_bounds("=", &real_bounds[..])?;
- self.print_where_clause(&generics.where_clause)?;
- self.s.word(";")?;
+ self.nbsp();
+ self.print_type_bounds("=", &real_bounds[..]);
+ self.print_where_clause(&generics.where_clause);
+ self.s.word(";");
}
ast::ItemKind::Mac(ref mac) => {
if item.ident.name == kw::Invalid {
- self.print_mac(mac)?;
+ self.print_mac(mac);
match mac.node.delim {
MacDelimiter::Brace => {}
- _ => self.s.word(";")?,
+ _ => self.s.word(";"),
}
} else {
- self.print_path(&mac.node.path, false, 0)?;
- self.s.word("! ")?;
- self.print_ident(item.ident)?;
- self.cbox(INDENT_UNIT)?;
- self.popen()?;
- self.print_tts(mac.node.stream())?;
- self.pclose()?;
- self.s.word(";")?;
- self.end()?;
+ self.print_path(&mac.node.path, false, 0);
+ self.s.word("! ");
+ self.print_ident(item.ident);
+ self.cbox(INDENT_UNIT);
+ self.popen();
+ self.print_tts(mac.node.stream());
+ self.pclose();
+ self.s.word(";");
+ self.end();
}
}
ast::ItemKind::MacroDef(ref tts) => {
- self.s.word("macro_rules! ")?;
- self.print_ident(item.ident)?;
- self.cbox(INDENT_UNIT)?;
- self.popen()?;
- self.print_tts(tts.stream())?;
- self.pclose()?;
- self.s.word(";")?;
- self.end()?;
+ self.s.word("macro_rules! ");
+ self.print_ident(item.ident);
+ self.cbox(INDENT_UNIT);
+ self.popen();
+ self.print_tts(tts.stream());
+ self.pclose();
+ self.s.word(";");
+ self.end();
}
}
self.ann.post(self, AnnNode::Item(item))
}
- fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
+ fn print_trait_ref(&mut self, t: &ast::TraitRef) {
self.print_path(&t.path, false, 0)
}
fn print_formal_generic_params(
&mut self,
generic_params: &[ast::GenericParam]
- ) -> io::Result<()> {
+ ) {
if !generic_params.is_empty() {
- self.s.word("for")?;
- self.print_generic_params(generic_params)?;
- self.nbsp()?;
+ self.s.word("for");
+ self.print_generic_params(generic_params);
+ self.nbsp();
}
- Ok(())
}
- fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> {
- self.print_formal_generic_params(&t.bound_generic_params)?;
+ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
+ self.print_formal_generic_params(&t.bound_generic_params);
self.print_trait_ref(&t.trait_ref)
}
- pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
+ crate fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
generics: &ast::Generics, ident: ast::Ident,
span: syntax_pos::Span,
- visibility: &ast::Visibility) -> io::Result<()> {
- self.head(visibility_qualified(visibility, "enum"))?;
- self.print_ident(ident)?;
- self.print_generic_params(&generics.params)?;
- self.print_where_clause(&generics.where_clause)?;
- self.s.space()?;
+ visibility: &ast::Visibility) {
+ self.head(visibility_qualified(visibility, "enum"));
+ self.print_ident(ident);
+ self.print_generic_params(&generics.params);
+ self.print_where_clause(&generics.where_clause);
+ self.s.space();
self.print_variants(&enum_definition.variants, span)
}
- pub fn print_variants(&mut self,
+ crate fn print_variants(&mut self,
variants: &[ast::Variant],
- span: syntax_pos::Span) -> io::Result<()> {
- self.bopen()?;
+ span: syntax_pos::Span) {
+ self.bopen();
for v in variants {
- self.space_if_not_bol()?;
- self.maybe_print_comment(v.span.lo())?;
- self.print_outer_attributes(&v.node.attrs)?;
- self.ibox(INDENT_UNIT)?;
- self.print_variant(v)?;
- self.s.word(",")?;
- self.end()?;
- self.maybe_print_trailing_comment(v.span, None)?;
+ self.space_if_not_bol();
+ self.maybe_print_comment(v.span.lo());
+ self.print_outer_attributes(&v.node.attrs);
+ self.ibox(INDENT_UNIT);
+ self.print_variant(v);
+ self.s.word(",");
+ self.end();
+ self.maybe_print_trailing_comment(v.span, None);
}
self.bclose(span)
}
- pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
+ crate fn print_visibility(&mut self, vis: &ast::Visibility) {
match vis.node {
ast::VisibilityKind::Public => self.word_nbsp("pub"),
ast::VisibilityKind::Crate(sugar) => match sugar {
self.word_nbsp(format!("pub(in {})", path))
}
}
- ast::VisibilityKind::Inherited => Ok(())
+ ast::VisibilityKind::Inherited => {}
}
}
- pub fn print_defaultness(&mut self, defaultness: ast::Defaultness) -> io::Result<()> {
+ crate fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
if let ast::Defaultness::Default = defaultness {
- self.word_nbsp("default")?;
+ self.word_nbsp("default");
}
- Ok(())
}
- pub fn print_struct(&mut self,
+ crate fn print_struct(&mut self,
struct_def: &ast::VariantData,
generics: &ast::Generics,
ident: ast::Ident,
span: syntax_pos::Span,
- print_finalizer: bool) -> io::Result<()> {
- self.print_ident(ident)?;
- self.print_generic_params(&generics.params)?;
+ print_finalizer: bool) {
+ self.print_ident(ident);
+ self.print_generic_params(&generics.params);
match struct_def {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
if let ast::VariantData::Tuple(..) = struct_def {
- self.popen()?;
+ self.popen();
self.commasep(
Inconsistent, struct_def.fields(),
|s, field| {
- s.maybe_print_comment(field.span.lo())?;
- s.print_outer_attributes(&field.attrs)?;
- s.print_visibility(&field.vis)?;
+ s.maybe_print_comment(field.span.lo());
+ s.print_outer_attributes(&field.attrs);
+ s.print_visibility(&field.vis);
s.print_type(&field.ty)
}
- )?;
- self.pclose()?;
+ );
+ self.pclose();
}
- self.print_where_clause(&generics.where_clause)?;
+ self.print_where_clause(&generics.where_clause);
if print_finalizer {
- self.s.word(";")?;
+ self.s.word(";");
}
- self.end()?;
- self.end() // close the outer-box
+ self.end();
+ self.end(); // close the outer-box
}
ast::VariantData::Struct(..) => {
- self.print_where_clause(&generics.where_clause)?;
- self.nbsp()?;
- self.bopen()?;
- self.hardbreak_if_not_bol()?;
+ self.print_where_clause(&generics.where_clause);
+ self.nbsp();
+ self.bopen();
+ self.hardbreak_if_not_bol();
for field in struct_def.fields() {
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(field.span.lo())?;
- self.print_outer_attributes(&field.attrs)?;
- self.print_visibility(&field.vis)?;
- self.print_ident(field.ident.unwrap())?;
- self.word_nbsp(":")?;
- self.print_type(&field.ty)?;
- self.s.word(",")?;
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(field.span.lo());
+ self.print_outer_attributes(&field.attrs);
+ self.print_visibility(&field.vis);
+ self.print_ident(field.ident.unwrap());
+ self.word_nbsp(":");
+ self.print_type(&field.ty);
+ self.s.word(",");
}
self.bclose(span)
}
}
- pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
- self.head("")?;
+ crate fn print_variant(&mut self, v: &ast::Variant) {
+ self.head("");
let generics = ast::Generics::default();
- self.print_struct(&v.node.data, &generics, v.node.ident, v.span, false)?;
+ self.print_struct(&v.node.data, &generics, v.node.ident, v.span, false);
match v.node.disr_expr {
Some(ref d) => {
- self.s.space()?;
- self.word_space("=")?;
+ self.s.space();
+ self.word_space("=");
self.print_expr(&d.value)
}
- _ => Ok(())
+ _ => {}
}
}
- pub fn print_method_sig(&mut self,
+ crate fn print_method_sig(&mut self,
ident: ast::Ident,
generics: &ast::Generics,
m: &ast::MethodSig,
vis: &ast::Visibility)
- -> io::Result<()> {
+ {
self.print_fn(&m.decl,
m.header,
Some(ident),
vis)
}
- pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
- -> io::Result<()> {
- self.ann.pre(self, AnnNode::SubItem(ti.id))?;
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(ti.span.lo())?;
- self.print_outer_attributes(&ti.attrs)?;
+ crate fn print_trait_item(&mut self, ti: &ast::TraitItem)
+ {
+ self.ann.pre(self, AnnNode::SubItem(ti.id));
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(ti.span.lo());
+ self.print_outer_attributes(&ti.attrs);
match ti.node {
ast::TraitItemKind::Const(ref ty, ref default) => {
self.print_associated_const(
ty,
default.as_ref().map(|expr| &**expr),
&source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
- )?;
+ );
}
ast::TraitItemKind::Method(ref sig, ref body) => {
if body.is_some() {
- self.head("")?;
+ self.head("");
}
self.print_method_sig(
ti.ident,
&ti.generics,
sig,
&source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
- )?;
+ );
if let Some(ref body) = *body {
- self.nbsp()?;
- self.print_block_with_attrs(body, &ti.attrs)?;
+ self.nbsp();
+ self.print_block_with_attrs(body, &ti.attrs);
} else {
- self.s.word(";")?;
+ self.s.word(";");
}
}
ast::TraitItemKind::Type(ref bounds, ref default) => {
self.print_associated_type(ti.ident, Some(bounds),
- default.as_ref().map(|ty| &**ty))?;
+ default.as_ref().map(|ty| &**ty));
}
ast::TraitItemKind::Macro(ref mac) => {
- self.print_mac(mac)?;
+ self.print_mac(mac);
match mac.node.delim {
MacDelimiter::Brace => {}
- _ => self.s.word(";")?,
+ _ => self.s.word(";"),
}
}
}
self.ann.post(self, AnnNode::SubItem(ti.id))
}
- pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
- self.ann.pre(self, AnnNode::SubItem(ii.id))?;
- self.hardbreak_if_not_bol()?;
- self.maybe_print_comment(ii.span.lo())?;
- self.print_outer_attributes(&ii.attrs)?;
- self.print_defaultness(ii.defaultness)?;
+ crate fn print_impl_item(&mut self, ii: &ast::ImplItem) {
+ self.ann.pre(self, AnnNode::SubItem(ii.id));
+ self.hardbreak_if_not_bol();
+ self.maybe_print_comment(ii.span.lo());
+ self.print_outer_attributes(&ii.attrs);
+ self.print_defaultness(ii.defaultness);
match ii.node {
ast::ImplItemKind::Const(ref ty, ref expr) => {
- self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis)?;
+ self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis);
}
ast::ImplItemKind::Method(ref sig, ref body) => {
- self.head("")?;
- self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis)?;
- self.nbsp()?;
- self.print_block_with_attrs(body, &ii.attrs)?;
+ self.head("");
+ self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis);
+ self.nbsp();
+ self.print_block_with_attrs(body, &ii.attrs);
}
ast::ImplItemKind::Type(ref ty) => {
- self.print_associated_type(ii.ident, None, Some(ty))?;
+ self.print_associated_type(ii.ident, None, Some(ty));
}
ast::ImplItemKind::Existential(ref bounds) => {
- self.word_space("existential")?;
- self.print_associated_type(ii.ident, Some(bounds), None)?;
+ self.word_space("existential");
+ self.print_associated_type(ii.ident, Some(bounds), None);
}
ast::ImplItemKind::Macro(ref mac) => {
- self.print_mac(mac)?;
+ self.print_mac(mac);
match mac.node.delim {
MacDelimiter::Brace => {}
- _ => self.s.word(";")?,
+ _ => self.s.word(";"),
}
}
}
self.ann.post(self, AnnNode::SubItem(ii.id))
}
- pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
- self.maybe_print_comment(st.span.lo())?;
+ crate fn print_stmt(&mut self, st: &ast::Stmt) {
+ self.maybe_print_comment(st.span.lo());
match st.node {
ast::StmtKind::Local(ref loc) => {
- self.print_outer_attributes(&loc.attrs)?;
- self.space_if_not_bol()?;
- self.ibox(INDENT_UNIT)?;
- self.word_nbsp("let")?;
-
- self.ibox(INDENT_UNIT)?;
- self.print_local_decl(loc)?;
- self.end()?;
+ self.print_outer_attributes(&loc.attrs);
+ self.space_if_not_bol();
+ self.ibox(INDENT_UNIT);
+ self.word_nbsp("let");
+
+ self.ibox(INDENT_UNIT);
+ self.print_local_decl(loc);
+ self.end();
if let Some(ref init) = loc.init {
- self.nbsp()?;
- self.word_space("=")?;
- self.print_expr(init)?;
+ self.nbsp();
+ self.word_space("=");
+ self.print_expr(init);
}
- self.s.word(";")?;
- self.end()?;
+ self.s.word(";");
+ self.end();
}
- ast::StmtKind::Item(ref item) => self.print_item(item)?,
+ ast::StmtKind::Item(ref item) => self.print_item(item),
ast::StmtKind::Expr(ref expr) => {
- self.space_if_not_bol()?;
- self.print_expr_outer_attr_style(expr, false)?;
+ self.space_if_not_bol();
+ self.print_expr_outer_attr_style(expr, false);
if parse::classify::expr_requires_semi_to_be_stmt(expr) {
- self.s.word(";")?;
+ self.s.word(";");
}
}
ast::StmtKind::Semi(ref expr) => {
- self.space_if_not_bol()?;
- self.print_expr_outer_attr_style(expr, false)?;
- self.s.word(";")?;
+ self.space_if_not_bol();
+ self.print_expr_outer_attr_style(expr, false);
+ self.s.word(";");
}
ast::StmtKind::Mac(ref mac) => {
let (ref mac, style, ref attrs) = **mac;
- self.space_if_not_bol()?;
- self.print_outer_attributes(attrs)?;
- self.print_mac(mac)?;
+ self.space_if_not_bol();
+ self.print_outer_attributes(attrs);
+ self.print_mac(mac);
if style == ast::MacStmtStyle::Semicolon {
- self.s.word(";")?;
+ self.s.word(";");
}
}
}
self.maybe_print_trailing_comment(st.span, None)
}
- pub fn print_block(&mut self, blk: &ast::Block) -> io::Result<()> {
+ crate fn print_block(&mut self, blk: &ast::Block) {
self.print_block_with_attrs(blk, &[])
}
- pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> io::Result<()> {
- self.print_block_unclosed_indent(blk, INDENT_UNIT)
- }
-
- pub fn print_block_unclosed_with_attrs(&mut self, blk: &ast::Block,
- attrs: &[ast::Attribute])
- -> io::Result<()> {
- self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, false)
- }
-
- pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block,
- indented: usize) -> io::Result<()> {
+ crate fn print_block_unclosed_indent(&mut self, blk: &ast::Block,
+ indented: usize) {
self.print_block_maybe_unclosed(blk, indented, &[], false)
}
- pub fn print_block_with_attrs(&mut self,
+ crate fn print_block_with_attrs(&mut self,
blk: &ast::Block,
- attrs: &[ast::Attribute]) -> io::Result<()> {
+ attrs: &[ast::Attribute]) {
self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, true)
}
- pub fn print_block_maybe_unclosed(&mut self,
+ crate fn print_block_maybe_unclosed(&mut self,
blk: &ast::Block,
indented: usize,
attrs: &[ast::Attribute],
- close_box: bool) -> io::Result<()> {
+ close_box: bool) {
match blk.rules {
- BlockCheckMode::Unsafe(..) => self.word_space("unsafe")?,
+ BlockCheckMode::Unsafe(..) => self.word_space("unsafe"),
BlockCheckMode::Default => ()
}
- self.maybe_print_comment(blk.span.lo())?;
- self.ann.pre(self, AnnNode::Block(blk))?;
- self.bopen()?;
+ self.maybe_print_comment(blk.span.lo());
+ self.ann.pre(self, AnnNode::Block(blk));
+ self.bopen();
- self.print_inner_attributes(attrs)?;
+ self.print_inner_attributes(attrs);
for (i, st) in blk.stmts.iter().enumerate() {
match st.node {
ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => {
- self.maybe_print_comment(st.span.lo())?;
- self.space_if_not_bol()?;
- self.print_expr_outer_attr_style(expr, false)?;
- self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?;
+ self.maybe_print_comment(st.span.lo());
+ self.space_if_not_bol();
+ self.print_expr_outer_attr_style(expr, false);
+ self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
}
- _ => self.print_stmt(st)?,
+ _ => self.print_stmt(st),
}
}
- self.bclose_maybe_open(blk.span, indented, close_box)?;
+ self.bclose_maybe_open(blk.span, indented, close_box);
self.ann.post(self, AnnNode::Block(blk))
}
/// Print a `let pats = scrutinee` expression.
- pub fn print_let(&mut self, pats: &[P<ast::Pat>], scrutinee: &ast::Expr) -> io::Result<()> {
- self.s.word("let ")?;
+ crate fn print_let(&mut self, pats: &[P<ast::Pat>], scrutinee: &ast::Expr) {
+ self.s.word("let ");
- self.print_pats(pats)?;
- self.s.space()?;
+ self.print_pats(pats);
+ self.s.space();
- self.word_space("=")?;
+ self.word_space("=");
self.print_expr_cond_paren(
scrutinee,
Self::cond_needs_par(scrutinee)
)
}
- fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
+ fn print_else(&mut self, els: Option<&ast::Expr>) {
match els {
Some(_else) => {
match _else.node {
// Another `else if` block.
ast::ExprKind::If(ref i, ref then, ref e) => {
- self.cbox(INDENT_UNIT - 1)?;
- self.ibox(0)?;
- self.s.word(" else if ")?;
- self.print_expr_as_cond(i)?;
- self.s.space()?;
- self.print_block(then)?;
+ self.cbox(INDENT_UNIT - 1);
+ self.ibox(0);
+ self.s.word(" else if ");
+ self.print_expr_as_cond(i);
+ self.s.space();
+ self.print_block(then);
self.print_else(e.as_ref().map(|e| &**e))
}
// Final `else` block.
ast::ExprKind::Block(ref b, _) => {
- self.cbox(INDENT_UNIT - 1)?;
- self.ibox(0)?;
- self.s.word(" else ")?;
+ self.cbox(INDENT_UNIT - 1);
+ self.ibox(0);
+ self.s.word(" else ");
self.print_block(b)
}
// Constraints would be great here!
}
}
}
- _ => Ok(())
+ _ => {}
}
}
- pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
- elseopt: Option<&ast::Expr>) -> io::Result<()> {
- self.head("if")?;
+ crate fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
+ elseopt: Option<&ast::Expr>) {
+ self.head("if");
- self.print_expr_as_cond(test)?;
- self.s.space()?;
+ self.print_expr_as_cond(test);
+ self.s.space();
- self.print_block(blk)?;
+ self.print_block(blk);
self.print_else(elseopt)
}
- pub fn print_mac(&mut self, m: &ast::Mac) -> io::Result<()> {
- self.print_path(&m.node.path, false, 0)?;
- self.s.word("!")?;
+ crate fn print_mac(&mut self, m: &ast::Mac) {
+ self.print_path(&m.node.path, false, 0);
+ self.s.word("!");
match m.node.delim {
- MacDelimiter::Parenthesis => self.popen()?,
- MacDelimiter::Bracket => self.s.word("[")?,
+ MacDelimiter::Parenthesis => self.popen(),
+ MacDelimiter::Bracket => self.s.word("["),
MacDelimiter::Brace => {
- self.head("")?;
- self.bopen()?;
+ self.head("");
+ self.bopen();
}
}
- self.print_tts(m.node.stream())?;
+ self.print_tts(m.node.stream());
match m.node.delim {
MacDelimiter::Parenthesis => self.pclose(),
MacDelimiter::Bracket => self.s.word("]"),
}
- fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> {
- self.popen()?;
- self.commasep_exprs(Inconsistent, args)?;
+ fn print_call_post(&mut self, args: &[P<ast::Expr>]) {
+ self.popen();
+ self.commasep_exprs(Inconsistent, args);
self.pclose()
}
- pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) -> io::Result<()> {
+ crate fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) {
self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
}
/// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
/// `if cond { ... }`.
- pub fn print_expr_as_cond(&mut self, expr: &ast::Expr) -> io::Result<()> {
+ crate fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
}
}
/// Print `expr` or `(expr)` when `needs_par` holds.
- fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) -> io::Result<()> {
+ fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
if needs_par {
- self.popen()?;
+ self.popen();
}
- self.print_expr(expr)?;
+ self.print_expr(expr);
if needs_par {
- self.pclose()?;
+ self.pclose();
}
- Ok(())
}
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>],
- attrs: &[Attribute]) -> io::Result<()> {
- self.ibox(INDENT_UNIT)?;
- self.s.word("[")?;
- self.print_inner_attributes_inline(attrs)?;
- self.commasep_exprs(Inconsistent, &exprs[..])?;
- self.s.word("]")?;
- self.end()
+ attrs: &[Attribute]) {
+ self.ibox(INDENT_UNIT);
+ self.s.word("[");
+ self.print_inner_attributes_inline(attrs);
+ self.commasep_exprs(Inconsistent, &exprs[..]);
+ self.s.word("]");
+ self.end();
}
fn print_expr_repeat(&mut self,
element: &ast::Expr,
count: &ast::AnonConst,
- attrs: &[Attribute]) -> io::Result<()> {
- self.ibox(INDENT_UNIT)?;
- self.s.word("[")?;
- self.print_inner_attributes_inline(attrs)?;
- self.print_expr(element)?;
- self.word_space(";")?;
- self.print_expr(&count.value)?;
- self.s.word("]")?;
- self.end()
+ attrs: &[Attribute]) {
+ self.ibox(INDENT_UNIT);
+ self.s.word("[");
+ self.print_inner_attributes_inline(attrs);
+ self.print_expr(element);
+ self.word_space(";");
+ self.print_expr(&count.value);
+ self.s.word("]");
+ self.end();
}
fn print_expr_struct(&mut self,
path: &ast::Path,
fields: &[ast::Field],
wth: &Option<P<ast::Expr>>,
- attrs: &[Attribute]) -> io::Result<()> {
- self.print_path(path, true, 0)?;
- self.s.word("{")?;
- self.print_inner_attributes_inline(attrs)?;
+ attrs: &[Attribute]) {
+ self.print_path(path, true, 0);
+ self.s.word("{");
+ self.print_inner_attributes_inline(attrs);
self.commasep_cmnt(
Consistent,
&fields[..],
|s, field| {
- s.ibox(INDENT_UNIT)?;
+ s.ibox(INDENT_UNIT);
if !field.is_shorthand {
- s.print_ident(field.ident)?;
- s.word_space(":")?;
+ s.print_ident(field.ident);
+ s.word_space(":");
}
- s.print_expr(&field.expr)?;
- s.end()
+ s.print_expr(&field.expr);
+ s.end();
},
- |f| f.span)?;
+ |f| f.span);
match *wth {
Some(ref expr) => {
- self.ibox(INDENT_UNIT)?;
+ self.ibox(INDENT_UNIT);
if !fields.is_empty() {
- self.s.word(",")?;
- self.s.space()?;
+ self.s.word(",");
+ self.s.space();
}
- self.s.word("..")?;
- self.print_expr(expr)?;
- self.end()?;
+ self.s.word("..");
+ self.print_expr(expr);
+ self.end();
}
_ => if !fields.is_empty() {
- self.s.word(",")?
+ self.s.word(",")
}
}
- self.s.word("}")?;
- Ok(())
+ self.s.word("}");
}
fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>],
- attrs: &[Attribute]) -> io::Result<()> {
- self.popen()?;
- self.print_inner_attributes_inline(attrs)?;
- self.commasep_exprs(Inconsistent, &exprs[..])?;
+ attrs: &[Attribute]) {
+ self.popen();
+ self.print_inner_attributes_inline(attrs);
+ self.commasep_exprs(Inconsistent, &exprs[..]);
if exprs.len() == 1 {
- self.s.word(",")?;
+ self.s.word(",");
}
self.pclose()
}
fn print_expr_call(&mut self,
func: &ast::Expr,
- args: &[P<ast::Expr>]) -> io::Result<()> {
+ args: &[P<ast::Expr>]) {
let prec =
match func.node {
ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
_ => parser::PREC_POSTFIX,
};
- self.print_expr_maybe_paren(func, prec)?;
+ self.print_expr_maybe_paren(func, prec);
self.print_call_post(args)
}
fn print_expr_method_call(&mut self,
segment: &ast::PathSegment,
- args: &[P<ast::Expr>]) -> io::Result<()> {
+ args: &[P<ast::Expr>]) {
let base_args = &args[1..];
- self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
- self.s.word(".")?;
- self.print_ident(segment.ident)?;
+ self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
+ self.s.word(".");
+ self.print_ident(segment.ident);
if let Some(ref args) = segment.args {
- self.print_generic_args(args, true)?;
+ self.print_generic_args(args, true);
}
self.print_call_post(base_args)
}
fn print_expr_binary(&mut self,
op: ast::BinOp,
lhs: &ast::Expr,
- rhs: &ast::Expr) -> io::Result<()> {
+ rhs: &ast::Expr) {
let assoc_op = AssocOp::from_ast_binop(op.node);
let prec = assoc_op.precedence() as i8;
let fixity = assoc_op.fixity();
_ => left_prec,
};
- self.print_expr_maybe_paren(lhs, left_prec)?;
- self.s.space()?;
- self.word_space(op.node.to_string())?;
+ self.print_expr_maybe_paren(lhs, left_prec);
+ self.s.space();
+ self.word_space(op.node.to_string());
self.print_expr_maybe_paren(rhs, right_prec)
}
fn print_expr_unary(&mut self,
op: ast::UnOp,
- expr: &ast::Expr) -> io::Result<()> {
- self.s.word(ast::UnOp::to_string(op))?;
+ expr: &ast::Expr) {
+ self.s.word(ast::UnOp::to_string(op));
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
}
fn print_expr_addr_of(&mut self,
mutability: ast::Mutability,
- expr: &ast::Expr) -> io::Result<()> {
- self.s.word("&")?;
- self.print_mutability(mutability)?;
+ expr: &ast::Expr) {
+ self.s.word("&");
+ self.print_mutability(mutability);
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
}
- pub fn print_expr(&mut self, expr: &ast::Expr) -> io::Result<()> {
+ crate fn print_expr(&mut self, expr: &ast::Expr) {
self.print_expr_outer_attr_style(expr, true)
}
fn print_expr_outer_attr_style(&mut self,
expr: &ast::Expr,
- is_inline: bool) -> io::Result<()> {
- self.maybe_print_comment(expr.span.lo())?;
+ is_inline: bool) {
+ self.maybe_print_comment(expr.span.lo());
let attrs = &expr.attrs;
if is_inline {
- self.print_outer_attributes_inline(attrs)?;
+ self.print_outer_attributes_inline(attrs);
} else {
- self.print_outer_attributes(attrs)?;
+ self.print_outer_attributes(attrs);
}
- self.ibox(INDENT_UNIT)?;
- self.ann.pre(self, AnnNode::Expr(expr))?;
+ self.ibox(INDENT_UNIT);
+ self.ann.pre(self, AnnNode::Expr(expr));
match expr.node {
ast::ExprKind::Box(ref expr) => {
- self.word_space("box")?;
- self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)?;
+ self.word_space("box");
+ self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
}
ast::ExprKind::Array(ref exprs) => {
- self.print_expr_vec(&exprs[..], attrs)?;
+ self.print_expr_vec(&exprs[..], attrs);
}
ast::ExprKind::Repeat(ref element, ref count) => {
- self.print_expr_repeat(element, count, attrs)?;
+ self.print_expr_repeat(element, count, attrs);
}
ast::ExprKind::Struct(ref path, ref fields, ref wth) => {
- self.print_expr_struct(path, &fields[..], wth, attrs)?;
+ self.print_expr_struct(path, &fields[..], wth, attrs);
}
ast::ExprKind::Tup(ref exprs) => {
- self.print_expr_tup(&exprs[..], attrs)?;
+ self.print_expr_tup(&exprs[..], attrs);
}
ast::ExprKind::Call(ref func, ref args) => {
- self.print_expr_call(func, &args[..])?;
+ self.print_expr_call(func, &args[..]);
}
ast::ExprKind::MethodCall(ref segment, ref args) => {
- self.print_expr_method_call(segment, &args[..])?;
+ self.print_expr_method_call(segment, &args[..]);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
- self.print_expr_binary(op, lhs, rhs)?;
+ self.print_expr_binary(op, lhs, rhs);
}
ast::ExprKind::Unary(op, ref expr) => {
- self.print_expr_unary(op, expr)?;
+ self.print_expr_unary(op, expr);
}
ast::ExprKind::AddrOf(m, ref expr) => {
- self.print_expr_addr_of(m, expr)?;
+ self.print_expr_addr_of(m, expr);
}
ast::ExprKind::Lit(ref lit) => {
- self.print_literal(lit)?;
+ self.print_literal(lit);
}
ast::ExprKind::Cast(ref expr, ref ty) => {
let prec = AssocOp::As.precedence() as i8;
- self.print_expr_maybe_paren(expr, prec)?;
- self.s.space()?;
- self.word_space("as")?;
- self.print_type(ty)?;
+ self.print_expr_maybe_paren(expr, prec);
+ self.s.space();
+ self.word_space("as");
+ self.print_type(ty);
}
ast::ExprKind::Type(ref expr, ref ty) => {
let prec = AssocOp::Colon.precedence() as i8;
- self.print_expr_maybe_paren(expr, prec)?;
- self.word_space(":")?;
- self.print_type(ty)?;
+ self.print_expr_maybe_paren(expr, prec);
+ self.word_space(":");
+ self.print_type(ty);
}
ast::ExprKind::Let(ref pats, ref scrutinee) => {
- self.print_let(pats, scrutinee)?;
+ self.print_let(pats, scrutinee);
}
ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
- self.print_if(test, blk, elseopt.as_ref().map(|e| &**e))?;
+ self.print_if(test, blk, elseopt.as_ref().map(|e| &**e));
}
ast::ExprKind::While(ref test, ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
- self.head("while")?;
- self.print_expr_as_cond(test)?;
- self.s.space()?;
- self.print_block_with_attrs(blk, attrs)?;
+ self.head("while");
+ self.print_expr_as_cond(test);
+ self.s.space();
+ self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
- self.head("for")?;
- self.print_pat(pat)?;
- self.s.space()?;
- self.word_space("in")?;
- self.print_expr_as_cond(iter)?;
- self.s.space()?;
- self.print_block_with_attrs(blk, attrs)?;
+ self.head("for");
+ self.print_pat(pat);
+ self.s.space();
+ self.word_space("in");
+ self.print_expr_as_cond(iter);
+ self.s.space();
+ self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Loop(ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
- self.head("loop")?;
- self.s.space()?;
- self.print_block_with_attrs(blk, attrs)?;
+ self.head("loop");
+ self.s.space();
+ self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Match(ref expr, ref arms) => {
- self.cbox(INDENT_UNIT)?;
- self.ibox(4)?;
- self.word_nbsp("match")?;
- self.print_expr_as_cond(expr)?;
- self.s.space()?;
- self.bopen()?;
- self.print_inner_attributes_no_trailing_hardbreak(attrs)?;
+ self.cbox(INDENT_UNIT);
+ self.ibox(4);
+ self.word_nbsp("match");
+ self.print_expr_as_cond(expr);
+ self.s.space();
+ self.bopen();
+ self.print_inner_attributes_no_trailing_hardbreak(attrs);
for arm in arms {
- self.print_arm(arm)?;
+ self.print_arm(arm);
}
- self.bclose_(expr.span, INDENT_UNIT)?;
+ self.bclose_(expr.span, INDENT_UNIT);
}
ast::ExprKind::Closure(
capture_clause, asyncness, movability, ref decl, ref body, _) => {
- self.print_movability(movability)?;
- self.print_asyncness(asyncness)?;
- self.print_capture_clause(capture_clause)?;
+ self.print_movability(movability);
+ self.print_asyncness(asyncness);
+ self.print_capture_clause(capture_clause);
- self.print_fn_block_args(decl)?;
- self.s.space()?;
- self.print_expr(body)?;
- self.end()?; // need to close a box
+ self.print_fn_block_args(decl);
+ self.s.space();
+ self.print_expr(body);
+ self.end(); // need to close a box
// a box will be closed by print_expr, but we didn't want an overall
// wrapper so we closed the corresponding opening. so create an
// empty box to satisfy the close.
- self.ibox(0)?;
+ self.ibox(0);
}
ast::ExprKind::Block(ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
// containing cbox, will be closed by print-block at }
- self.cbox(INDENT_UNIT)?;
+ self.cbox(INDENT_UNIT);
// head-box, will be closed by print-block after {
- self.ibox(0)?;
- self.print_block_with_attrs(blk, attrs)?;
+ self.ibox(0);
+ self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Async(capture_clause, _, ref blk) => {
- self.word_nbsp("async")?;
- self.print_capture_clause(capture_clause)?;
- self.s.space()?;
+ self.word_nbsp("async");
+ self.print_capture_clause(capture_clause);
+ self.s.space();
// cbox/ibox in analogy to the `ExprKind::Block` arm above
- self.cbox(INDENT_UNIT)?;
- self.ibox(0)?;
- self.print_block_with_attrs(blk, attrs)?;
+ self.cbox(INDENT_UNIT);
+ self.ibox(0);
+ self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Await(origin, ref expr) => {
match origin {
ast::AwaitOrigin::MacroLike => {
- self.s.word("await!")?;
- self.print_expr_maybe_paren(expr, parser::PREC_FORCE_PAREN)?;
+ self.s.word("await!");
+ self.print_expr_maybe_paren(expr, parser::PREC_FORCE_PAREN);
}
ast::AwaitOrigin::FieldLike => {
- self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
- self.s.word(".await")?;
+ self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+ self.s.word(".await");
}
}
}
ast::ExprKind::Assign(ref lhs, ref rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
- self.print_expr_maybe_paren(lhs, prec + 1)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_expr_maybe_paren(rhs, prec)?;
+ self.print_expr_maybe_paren(lhs, prec + 1);
+ self.s.space();
+ self.word_space("=");
+ self.print_expr_maybe_paren(rhs, prec);
}
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
- self.print_expr_maybe_paren(lhs, prec + 1)?;
- self.s.space()?;
- self.s.word(op.node.to_string())?;
- self.word_space("=")?;
- self.print_expr_maybe_paren(rhs, prec)?;
+ self.print_expr_maybe_paren(lhs, prec + 1);
+ self.s.space();
+ self.s.word(op.node.to_string());
+ self.word_space("=");
+ self.print_expr_maybe_paren(rhs, prec);
}
ast::ExprKind::Field(ref expr, ident) => {
- self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
- self.s.word(".")?;
- self.print_ident(ident)?;
+ self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+ self.s.word(".");
+ self.print_ident(ident);
}
ast::ExprKind::Index(ref expr, ref index) => {
- self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
- self.s.word("[")?;
- self.print_expr(index)?;
- self.s.word("]")?;
+ self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+ self.s.word("[");
+ self.print_expr(index);
+ self.s.word("]");
}
ast::ExprKind::Range(ref start, ref end, limits) => {
// Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
// a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
let fake_prec = AssocOp::LOr.precedence() as i8;
if let Some(ref e) = *start {
- self.print_expr_maybe_paren(e, fake_prec)?;
+ self.print_expr_maybe_paren(e, fake_prec);
}
if limits == ast::RangeLimits::HalfOpen {
- self.s.word("..")?;
+ self.s.word("..");
} else {
- self.s.word("..=")?;
+ self.s.word("..=");
}
if let Some(ref e) = *end {
- self.print_expr_maybe_paren(e, fake_prec)?;
+ self.print_expr_maybe_paren(e, fake_prec);
}
}
ast::ExprKind::Path(None, ref path) => {
- self.print_path(path, true, 0)?
+ self.print_path(path, true, 0)
}
ast::ExprKind::Path(Some(ref qself), ref path) => {
- self.print_qpath(path, qself, true)?
+ self.print_qpath(path, qself, true)
}
ast::ExprKind::Break(opt_label, ref opt_expr) => {
- self.s.word("break")?;
- self.s.space()?;
+ self.s.word("break");
+ self.s.space();
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.s.space()?;
+ self.print_ident(label.ident);
+ self.s.space();
}
if let Some(ref expr) = *opt_expr {
- self.print_expr_maybe_paren(expr, parser::PREC_JUMP)?;
- self.s.space()?;
+ self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+ self.s.space();
}
}
ast::ExprKind::Continue(opt_label) => {
- self.s.word("continue")?;
- self.s.space()?;
+ self.s.word("continue");
+ self.s.space();
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.s.space()?
+ self.print_ident(label.ident);
+ self.s.space()
}
}
ast::ExprKind::Ret(ref result) => {
- self.s.word("return")?;
+ self.s.word("return");
if let Some(ref expr) = *result {
- self.s.word(" ")?;
- self.print_expr_maybe_paren(expr, parser::PREC_JUMP)?;
+ self.s.word(" ");
+ self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::InlineAsm(ref a) => {
- self.s.word("asm!")?;
- self.popen()?;
- self.print_string(&a.asm.as_str(), a.asm_str_style)?;
- self.word_space(":")?;
+ self.s.word("asm!");
+ self.popen();
+ self.print_string(&a.asm.as_str(), a.asm_str_style);
+ self.word_space(":");
self.commasep(Inconsistent, &a.outputs, |s, out| {
let constraint = out.constraint.as_str();
match ch.next() {
Some('=') if out.is_rw => {
s.print_string(&format!("+{}", ch.as_str()),
- ast::StrStyle::Cooked)?
+ ast::StrStyle::Cooked)
}
- _ => s.print_string(&constraint, ast::StrStyle::Cooked)?
+ _ => s.print_string(&constraint, ast::StrStyle::Cooked)
}
- s.popen()?;
- s.print_expr(&out.expr)?;
- s.pclose()?;
- Ok(())
- })?;
- self.s.space()?;
- self.word_space(":")?;
+ s.popen();
+ s.print_expr(&out.expr);
+ s.pclose();
+ });
+ self.s.space();
+ self.word_space(":");
self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| {
- s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
- s.popen()?;
- s.print_expr(o)?;
- s.pclose()?;
- Ok(())
- })?;
- self.s.space()?;
- self.word_space(":")?;
+ s.print_string(&co.as_str(), ast::StrStyle::Cooked);
+ s.popen();
+ s.print_expr(o);
+ s.pclose();
+ });
+ self.s.space();
+ self.word_space(":");
self.commasep(Inconsistent, &a.clobbers,
|s, co| {
- s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
- Ok(())
- })?;
+ s.print_string(&co.as_str(), ast::StrStyle::Cooked);
+ });
let mut options = vec![];
if a.volatile {
}
if !options.is_empty() {
- self.s.space()?;
- self.word_space(":")?;
+ self.s.space();
+ self.word_space(":");
self.commasep(Inconsistent, &options,
|s, &co| {
- s.print_string(co, ast::StrStyle::Cooked)?;
- Ok(())
- })?;
+ s.print_string(co, ast::StrStyle::Cooked);
+ });
}
- self.pclose()?;
+ self.pclose();
}
- ast::ExprKind::Mac(ref m) => self.print_mac(m)?,
+ ast::ExprKind::Mac(ref m) => self.print_mac(m),
ast::ExprKind::Paren(ref e) => {
- self.popen()?;
- self.print_inner_attributes_inline(attrs)?;
- self.print_expr(e)?;
- self.pclose()?;
+ self.popen();
+ self.print_inner_attributes_inline(attrs);
+ self.print_expr(e);
+ self.pclose();
},
ast::ExprKind::Yield(ref e) => {
- self.s.word("yield")?;
+ self.s.word("yield");
match *e {
Some(ref expr) => {
- self.s.space()?;
- self.print_expr_maybe_paren(expr, parser::PREC_JUMP)?;
+ self.s.space();
+ self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
_ => ()
}
}
ast::ExprKind::Try(ref e) => {
- self.print_expr_maybe_paren(e, parser::PREC_POSTFIX)?;
- self.s.word("?")?
+ self.print_expr_maybe_paren(e, parser::PREC_POSTFIX);
+ self.s.word("?")
}
ast::ExprKind::TryBlock(ref blk) => {
- self.head("try")?;
- self.s.space()?;
- self.print_block_with_attrs(blk, attrs)?
+ self.head("try");
+ self.s.space();
+ self.print_block_with_attrs(blk, attrs)
}
ast::ExprKind::Err => {
- self.popen()?;
- self.s.word("/*ERROR*/")?;
- self.pclose()?
+ self.popen();
+ self.s.word("/*ERROR*/");
+ self.pclose()
}
}
- self.ann.post(self, AnnNode::Expr(expr))?;
- self.end()
+ self.ann.post(self, AnnNode::Expr(expr));
+ self.end();
}
- pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> {
- self.print_pat(&loc.pat)?;
+ crate fn print_local_decl(&mut self, loc: &ast::Local) {
+ self.print_pat(&loc.pat);
if let Some(ref ty) = loc.ty {
- self.word_space(":")?;
- self.print_type(ty)?;
+ self.word_space(":");
+ self.print_type(ty);
}
- Ok(())
}
- pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
+ crate fn print_ident(&mut self, ident: ast::Ident) {
if ident.is_raw_guess() {
- self.s.word(format!("r#{}", ident))?;
+ self.s.word(format!("r#{}", ident));
} else {
- self.s.word(ident.as_str().to_string())?;
+ self.s.word(ident.as_str().to_string());
}
self.ann.post(self, AnnNode::Ident(&ident))
}
- pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
+ crate fn print_usize(&mut self, i: usize) {
self.s.word(i.to_string())
}
- pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
- self.s.word(name.as_str().to_string())?;
+ crate fn print_name(&mut self, name: ast::Name) {
+ self.s.word(name.as_str().to_string());
self.ann.post(self, AnnNode::Name(&name))
}
- pub fn print_for_decl(&mut self, loc: &ast::Local,
- coll: &ast::Expr) -> io::Result<()> {
- self.print_local_decl(loc)?;
- self.s.space()?;
- self.word_space("in")?;
- self.print_expr(coll)
- }
-
fn print_path(&mut self,
path: &ast::Path,
colons_before_params: bool,
- depth: usize)
- -> io::Result<()>
- {
- self.maybe_print_comment(path.span.lo())?;
+ depth: usize) {
+ self.maybe_print_comment(path.span.lo());
for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() {
if i > 0 {
- self.s.word("::")?
+ self.s.word("::")
}
- self.print_path_segment(segment, colons_before_params)?;
+ self.print_path_segment(segment, colons_before_params);
}
-
- Ok(())
}
fn print_path_segment(&mut self,
segment: &ast::PathSegment,
- colons_before_params: bool)
- -> io::Result<()>
- {
+ colons_before_params: bool) {
if segment.ident.name != kw::PathRoot {
if segment.ident.name == kw::DollarCrate {
- self.print_dollar_crate(segment.ident)?;
+ self.print_dollar_crate(segment.ident);
} else {
- self.print_ident(segment.ident)?;
+ self.print_ident(segment.ident);
}
if let Some(ref args) = segment.args {
- self.print_generic_args(args, colons_before_params)?;
+ self.print_generic_args(args, colons_before_params);
}
}
- Ok(())
}
fn print_qpath(&mut self,
path: &ast::Path,
qself: &ast::QSelf,
colons_before_params: bool)
- -> io::Result<()>
{
- self.s.word("<")?;
- self.print_type(&qself.ty)?;
+ self.s.word("<");
+ self.print_type(&qself.ty);
if qself.position > 0 {
- self.s.space()?;
- self.word_space("as")?;
+ self.s.space();
+ self.word_space("as");
let depth = path.segments.len() - qself.position;
- self.print_path(path, false, depth)?;
+ self.print_path(path, false, depth);
}
- self.s.word(">")?;
- self.s.word("::")?;
+ self.s.word(">");
+ self.s.word("::");
let item_segment = path.segments.last().unwrap();
- self.print_ident(item_segment.ident)?;
+ self.print_ident(item_segment.ident);
match item_segment.args {
Some(ref args) => self.print_generic_args(args, colons_before_params),
- None => Ok(()),
+ None => {},
}
}
fn print_generic_args(&mut self,
args: &ast::GenericArgs,
colons_before_params: bool)
- -> io::Result<()>
{
if colons_before_params {
- self.s.word("::")?
+ self.s.word("::")
}
match *args {
ast::GenericArgs::AngleBracketed(ref data) => {
- self.s.word("<")?;
+ self.s.word("<");
self.commasep(Inconsistent, &data.args, |s, generic_arg| {
s.print_generic_arg(generic_arg)
- })?;
+ });
let mut comma = data.args.len() != 0;
for constraint in data.constraints.iter() {
if comma {
- self.word_space(",")?
+ self.word_space(",")
}
- self.print_ident(constraint.ident)?;
- self.s.space()?;
+ self.print_ident(constraint.ident);
+ self.s.space();
match constraint.kind {
ast::AssocTyConstraintKind::Equality { ref ty } => {
- self.word_space("=")?;
- self.print_type(ty)?;
+ self.word_space("=");
+ self.print_type(ty);
}
ast::AssocTyConstraintKind::Bound { ref bounds } => {
- self.print_type_bounds(":", &*bounds)?;
+ self.print_type_bounds(":", &*bounds);
}
}
comma = true;
}
- self.s.word(">")?
+ self.s.word(">")
}
ast::GenericArgs::Parenthesized(ref data) => {
- self.s.word("(")?;
+ self.s.word("(");
self.commasep(
Inconsistent,
&data.inputs,
- |s, ty| s.print_type(ty))?;
- self.s.word(")")?;
+ |s, ty| s.print_type(ty));
+ self.s.word(")");
if let Some(ref ty) = data.output {
- self.space_if_not_bol()?;
- self.word_space("->")?;
- self.print_type(ty)?;
+ self.space_if_not_bol();
+ self.word_space("->");
+ self.print_type(ty);
}
}
}
-
- Ok(())
}
- pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
- self.maybe_print_comment(pat.span.lo())?;
- self.ann.pre(self, AnnNode::Pat(pat))?;
+ crate fn print_pat(&mut self, pat: &ast::Pat) {
+ self.maybe_print_comment(pat.span.lo());
+ self.ann.pre(self, AnnNode::Pat(pat));
/* Pat isn't normalized, but the beauty of it
is that it doesn't matter */
match pat.node {
- PatKind::Wild => self.s.word("_")?,
+ PatKind::Wild => self.s.word("_"),
PatKind::Ident(binding_mode, ident, ref sub) => {
match binding_mode {
ast::BindingMode::ByRef(mutbl) => {
- self.word_nbsp("ref")?;
- self.print_mutability(mutbl)?;
+ self.word_nbsp("ref");
+ self.print_mutability(mutbl);
}
ast::BindingMode::ByValue(ast::Mutability::Immutable) => {}
ast::BindingMode::ByValue(ast::Mutability::Mutable) => {
- self.word_nbsp("mut")?;
+ self.word_nbsp("mut");
}
}
- self.print_ident(ident)?;
+ self.print_ident(ident);
if let Some(ref p) = *sub {
- self.s.word("@")?;
- self.print_pat(p)?;
+ self.s.word("@");
+ self.print_pat(p);
}
}
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
- self.print_path(path, true, 0)?;
- self.popen()?;
+ self.print_path(path, true, 0);
+ self.popen();
if let Some(ddpos) = ddpos {
- self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
+ self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 {
- self.word_space(",")?;
+ self.word_space(",");
}
- self.s.word("..")?;
+ self.s.word("..");
if ddpos != elts.len() {
- self.s.word(",")?;
- self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?;
+ self.s.word(",");
+ self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
}
} else {
- self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p))?;
+ self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
}
- self.pclose()?;
+ self.pclose();
}
PatKind::Path(None, ref path) => {
- self.print_path(path, true, 0)?;
+ self.print_path(path, true, 0);
}
PatKind::Path(Some(ref qself), ref path) => {
- self.print_qpath(path, qself, false)?;
+ self.print_qpath(path, qself, false);
}
PatKind::Struct(ref path, ref fields, etc) => {
- self.print_path(path, true, 0)?;
- self.nbsp()?;
- self.word_space("{")?;
+ self.print_path(path, true, 0);
+ self.nbsp();
+ self.word_space("{");
self.commasep_cmnt(
Consistent, &fields[..],
|s, f| {
- s.cbox(INDENT_UNIT)?;
+ s.cbox(INDENT_UNIT);
if !f.node.is_shorthand {
- s.print_ident(f.node.ident)?;
- s.word_nbsp(":")?;
+ s.print_ident(f.node.ident);
+ s.word_nbsp(":");
}
- s.print_pat(&f.node.pat)?;
- s.end()
+ s.print_pat(&f.node.pat);
+ s.end();
},
- |f| f.node.pat.span)?;
+ |f| f.node.pat.span);
if etc {
- if !fields.is_empty() { self.word_space(",")?; }
- self.s.word("..")?;
+ if !fields.is_empty() { self.word_space(","); }
+ self.s.word("..");
}
- self.s.space()?;
- self.s.word("}")?;
+ self.s.space();
+ self.s.word("}");
}
PatKind::Tuple(ref elts, ddpos) => {
- self.popen()?;
+ self.popen();
if let Some(ddpos) = ddpos {
- self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
+ self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 {
- self.word_space(",")?;
+ self.word_space(",");
}
- self.s.word("..")?;
+ self.s.word("..");
if ddpos != elts.len() {
- self.s.word(",")?;
- self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p))?;
+ self.s.word(",");
+ self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
}
} else {
- self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p))?;
+ self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
if elts.len() == 1 {
- self.s.word(",")?;
+ self.s.word(",");
}
}
- self.pclose()?;
+ self.pclose();
}
PatKind::Box(ref inner) => {
- self.s.word("box ")?;
- self.print_pat(inner)?;
+ self.s.word("box ");
+ self.print_pat(inner);
}
PatKind::Ref(ref inner, mutbl) => {
- self.s.word("&")?;
+ self.s.word("&");
if mutbl == ast::Mutability::Mutable {
- self.s.word("mut ")?;
+ self.s.word("mut ");
}
- self.print_pat(inner)?;
+ self.print_pat(inner);
}
- PatKind::Lit(ref e) => self.print_expr(&**e)?,
+ PatKind::Lit(ref e) => self.print_expr(&**e),
PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
- self.print_expr(begin)?;
- self.s.space()?;
+ self.print_expr(begin);
+ self.s.space();
match *end_kind {
- RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("...")?,
- RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..=")?,
- RangeEnd::Excluded => self.s.word("..")?,
+ RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."),
+ RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="),
+ RangeEnd::Excluded => self.s.word(".."),
}
- self.print_expr(end)?;
+ self.print_expr(end);
}
PatKind::Slice(ref before, ref slice, ref after) => {
- self.s.word("[")?;
+ self.s.word("[");
self.commasep(Inconsistent,
&before[..],
- |s, p| s.print_pat(p))?;
+ |s, p| s.print_pat(p));
if let Some(ref p) = *slice {
- if !before.is_empty() { self.word_space(",")?; }
+ if !before.is_empty() { self.word_space(","); }
if let PatKind::Wild = p.node {
// Print nothing
} else {
- self.print_pat(p)?;
+ self.print_pat(p);
}
- self.s.word("..")?;
- if !after.is_empty() { self.word_space(",")?; }
+ self.s.word("..");
+ if !after.is_empty() { self.word_space(","); }
}
self.commasep(Inconsistent,
&after[..],
- |s, p| s.print_pat(p))?;
- self.s.word("]")?;
+ |s, p| s.print_pat(p));
+ self.s.word("]");
}
PatKind::Paren(ref inner) => {
- self.popen()?;
- self.print_pat(inner)?;
- self.pclose()?;
+ self.popen();
+ self.print_pat(inner);
+ self.pclose();
}
- PatKind::Mac(ref m) => self.print_mac(m)?,
+ PatKind::Mac(ref m) => self.print_mac(m),
}
self.ann.post(self, AnnNode::Pat(pat))
}
- fn print_pats(&mut self, pats: &[P<ast::Pat>]) -> io::Result<()> {
+ fn print_pats(&mut self, pats: &[P<ast::Pat>]) {
let mut first = true;
for p in pats {
if first {
first = false;
} else {
- self.s.space()?;
- self.word_space("|")?;
+ self.s.space();
+ self.word_space("|");
}
- self.print_pat(p)?;
+ self.print_pat(p);
}
- Ok(())
}
- fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
+ fn print_arm(&mut self, arm: &ast::Arm) {
// I have no idea why this check is necessary, but here it
// is :(
if arm.attrs.is_empty() {
- self.s.space()?;
- }
- self.cbox(INDENT_UNIT)?;
- self.ibox(0)?;
- self.maybe_print_comment(arm.pats[0].span.lo())?;
- self.print_outer_attributes(&arm.attrs)?;
- self.print_pats(&arm.pats)?;
- self.s.space()?;
+ self.s.space();
+ }
+ self.cbox(INDENT_UNIT);
+ self.ibox(0);
+ self.maybe_print_comment(arm.pats[0].span.lo());
+ self.print_outer_attributes(&arm.attrs);
+ self.print_pats(&arm.pats);
+ self.s.space();
if let Some(ref e) = arm.guard {
- self.word_space("if")?;
- self.print_expr(e)?;
- self.s.space()?;
+ self.word_space("if");
+ self.print_expr(e);
+ self.s.space();
}
- self.word_space("=>")?;
+ self.word_space("=>");
match arm.body.node {
ast::ExprKind::Block(ref blk, opt_label) => {
if let Some(label) = opt_label {
- self.print_ident(label.ident)?;
- self.word_space(":")?;
+ self.print_ident(label.ident);
+ self.word_space(":");
}
// the block will close the pattern's ibox
- self.print_block_unclosed_indent(blk, INDENT_UNIT)?;
+ self.print_block_unclosed_indent(blk, INDENT_UNIT);
// If it is a user-provided unsafe block, print a comma after it
if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
- self.s.word(",")?;
+ self.s.word(",");
}
}
_ => {
- self.end()?; // close the ibox for the pattern
- self.print_expr(&arm.body)?;
- self.s.word(",")?;
+ self.end(); // close the ibox for the pattern
+ self.print_expr(&arm.body);
+ self.s.word(",");
}
}
- self.end() // close enclosing cbox
+ self.end(); // close enclosing cbox
}
- fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Result<()> {
+ fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
match explicit_self.node {
SelfKind::Value(m) => {
- self.print_mutability(m)?;
+ self.print_mutability(m);
self.s.word("self")
}
SelfKind::Region(ref lt, m) => {
- self.s.word("&")?;
- self.print_opt_lifetime(lt)?;
- self.print_mutability(m)?;
+ self.s.word("&");
+ self.print_opt_lifetime(lt);
+ self.print_mutability(m);
self.s.word("self")
}
SelfKind::Explicit(ref typ, m) => {
- self.print_mutability(m)?;
- self.s.word("self")?;
- self.word_space(":")?;
+ self.print_mutability(m);
+ self.s.word("self");
+ self.word_space(":");
self.print_type(typ)
}
}
}
- pub fn print_fn(&mut self,
+ crate fn print_fn(&mut self,
decl: &ast::FnDecl,
header: ast::FnHeader,
name: Option<ast::Ident>,
generics: &ast::Generics,
- vis: &ast::Visibility) -> io::Result<()> {
- self.print_fn_header_info(header, vis)?;
+ vis: &ast::Visibility) {
+ self.print_fn_header_info(header, vis);
if let Some(name) = name {
- self.nbsp()?;
- self.print_ident(name)?;
+ self.nbsp();
+ self.print_ident(name);
}
- self.print_generic_params(&generics.params)?;
- self.print_fn_args_and_ret(decl)?;
+ self.print_generic_params(&generics.params);
+ self.print_fn_args_and_ret(decl);
self.print_where_clause(&generics.where_clause)
}
- pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl)
- -> io::Result<()> {
- self.popen()?;
- self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
- self.pclose()?;
+ crate fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl) {
+ self.popen();
+ self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false));
+ self.pclose();
self.print_fn_output(decl)
}
- pub fn print_fn_block_args(
- &mut self,
- decl: &ast::FnDecl)
- -> io::Result<()> {
- self.s.word("|")?;
- self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
- self.s.word("|")?;
+ crate fn print_fn_block_args(&mut self, decl: &ast::FnDecl) {
+ self.s.word("|");
+ self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true));
+ self.s.word("|");
if let ast::FunctionRetTy::Default(..) = decl.output {
- return Ok(());
+ return;
}
- self.space_if_not_bol()?;
- self.word_space("->")?;
+ self.space_if_not_bol();
+ self.word_space("->");
match decl.output {
ast::FunctionRetTy::Ty(ref ty) => {
- self.print_type(ty)?;
+ self.print_type(ty);
self.maybe_print_comment(ty.span.lo())
}
ast::FunctionRetTy::Default(..) => unreachable!(),
}
}
- pub fn print_movability(&mut self, movability: ast::Movability)
- -> io::Result<()> {
+ crate fn print_movability(&mut self, movability: ast::Movability) {
match movability {
ast::Movability::Static => self.word_space("static"),
- ast::Movability::Movable => Ok(()),
+ ast::Movability::Movable => {},
}
}
- pub fn print_asyncness(&mut self, asyncness: ast::IsAsync)
- -> io::Result<()> {
+ crate fn print_asyncness(&mut self, asyncness: ast::IsAsync) {
if asyncness.is_async() {
- self.word_nbsp("async")?;
+ self.word_nbsp("async");
}
- Ok(())
}
- pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy)
- -> io::Result<()> {
+ crate fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
match capture_clause {
ast::CaptureBy::Value => self.word_space("move"),
- ast::CaptureBy::Ref => Ok(()),
+ ast::CaptureBy::Ref => {},
}
}
- pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound])
- -> io::Result<()> {
+ crate fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) {
if !bounds.is_empty() {
- self.s.word(prefix)?;
+ self.s.word(prefix);
let mut first = true;
for bound in bounds {
if !(first && prefix.is_empty()) {
- self.nbsp()?;
+ self.nbsp();
}
if first {
first = false;
} else {
- self.word_space("+")?;
+ self.word_space("+");
}
match bound {
GenericBound::Trait(tref, modifier) => {
if modifier == &TraitBoundModifier::Maybe {
- self.s.word("?")?;
+ self.s.word("?");
}
- self.print_poly_trait_ref(tref)?;
+ self.print_poly_trait_ref(tref);
}
- GenericBound::Outlives(lt) => self.print_lifetime(*lt)?,
+ GenericBound::Outlives(lt) => self.print_lifetime(*lt),
}
}
}
- Ok(())
}
- pub fn print_lifetime(&mut self, lifetime: ast::Lifetime) -> io::Result<()> {
+ crate fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
self.print_name(lifetime.ident.name)
}
- pub fn print_lifetime_bounds(&mut self, lifetime: ast::Lifetime, bounds: &ast::GenericBounds)
- -> io::Result<()>
- {
- self.print_lifetime(lifetime)?;
+ crate fn print_lifetime_bounds(
+ &mut self, lifetime: ast::Lifetime, bounds: &ast::GenericBounds) {
+ self.print_lifetime(lifetime);
if !bounds.is_empty() {
- self.s.word(": ")?;
+ self.s.word(": ");
for (i, bound) in bounds.iter().enumerate() {
if i != 0 {
- self.s.word(" + ")?;
+ self.s.word(" + ");
}
match bound {
- ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt)?,
+ ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt),
_ => panic!(),
}
}
}
- Ok(())
}
- pub fn print_generic_params(
- &mut self,
- generic_params: &[ast::GenericParam]
- ) -> io::Result<()> {
+ crate fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
if generic_params.is_empty() {
- return Ok(());
+ return;
}
- self.s.word("<")?;
+ self.s.word("<");
self.commasep(Inconsistent, &generic_params, |s, param| {
match param.kind {
ast::GenericParamKind::Lifetime => {
- s.print_outer_attributes_inline(¶m.attrs)?;
+ s.print_outer_attributes_inline(¶m.attrs);
let lt = ast::Lifetime { id: param.id, ident: param.ident };
s.print_lifetime_bounds(lt, ¶m.bounds)
}
ast::GenericParamKind::Type { ref default } => {
- s.print_outer_attributes_inline(¶m.attrs)?;
- s.print_ident(param.ident)?;
- s.print_type_bounds(":", ¶m.bounds)?;
+ s.print_outer_attributes_inline(¶m.attrs);
+ s.print_ident(param.ident);
+ s.print_type_bounds(":", ¶m.bounds);
match default {
Some(ref default) => {
- s.s.space()?;
- s.word_space("=")?;
+ s.s.space();
+ s.word_space("=");
s.print_type(default)
}
- _ => Ok(())
+ _ => {}
}
}
ast::GenericParamKind::Const { ref ty } => {
- s.print_outer_attributes_inline(¶m.attrs)?;
- s.word_space("const")?;
- s.print_ident(param.ident)?;
- s.s.space()?;
- s.word_space(":")?;
- s.print_type(ty)?;
+ s.print_outer_attributes_inline(¶m.attrs);
+ s.word_space("const");
+ s.print_ident(param.ident);
+ s.s.space();
+ s.word_space(":");
+ s.print_type(ty);
s.print_type_bounds(":", ¶m.bounds)
}
}
- })?;
+ });
- self.s.word(">")?;
- Ok(())
+ self.s.word(">");
}
- pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
- -> io::Result<()> {
+ crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
if where_clause.predicates.is_empty() {
- return Ok(())
+ return;
}
- self.s.space()?;
- self.word_space("where")?;
+ self.s.space();
+ self.word_space("where");
for (i, predicate) in where_clause.predicates.iter().enumerate() {
if i != 0 {
- self.word_space(",")?;
+ self.word_space(",");
}
match *predicate {
ref bounds,
..
}) => {
- self.print_formal_generic_params(bound_generic_params)?;
- self.print_type(bounded_ty)?;
- self.print_type_bounds(":", bounds)?;
+ self.print_formal_generic_params(bound_generic_params);
+ self.print_type(bounded_ty);
+ self.print_type_bounds(":", bounds);
}
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
- self.print_lifetime_bounds(*lifetime, bounds)?;
+ self.print_lifetime_bounds(*lifetime, bounds);
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
- self.print_type(lhs_ty)?;
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(rhs_ty)?;
+ self.print_type(lhs_ty);
+ self.s.space();
+ self.word_space("=");
+ self.print_type(rhs_ty);
}
}
}
-
- Ok(())
}
- pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
+ crate fn print_use_tree(&mut self, tree: &ast::UseTree) {
match tree.kind {
ast::UseTreeKind::Simple(rename, ..) => {
- self.print_path(&tree.prefix, false, 0)?;
+ self.print_path(&tree.prefix, false, 0);
if let Some(rename) = rename {
- self.s.space()?;
- self.word_space("as")?;
- self.print_ident(rename)?;
+ self.s.space();
+ self.word_space("as");
+ self.print_ident(rename);
}
}
ast::UseTreeKind::Glob => {
if !tree.prefix.segments.is_empty() {
- self.print_path(&tree.prefix, false, 0)?;
- self.s.word("::")?;
+ self.print_path(&tree.prefix, false, 0);
+ self.s.word("::");
}
- self.s.word("*")?;
+ self.s.word("*");
}
ast::UseTreeKind::Nested(ref items) => {
if tree.prefix.segments.is_empty() {
- self.s.word("{")?;
+ self.s.word("{");
} else {
- self.print_path(&tree.prefix, false, 0)?;
- self.s.word("::{")?;
+ self.print_path(&tree.prefix, false, 0);
+ self.s.word("::{");
}
self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| {
this.print_use_tree(tree)
- })?;
- self.s.word("}")?;
+ });
+ self.s.word("}");
}
}
-
- Ok(())
}
- pub fn print_mutability(&mut self,
- mutbl: ast::Mutability) -> io::Result<()> {
+ crate fn print_mutability(&mut self, mutbl: ast::Mutability) {
match mutbl {
ast::Mutability::Mutable => self.word_nbsp("mut"),
- ast::Mutability::Immutable => Ok(()),
+ ast::Mutability::Immutable => {},
}
}
- pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> {
- self.print_mutability(mt.mutbl)?;
+ crate fn print_mt(&mut self, mt: &ast::MutTy) {
+ self.print_mutability(mt.mutbl);
self.print_type(&mt.ty)
}
- pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()> {
- self.ibox(INDENT_UNIT)?;
+ crate fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) {
+ self.ibox(INDENT_UNIT);
match input.ty.node {
- ast::TyKind::Infer if is_closure => self.print_pat(&input.pat)?,
+ ast::TyKind::Infer if is_closure => self.print_pat(&input.pat),
_ => {
if let Some(eself) = input.to_self() {
- self.print_explicit_self(&eself)?;
+ self.print_explicit_self(&eself);
} else {
let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
ident.name == kw::Invalid
false
};
if !invalid {
- self.print_pat(&input.pat)?;
- self.s.word(":")?;
- self.s.space()?;
+ self.print_pat(&input.pat);
+ self.s.word(":");
+ self.s.space();
}
- self.print_type(&input.ty)?;
+ self.print_type(&input.ty);
}
}
}
- self.end()
+ self.end();
}
- pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> io::Result<()> {
+ crate fn print_fn_output(&mut self, decl: &ast::FnDecl) {
if let ast::FunctionRetTy::Default(..) = decl.output {
- return Ok(());
+ return;
}
- self.space_if_not_bol()?;
- self.ibox(INDENT_UNIT)?;
- self.word_space("->")?;
+ self.space_if_not_bol();
+ self.ibox(INDENT_UNIT);
+ self.word_space("->");
match decl.output {
ast::FunctionRetTy::Default(..) => unreachable!(),
ast::FunctionRetTy::Ty(ref ty) =>
- self.print_type(ty)?
+ self.print_type(ty),
}
- self.end()?;
+ self.end();
match decl.output {
ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo()),
- _ => Ok(())
+ _ => {}
}
}
- pub fn print_ty_fn(&mut self,
+ crate fn print_ty_fn(&mut self,
abi: abi::Abi,
unsafety: ast::Unsafety,
decl: &ast::FnDecl,
name: Option<ast::Ident>,
generic_params: &[ast::GenericParam])
- -> io::Result<()> {
- self.ibox(INDENT_UNIT)?;
+ {
+ self.ibox(INDENT_UNIT);
if !generic_params.is_empty() {
- self.s.word("for")?;
- self.print_generic_params(generic_params)?;
+ self.s.word("for");
+ self.print_generic_params(generic_params);
}
let generics = ast::Generics {
params: Vec::new(),
ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
name,
&generics,
- &source_map::dummy_spanned(ast::VisibilityKind::Inherited))?;
- self.end()
+ &source_map::dummy_spanned(ast::VisibilityKind::Inherited));
+ self.end();
}
- pub fn maybe_print_trailing_comment(&mut self, span: syntax_pos::Span,
+ crate fn maybe_print_trailing_comment(&mut self, span: syntax_pos::Span,
next_pos: Option<BytePos>)
- -> io::Result<()> {
+ {
let cm = match self.cm {
Some(cm) => cm,
- _ => return Ok(())
+ _ => return,
};
if let Some(ref cmnt) = self.next_comment() {
- if cmnt.style != comments::Trailing { return Ok(()) }
+ if cmnt.style != comments::Trailing { return; }
let span_line = cm.lookup_char_pos(span.hi());
let comment_line = cm.lookup_char_pos(cmnt.pos);
let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
- self.print_comment(cmnt)?;
+ self.print_comment(cmnt);
}
}
- Ok(())
}
- pub fn print_remaining_comments(&mut self) -> io::Result<()> {
+ crate fn print_remaining_comments(&mut self) {
// If there aren't any remaining comments, then we need to manually
// make sure there is a line break at the end.
if self.next_comment().is_none() {
- self.s.hardbreak()?;
+ self.s.hardbreak();
}
while let Some(ref cmnt) = self.next_comment() {
- self.print_comment(cmnt)?;
- }
- Ok(())
- }
-
- pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
- opt_abi: Option<Abi>)
- -> io::Result<()> {
- match opt_abi {
- Some(Abi::Rust) => Ok(()),
- Some(abi) => {
- self.word_nbsp("extern")?;
- self.word_nbsp(abi.to_string())
- }
- None => Ok(())
- }
- }
-
- pub fn print_extern_opt_abi(&mut self,
- opt_abi: Option<Abi>) -> io::Result<()> {
- match opt_abi {
- Some(abi) => {
- self.word_nbsp("extern")?;
- self.word_nbsp(abi.to_string())
- }
- None => Ok(())
+ self.print_comment(cmnt);
}
}
- pub fn print_fn_header_info(&mut self,
+ crate fn print_fn_header_info(&mut self,
header: ast::FnHeader,
- vis: &ast::Visibility) -> io::Result<()> {
- self.s.word(visibility_qualified(vis, ""))?;
+ vis: &ast::Visibility) {
+ self.s.word(visibility_qualified(vis, ""));
match header.constness.node {
ast::Constness::NotConst => {}
- ast::Constness::Const => self.word_nbsp("const")?
+ ast::Constness::Const => self.word_nbsp("const")
}
- self.print_asyncness(header.asyncness.node)?;
- self.print_unsafety(header.unsafety)?;
+ self.print_asyncness(header.asyncness.node);
+ self.print_unsafety(header.unsafety);
if header.abi != Abi::Rust {
- self.word_nbsp("extern")?;
- self.word_nbsp(header.abi.to_string())?;
+ self.word_nbsp("extern");
+ self.word_nbsp(header.abi.to_string());
}
self.s.word("fn")
}
- pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> {
+ crate fn print_unsafety(&mut self, s: ast::Unsafety) {
match s {
- ast::Unsafety::Normal => Ok(()),
+ ast::Unsafety::Normal => {},
ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
}
}
- pub fn print_is_auto(&mut self, s: ast::IsAuto) -> io::Result<()> {
+ crate fn print_is_auto(&mut self, s: ast::IsAuto) {
match s {
ast::IsAuto::Yes => self.word_nbsp("auto"),
- ast::IsAuto::No => Ok(()),
+ ast::IsAuto::No => {}
}
}
}
ptr: Box<T>
}
-#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
+#[allow(non_snake_case)]
pub fn P<T: 'static>(value: T) -> P<T> {
P {
- ptr: Box::new(value)
+ ptr: box value
}
}
use crate::feature_gate::Features;
use crate::util::map_in_place::MapInPlace;
use crate::parse::{token, ParseSess};
-use crate::print::pprust;
use crate::ast::{self, Ident};
use crate::ptr::P;
use crate::symbol::{self, Symbol, kw, sym};
// We don't want to recurse into anything other than mods, since
// mods or tests inside of functions will break things
if let ast::ItemKind::Mod(mut module) = item.node {
- let tests = mem::replace(&mut self.tests, Vec::new());
- let tested_submods = mem::replace(&mut self.tested_submods, Vec::new());
+ let tests = mem::take(&mut self.tests);
+ let tested_submods = mem::take(&mut self.tested_submods);
noop_visit_mod(&mut module, self);
let tests = mem::replace(&mut self.tests, tests);
let tested_submods = mem::replace(&mut self.tested_submods, tested_submods);
TokenStream: Send + Sync,
{}
-// These are safe since we ensure that they hold for all fields in the `_dummy` function.
-//
-// These impls are only here because the compiler takes forever to compute the Send and Sync
-// bounds without them.
-// FIXME: Remove these impls when the compiler can compute the bounds quickly again.
-// See https://github.com/rust-lang/rust/issues/60846
-#[cfg(all(bootstrap, parallel_compiler))]
-unsafe impl Send for TokenTree {}
-#[cfg(all(bootstrap, parallel_compiler))]
-unsafe impl Sync for TokenTree {}
-
impl TokenTree {
/// Use this token tree as a matcher to parse given tts.
pub fn parse(cx: &base::ExtCtxt<'_>, mtch: &[quoted::TokenTree], tts: TokenStream)
}
/// Map string to parser (via tts)
-pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
+pub fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
}
Ok(Assert { cond_expr, custom_message })
}
-fn parse_custom_message<'a>(parser: &mut Parser<'a>) -> Option<TokenStream> {
+fn parse_custom_message(parser: &mut Parser<'_>) -> Option<TokenStream> {
let ts = parser.parse_tokens();
if !ts.is_empty() {
Some(ts)
pub type EnumNonMatchCollapsedFunc<'a> =
Box<dyn FnMut(&mut ExtCtxt<'_>, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
-pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
- -> RefCell<CombineSubstructureFunc<'a>> {
+pub fn combine_substructure(f: CombineSubstructureFunc<'_>)
+ -> RefCell<CombineSubstructureFunc<'_>> {
RefCell::new(f)
}
}
impl<'a> Path<'a> {
- pub fn new<'r>(path: Vec<&'r str>) -> Path<'r> {
+ pub fn new(path: Vec<&str>) -> Path<'_> {
Path::new_(path, None, Vec::new(), PathKind::Std)
}
- pub fn new_local<'r>(path: &'r str) -> Path<'r> {
+ pub fn new_local(path: &str) -> Path<'_> {
Path::new_(vec![path], None, Vec::new(), PathKind::Local)
}
pub fn new_<'r>(path: Vec<&'r str>,
pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
Borrowed(None, ast::Mutability::Immutable)
}
-pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
+pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
Ptr(ty, borrowed_ptrty())
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(in_band_lifetimes)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(rust_2018_idioms)]
-#![deny(internal)]
#![deny(unused_lifetimes)]
#![feature(const_fn)]
associated_type_defaults,
associated_types,
async_await,
+ async_closure,
attr,
attributes,
attr_literals,
cfg_target_thread_local,
cfg_target_vendor,
char,
+ clippy,
clone,
Clone,
clone_closures,
custom_inner_attributes,
custom_test_frameworks,
c_variadic,
+ declare_lint_pass,
decl_macro,
Default,
default_lib_allocator,
if_while_or_patterns,
ignore,
impl_header_lifetime_elision,
+ impl_lint_pass,
impl_trait_in_bindings,
import_shadowing,
index,
link_llvm_intrinsics,
link_name,
link_section,
+ LintPass,
lint_reasons,
literal,
local_inner_macros,
match_beginning_vert,
match_default_bindings,
may_dangle,
+ member_constraints,
message,
meta,
min_const_fn,
let fg;
let bg;
unsafe {
+ #[allow(deprecated)]
let mut buffer_info = ::std::mem::uninitialized();
if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), &mut buffer_info) != 0 {
fg = bits_to_color(buffer_info.wAttributes);
pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
exception: *mut _Unwind_Exception);
+#[cfg_attr(feature = "llvm-libunwind",
+ link(name = "unwind", kind = "static"))]
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
}
pub use _Unwind_Action::*;
+ #[cfg_attr(feature = "llvm-libunwind",
+ link(name = "unwind", kind = "static"))]
extern "C" {
pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
pub const UNWIND_POINTER_REG: c_int = 12;
pub const UNWIND_IP_REG: c_int = 15;
+ #[cfg_attr(feature = "llvm-libunwind",
+ link(name = "unwind", kind = "static"))]
extern "C" {
fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
regclass: _Unwind_VRS_RegClass,
cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
// Not 32-bit iOS
+ #[cfg_attr(feature = "llvm-libunwind",
+ link(name = "unwind", kind = "static"))]
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
}
} else {
// 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
+ #[cfg_attr(feature = "llvm-libunwind",
+ link(name = "unwind", kind = "static"))]
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
# 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: 2019-05-23
+date: 2019-07-04
rustc: beta
cargo: beta
return f.c;
}
+struct quad_floats {
+ float a;
+ float b;
+ float c;
+ float d;
+};
+
+float get_c_exhaust_sysv64_ints(
+ void *a,
+ void *b,
+ void *c,
+ void *d,
+ void *e,
+ void *f,
+ // `f` used the last integer register, so `g` goes on the stack.
+ // It also used to bring the "count of available integer registers" down to
+ // `-1` which broke the next SSE-only aggregate argument (`h`) - see #62350.
+ void *g,
+ struct quad_floats h
+) {
+ return h.c;
+}
+
// Calculates the average of `(x + y) / n` where x: i64, y: f64. There must be exactly n pairs
// passed as variadic arguments. There are two versions of this function: the
// variadic one, and the one that takes a `va_list`.
-// Test that `-Zpgo-gen` creates expected instrumentation artifacts in LLVM IR.
+// Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
// Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms.
// needs-profiler-support
-// compile-flags: -Z pgo-gen -Ccodegen-units=1 -Cpanic=abort
+// compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort
// CHECK: @__llvm_profile_raw_version =
// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
// aux-build:point.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph -Cpanic=unwind
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(panic_unwind)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
// aux-build:point.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
// aux-build:point.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
// revisions:cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// results in a change of the ICH for the enum's metadata, and that it stays
// the same between rev2 and rev3.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -C debug-assertions
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// results in a change of the ICH for the struct's metadata, and that it stays
// the same between rev2 and rev3.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// results in a change of the ICH for the trait's metadata, and that it stays
// the same between rev2 and rev3.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// results in a change of the ICH for the enum's metadata, and that it stays
// the same between rev2 and rev3.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
// the nested items (or even added new ones).
// revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "rlib"]
#![feature(rustc_attrs)]
// aux-build:incremental_proc_macro_aux.rs
// revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test makes sure that we still find the proc-macro registrar function
// when we compile proc-macros incrementally (see #47292).
// revisions:cfail1 cfail2 cfail3
// compile-flags:-Zquery-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
// revisions:cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph --test
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![crate_type = "rlib"]
// subsequent runs) if incremental compilation is enabled.
// revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(on_unimplemented)]
#![deny(unused_attributes)]
// enabled.
// revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![deny(unused_attributes)]
// revisions: cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
#![feature(rustc_attrs)]
// revisions: cfail1 cfail2 cfail3
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test case makes sure that we can compile with incremental compilation
// enabled when there are macros exported from this crate. (See #37756)
// Note that we specify -g so that the SourceFiles actually get referenced by the
// incr. comp. cache:
// compile-flags: -Z query-dep-graph -g
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type= "rlib"]
// revisions: cfail1 cfail2
// compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
#![feature(rustc_attrs)]
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -O
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -O
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![crate_type="rlib"]
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Coverflow-checks=on
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
#![warn(const_err)]
cpp-executable:
$(RUSTC) -Clinker-plugin-lto=on \
- -Zpgo-gen="$(TMPDIR)"/cpp-profdata \
+ -Cprofile-generate="$(TMPDIR)"/cpp-profdata \
-o "$(TMPDIR)"/librustlib-xlto.a \
$(COMMON_FLAGS) \
./rustlib.rs
-o "$(TMPDIR)"/cpp-profdata/merged.profdata \
"$(TMPDIR)"/cpp-profdata/default_*.profraw
$(RUSTC) -Clinker-plugin-lto=on \
- -Zpgo-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
+ -Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
-o "$(TMPDIR)"/librustlib-xlto.a \
$(COMMON_FLAGS) \
./rustlib.rs
$(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3
(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
$(RUSTC) -Clinker-plugin-lto=on \
- -Zpgo-gen="$(TMPDIR)"/rs-profdata \
+ -Cprofile-generate="$(TMPDIR)"/rs-profdata \
-L$(TMPDIR) \
$(COMMON_FLAGS) \
-Clinker=$(CLANG) \
rm "$(TMPDIR)"/libxyz.a
(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
$(RUSTC) -Clinker-plugin-lto=on \
- -Zpgo-use="$(TMPDIR)"/rs-profdata/merged.profdata \
+ -Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \
-L$(TMPDIR) \
$(COMMON_FLAGS) \
-Clinker=$(CLANG) \
-include ../tools.mk
-COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)"
+COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
# https://github.com/rust-lang/rust/issues/61002
-include ../tools.mk
-COMPILE_FLAGS=-O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)"
+COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)"
# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
# https://github.com/rust-lang/rust/issues/61002
-include ../tools.mk
-COMPILE_FLAGS=-g -Z pgo-gen="$(TMPDIR)"
+COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)"
# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
# https://github.com/rust-lang/rust/issues/61002
all:
# Compile the test program with instrumentation
- $(RUSTC) $(COMMON_FLAGS) -Z pgo-gen="$(TMPDIR)" main.rs
+ $(RUSTC) $(COMMON_FLAGS) -Cprofile-generate="$(TMPDIR)" main.rs
# Run it in order to generate some profiling data
$(call RUN,main some-argument) || exit 1
# Postprocess the profiling data so it can be used by the compiler
-o "$(TMPDIR)"/merged.profdata \
"$(TMPDIR)"/default_*.profraw
# Compile the test program again, making use of the profiling data
- $(RUSTC) $(COMMON_FLAGS) -Z pgo-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs
+ $(RUSTC) $(COMMON_FLAGS) -Cprofile-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs
# Check that the generate IR contains some things that we expect
#
# We feed the file into LLVM FileCheck tool *in reverse* so that we see the
use std::mem;
fn main() {
+ #[allow(deprecated)]
let xs: [u8; 4] = unsafe { mem::uninitialized() };
let y = xs[0] + xs[1];
}
// ignore-stage1
// compile-flags: -D crate-not-okay
-#![feature(plugin, rustc_attrs)]
+#![feature(plugin, custom_attribute, custom_inner_attributes, rustc_attrs)]
+
#![plugin(lint_for_crate)]
#![rustc_crate_okay]
#![rustc_crate_blue]
#![rustc_crate_grey]
#![rustc_crate_green]
-pub fn main() { }
+fn main() {}
// extern-return-TwoU64s
// foreign-fn-with-byval
// issue-28676
+// issue-62350-sysv-neg-reg-counts
// struct-return
// ignore-android
#[derive(Copy, Clone)]
pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
+ #[derive(Copy, Clone)]
+ pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
+
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Floats { a: f64, b: u8, c: f64 }
pub fn get_z(x: S) -> u64;
pub fn get_c_many_params(_: *const (), _: *const (),
_: *const (), _: *const (), f: Quad) -> u64;
+ pub fn get_c_exhaust_sysv64_ints(
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ h: QuadFloats,
+ ) -> f32;
pub fn rust_dbg_abi_1(q: Quad) -> Quad;
pub fn rust_dbg_abi_2(f: Floats) -> Floats;
}
test();
}
+ fn test_62350() {
+ use std::ptr;
+ unsafe {
+ let null = ptr::null();
+ let q = QuadFloats {
+ a: 10.2,
+ b: 20.3,
+ c: 30.4,
+ d: 40.5
+ };
+ assert_eq!(
+ get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
+ q.c,
+ );
+ }
+ }
+
+ pub fn issue_62350() {
+ test_62350();
+ }
+
fn test1() {
unsafe {
let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa,
extern_return_twou64s();
foreign_fn_with_byval();
issue_28676();
+ issue_62350();
struct_return();
}
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+#![allow(improper_ctypes)]
+
+// ignore-wasm32-bare no libc to test ffi with
+
+#[derive(Copy, Clone)]
+pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
+
+mod rustrt {
+ use super::QuadFloats;
+
+ #[link(name = "rust_test_helpers", kind = "static")]
+ extern {
+ pub fn get_c_exhaust_sysv64_ints(
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ _: *const (),
+ h: QuadFloats,
+ ) -> f32;
+ }
+}
+
+fn test() {
+ unsafe {
+ let null = std::ptr::null();
+ let q = QuadFloats {
+ a: 10.2,
+ b: 20.3,
+ c: 30.4,
+ d: 40.5
+ };
+ assert_eq!(
+ rustrt::get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
+ q.c,
+ );
+ }
+}
+
+pub fn main() {
+ test();
+}
--- /dev/null
+// Test that we don't duplicate storage for futures moved around in .await, and
+// for futures moved into other futures.
+//
+// The exact sizes can change by a few bytes (we'd like to know when they do).
+// What we don't want to see is the wrong multiple of 1024 (the size of BigFut)
+// being reflected in the size.
+//
+// See issue #59123 for a full explanation.
+
+// edition:2018
+
+#![feature(async_await)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+const BIG_FUT_SIZE: usize = 1024;
+struct BigFut([u8; BIG_FUT_SIZE]);
+
+impl BigFut {
+ fn new() -> Self {
+ BigFut([0; BIG_FUT_SIZE])
+ } }
+
+impl Drop for BigFut {
+ fn drop(&mut self) {}
+}
+
+impl Future for BigFut {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+#[allow(dead_code)]
+struct Joiner {
+ a: Option<BigFut>,
+ b: Option<BigFut>,
+ c: Option<BigFut>,
+}
+
+impl Future for Joiner {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(())
+ }
+}
+
+fn noop() {}
+
+async fn single() {
+ let x = BigFut::new();
+ x.await;
+}
+
+async fn single_with_noop() {
+ let x = BigFut::new();
+ noop();
+ x.await;
+}
+
+async fn joined() {
+ let a = BigFut::new();
+ let b = BigFut::new();
+ let c = BigFut::new();
+
+ let joiner = Joiner {
+ a: Some(a),
+ b: Some(b),
+ c: Some(c),
+ };
+ joiner.await
+}
+
+async fn joined_with_noop() {
+ let a = BigFut::new();
+ let b = BigFut::new();
+ let c = BigFut::new();
+
+ let joiner = Joiner {
+ a: Some(a),
+ b: Some(b),
+ c: Some(c),
+ };
+ noop();
+ joiner.await
+}
+
+fn main() {
+ assert_eq!(1028, std::mem::size_of_val(&single()));
+ assert_eq!(1032, std::mem::size_of_val(&single_with_noop()));
+ assert_eq!(3084, std::mem::size_of_val(&joined()));
+ assert_eq!(3084, std::mem::size_of_val(&joined_with_noop()));
+}
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
#[path = "../auxiliary/arc_wake.rs"]
mod arc_wake;
fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) }
async fn await1_level1() -> u8 {
- await!(base())
+ base().await
}
async fn await2_level1() -> u8 {
- await!(base()) + await!(base())
+ base().await + base().await
}
async fn await3_level1() -> u8 {
- await!(base()) + await!(base()) + await!(base())
+ base().await + base().await + base().await
}
async fn await3_level2() -> u8 {
- await!(await3_level1()) + await!(await3_level1()) + await!(await3_level1())
+ await3_level1().await + await3_level1().await + await3_level1().await
}
async fn await3_level3() -> u8 {
- await!(await3_level2()) + await!(await3_level2()) + await!(await3_level2())
+ await3_level2().await + await3_level2().await + await3_level2().await
}
async fn await3_level4() -> u8 {
- await!(await3_level3()) + await!(await3_level3()) + await!(await3_level3())
+ await3_level3().await + await3_level3().await + await3_level3().await
}
async fn await3_level5() -> u8 {
- await!(await3_level4()) + await!(await3_level4()) + await!(await3_level4())
+ await3_level4().await + await3_level4().await + await3_level4().await
}
fn main() {
// handled incorrectly in generators.
// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
#![allow(unused)]
use std::future::Future;
fn main() {
let fut = async {
let _rc = Rc::new(()); // Also crashes with Arc
- await!(Never());
+ Never().await;
};
let _bla = fut; // Moving the future is required.
}
+++ /dev/null
-#![allow(unused_attributes)]
-
-// This test ensures we can attach attributes to the formals in all
-// places where generic parameter lists occur, assuming appropriate
-// feature gates are enabled.
-//
-// (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.)
-
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-
-struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
-struct StTy<#[rustc_ty_struct] I>(I);
-
-enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
-enum EnTy<#[rustc_ty_enum] J> { A(J), B }
-
-trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
-
-type TyLt<#[rustc_lt_type] 'd> = &'d u32;
-type TyTy<#[rustc_ty_type] L> = (L, );
-
-impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
-impl<#[rustc_ty_inherent] M> StTy<M> { }
-
-impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
- fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
-}
-impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
- fn foo(&self, _: N) { }
-}
-
-fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-fn f_ty<#[rustc_ty_fn] O>(_: O) { }
-
-impl<I> StTy<I> {
- fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
- fn m_ty<#[rustc_ty_meth] P>(_: P) { }
-}
-
-fn hof_lt<Q>(_: Q)
- where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-{
-}
-
-fn main() {
-
-}
--- /dev/null
+#![feature(rustc_private)]
+
+fn main() {
+ #[cfg(unix)]
+ run()
+}
+
+#[cfg(unix)]
+fn run() {
+ extern crate libc;
+ use std::process::Command;
+ use std::os::unix::prelude::*;
+
+ let mut p = Command::new("/bin/sh")
+ .arg("-c").arg("true")
+ .uid(unsafe { libc::getuid() })
+ .gid(unsafe { libc::getgid() })
+ .spawn().unwrap();
+ assert!(p.wait().unwrap().success());
+
+ // if we're already root, this isn't a valid test. Most of the bots run
+ // as non-root though (android is an exception).
+ if unsafe { libc::getuid() != 0 } {
+ assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
+ }
+}
--- /dev/null
+// Test that values are not leaked in async functions, even in the cases where:
+// * Dropping one of the values panics while running the future.
+// * The future is dropped at one of its suspend points.
+// * Dropping one of the values panics while dropping the future.
+
+// run-pass
+// edition:2018
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![feature(slice_patterns)]
+#![feature(async_await)]
+
+use std::{
+ cell::{Cell, RefCell},
+ future::Future,
+ marker::Unpin,
+ panic,
+ pin::Pin,
+ ptr,
+ rc::Rc,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ usize,
+};
+
+struct InjectedFailure;
+
+struct Defer<T> {
+ ready: bool,
+ value: Option<T>,
+}
+
+impl<T: Unpin> Future for Defer<T> {
+ type Output = T;
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
+ if self.ready {
+ Poll::Ready(self.value.take().unwrap())
+ } else {
+ self.ready = true;
+ Poll::Pending
+ }
+ }
+}
+
+/// Allocator tracks the creation and destruction of `Ptr`s.
+/// The `failing_op`-th operation will panic.
+struct Allocator {
+ data: RefCell<Vec<bool>>,
+ failing_op: usize,
+ cur_ops: Cell<usize>,
+}
+
+impl panic::UnwindSafe for Allocator {}
+impl panic::RefUnwindSafe for Allocator {}
+
+impl Drop for Allocator {
+ fn drop(&mut self) {
+ let data = self.data.borrow();
+ if data.iter().any(|d| *d) {
+ panic!("missing free: {:?}", data);
+ }
+ }
+}
+
+impl Allocator {
+ fn new(failing_op: usize) -> Self {
+ Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) }
+ }
+ fn alloc(&self) -> impl Future<Output = Ptr<'_>> + '_ {
+ self.fallible_operation();
+
+ let mut data = self.data.borrow_mut();
+
+ let addr = data.len();
+ data.push(true);
+ Defer { ready: false, value: Some(Ptr(addr, self)) }
+ }
+ fn fallible_operation(&self) {
+ self.cur_ops.set(self.cur_ops.get() + 1);
+
+ if self.cur_ops.get() == self.failing_op {
+ panic!(InjectedFailure);
+ }
+ }
+}
+
+// Type that tracks whether it was dropped and can panic when it's created or
+// destroyed.
+struct Ptr<'a>(usize, &'a Allocator);
+impl<'a> Drop for Ptr<'a> {
+ fn drop(&mut self) {
+ match self.1.data.borrow_mut()[self.0] {
+ false => panic!("double free at index {:?}", self.0),
+ ref mut d => *d = false,
+ }
+
+ self.1.fallible_operation();
+ }
+}
+
+async fn dynamic_init(a: Rc<Allocator>, c: bool) {
+ let _x;
+ if c {
+ _x = Some(a.alloc().await);
+ }
+}
+
+async fn dynamic_drop(a: Rc<Allocator>, c: bool) {
+ let x = a.alloc().await;
+ if c {
+ Some(x)
+ } else {
+ None
+ };
+}
+
+struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>);
+async fn struct_dynamic_drop(a: Rc<Allocator>, c0: bool, c1: bool, c: bool) {
+ for i in 0..2 {
+ let x;
+ let y;
+ if (c0 && i == 0) || (c1 && i == 1) {
+ x = (a.alloc().await, a.alloc().await, a.alloc().await);
+ y = TwoPtrs(a.alloc().await, a.alloc().await);
+ if c {
+ drop(x.1);
+ a.alloc().await;
+ drop(y.0);
+ a.alloc().await;
+ }
+ }
+ }
+}
+
+async fn field_assignment(a: Rc<Allocator>, c0: bool) {
+ let mut x = (TwoPtrs(a.alloc().await, a.alloc().await), a.alloc().await);
+
+ x.1 = a.alloc().await;
+ x.1 = a.alloc().await;
+
+ let f = (x.0).0;
+ a.alloc().await;
+ if c0 {
+ (x.0).0 = f;
+ }
+ a.alloc().await;
+}
+
+async fn assignment(a: Rc<Allocator>, c0: bool, c1: bool) {
+ let mut _v = a.alloc().await;
+ let mut _w = a.alloc().await;
+ if c0 {
+ drop(_v);
+ }
+ _v = _w;
+ if c1 {
+ _w = a.alloc().await;
+ }
+}
+
+async fn array_simple(a: Rc<Allocator>) {
+ let _x = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
+}
+
+async fn vec_simple(a: Rc<Allocator>) {
+ let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
+}
+
+async fn mixed_drop_and_nondrop(a: Rc<Allocator>) {
+ // check that destructor panics handle drop
+ // and non-drop blocks in the same scope correctly.
+ //
+ // Surprisingly enough, this used to not work.
+ let (x, y, z);
+ x = a.alloc().await;
+ y = 5;
+ z = a.alloc().await;
+}
+
+#[allow(unreachable_code)]
+async fn vec_unreachable(a: Rc<Allocator>) {
+ let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, return];
+}
+
+async fn slice_pattern_one_of(a: Rc<Allocator>, i: usize) {
+ let array = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
+ let _x = match i {
+ 0 => {
+ let [a, ..] = array;
+ a
+ }
+ 1 => {
+ let [_, a, ..] = array;
+ a
+ }
+ 2 => {
+ let [_, _, a, _] = array;
+ a
+ }
+ 3 => {
+ let [_, _, _, a] = array;
+ a
+ }
+ _ => panic!("unmatched"),
+ };
+ a.alloc().await;
+}
+
+async fn subslice_pattern_from_end_with_drop(a: Rc<Allocator>, arg: bool, arg2: bool) {
+ let arr = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await];
+ if arg2 {
+ drop(arr);
+ return;
+ }
+
+ if arg {
+ let [.., _x, _] = arr;
+ } else {
+ let [_, _y..] = arr;
+ }
+ a.alloc().await;
+}
+
+async fn subslice_pattern_reassign(a: Rc<Allocator>) {
+ let mut ar = [a.alloc().await, a.alloc().await, a.alloc().await];
+ let [_, _, _x] = ar;
+ ar = [a.alloc().await, a.alloc().await, a.alloc().await];
+ let [_, _y..] = ar;
+ a.alloc().await;
+}
+
+fn run_test<F, G>(cx: &mut Context<'_>, ref f: F)
+where
+ F: Fn(Rc<Allocator>) -> G,
+ G: Future<Output = ()>,
+{
+ for polls in 0.. {
+ // Run without any panics to find which operations happen after the
+ // penultimate `poll`.
+ let first_alloc = Rc::new(Allocator::new(usize::MAX));
+ let mut fut = Box::pin(f(first_alloc.clone()));
+ let mut ops_before_last_poll = 0;
+ let mut completed = false;
+ for _ in 0..polls {
+ ops_before_last_poll = first_alloc.cur_ops.get();
+ if let Poll::Ready(()) = fut.as_mut().poll(cx) {
+ completed = true;
+ }
+ }
+ drop(fut);
+
+ // Start at `ops_before_last_poll` so that we will always be able to
+ // `poll` the expected number of times.
+ for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() {
+ let alloc = Rc::new(Allocator::new(failing_op + 1));
+ let f = &f;
+ let cx = &mut *cx;
+ let result = panic::catch_unwind(panic::AssertUnwindSafe(move || {
+ let mut fut = Box::pin(f(alloc));
+ for _ in 0..polls {
+ let _ = fut.as_mut().poll(cx);
+ }
+ drop(fut);
+ }));
+ match result {
+ Ok(..) => panic!("test executed more ops on first call"),
+ Err(e) => {
+ if e.downcast_ref::<InjectedFailure>().is_none() {
+ panic::resume_unwind(e);
+ }
+ }
+ }
+ }
+
+ if completed {
+ break;
+ }
+ }
+}
+
+fn clone_waker(data: *const ()) -> RawWaker {
+ RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop))
+}
+
+fn main() {
+ let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) };
+ let context = &mut Context::from_waker(&waker);
+
+ run_test(context, |a| dynamic_init(a, false));
+ run_test(context, |a| dynamic_init(a, true));
+ run_test(context, |a| dynamic_drop(a, false));
+ run_test(context, |a| dynamic_drop(a, true));
+
+ run_test(context, |a| assignment(a, false, false));
+ run_test(context, |a| assignment(a, false, true));
+ run_test(context, |a| assignment(a, true, false));
+ run_test(context, |a| assignment(a, true, true));
+
+ run_test(context, |a| array_simple(a));
+ run_test(context, |a| vec_simple(a));
+ run_test(context, |a| vec_unreachable(a));
+
+ run_test(context, |a| struct_dynamic_drop(a, false, false, false));
+ run_test(context, |a| struct_dynamic_drop(a, false, false, true));
+ run_test(context, |a| struct_dynamic_drop(a, false, true, false));
+ run_test(context, |a| struct_dynamic_drop(a, false, true, true));
+ run_test(context, |a| struct_dynamic_drop(a, true, false, false));
+ run_test(context, |a| struct_dynamic_drop(a, true, false, true));
+ run_test(context, |a| struct_dynamic_drop(a, true, true, false));
+ run_test(context, |a| struct_dynamic_drop(a, true, true, true));
+
+ run_test(context, |a| field_assignment(a, false));
+ run_test(context, |a| field_assignment(a, true));
+
+ run_test(context, |a| mixed_drop_and_nondrop(a));
+
+ run_test(context, |a| slice_pattern_one_of(a, 0));
+ run_test(context, |a| slice_pattern_one_of(a, 1));
+ run_test(context, |a| slice_pattern_one_of(a, 2));
+ run_test(context, |a| slice_pattern_one_of(a, 3));
+
+ run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true));
+ run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false));
+ run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true));
+ run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false));
+ run_test(context, |a| subslice_pattern_reassign(a));
+}
fn main() {
// Check that the tail statement in the body unifies with something
for _ in 0..3 {
+ #[allow(deprecated)]
unsafe { std::mem::uninitialized() }
}
--- /dev/null
+// Test that we don't duplicate storage for a variable that is moved to another
+// binding. This used to happen in the presence of unwind and drop edges (see
+// `complex` below.)
+//
+// The exact sizes here can change (we'd like to know when they do). What we
+// don't want to see is the `complex` generator size being upwards of 2048 bytes
+// (which would indicate it is reserving space for two copies of Foo.)
+//
+// See issue #59123 for a full explanation.
+
+// edition:2018
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+const FOO_SIZE: usize = 1024;
+struct Foo([u8; FOO_SIZE]);
+
+impl Drop for Foo {
+ fn drop(&mut self) {}
+}
+
+fn move_before_yield() -> impl Generator<Yield = (), Return = ()> {
+ static || {
+ let first = Foo([0; FOO_SIZE]);
+ let _second = first;
+ yield;
+ // _second dropped here
+ }
+}
+
+fn noop() {}
+
+fn move_before_yield_with_noop() -> impl Generator<Yield = (), Return = ()> {
+ static || {
+ let first = Foo([0; FOO_SIZE]);
+ noop();
+ let _second = first;
+ yield;
+ // _second dropped here
+ }
+}
+
+// Today we don't have NRVO (we allocate space for both `first` and `second`,)
+// but we can overlap `first` with `_third`.
+fn overlap_move_points() -> impl Generator<Yield = (), Return = ()> {
+ static || {
+ let first = Foo([0; FOO_SIZE]);
+ yield;
+ let second = first;
+ yield;
+ let _third = second;
+ yield;
+ }
+}
+
+fn main() {
+ assert_eq!(1028, std::mem::size_of_val(&move_before_yield()));
+ assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop()));
+ assert_eq!(2056, std::mem::size_of_val(&overlap_move_points()));
+}
+++ /dev/null
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![feature(intrinsics)]
-
-mod rusti {
- extern "rust-intrinsic" {
- pub fn uninit<T>() -> T;
- }
-}
-pub fn main() {
- let _a : isize = unsafe {rusti::uninit()};
-}
}
fn main() {
- take(Handler::Default, Box::new(main));
+ #[allow(unused_must_use)] {
+ take(Handler::Default, Box::new(main));
+ }
}
#[inline(never)]
impl FromUnchecked for [u8; 1] {
unsafe fn from_unchecked() {
+ #[allow(deprecated)]
let mut array: Self = std::mem::uninitialized();
let _ptr = &mut array as *mut [u8] as *mut u8;
}
--- /dev/null
+// If a struct is packed and its last field has drop glue, then that
+// field needs to be Sized (to allow it to be destroyed out-of-place).
+//
+// This is checked by the compiler during wfcheck. That check used
+// to have problems with associated types in the last field - test
+// that this doesn't ICE.
+
+#![allow(unused_imports, dead_code)]
+
+pub struct S;
+
+pub trait Trait<R> { type Assoc; }
+
+impl<X> Trait<X> for S { type Assoc = X; }
+
+#[repr(C, packed)]
+struct PackedAssocSized {
+ pos: Box<<S as Trait<usize>>::Assoc>,
+}
+
+fn main() { println!("Hello, world!"); }
// in a runtime panic.
#![feature(never_type)]
+#![allow(deprecated)]
use std::{mem, panic};
// run-pass
+
#![allow(stable_features)]
+#![allow(unused_must_use)]
// ignore-emscripten no threads support
// run-pass
#![feature(decl_macro)]
-r#macro_rules! r#struct {
+macro_rules! r#struct {
($r#struct:expr) => { $r#struct }
}
#[allow(unconditional_recursion)]
fn recurse(array: &[u64]) {
unsafe { black_box(array.as_ptr() as u64); }
+ #[allow(deprecated)]
let local: [_; 1024] = unsafe { mem::uninitialized() };
recurse(&local);
}
unsafe {
// This should be safe, because we don't match on it unless it's fully formed,
// and it doesn't have a destructor.
+ #[allow(deprecated)]
let mut dest: MyEnum = mem::uninitialized();
while buf.len() > 0 {
match parse_my_enum(&mut dest, &mut buf) {
unsafe {
// This should be safe, because we don't match on it unless it's fully formed,
// and it doesn't have a destructor.
+ #[allow(deprecated)]
let mut dest: MyEnum = mem::uninitialized();
while buf.len() > 0 {
match parse_my_enum(&mut dest, &mut buf) {
unsafe {
// This should be safe, because we don't match on it unless it's fully formed,
// and it doesn't have a destructor.
+ #[allow(deprecated)]
let mut dest: MyEnum = mem::uninitialized();
while buf.len() > 0 {
match parse_my_enum(&mut dest, &mut buf) {
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-#[derive(Debug, PartialEq, Eq)]
-enum Foo {
- Bar(i32),
- Baz { i: i32 },
-}
-
-type FooAlias = Foo;
-type OptionAlias = Option<i32>;
-
-impl Foo {
- fn foo() -> Self {
- Self::Bar(3)
- }
-}
-
-fn main() {
- let t = FooAlias::Bar(1);
- assert_eq!(t, Foo::Bar(1));
- let t = FooAlias::Baz { i: 2 };
- assert_eq!(t, Foo::Baz { i: 2 });
- match t {
- FooAlias::Bar(_i) => {}
- FooAlias::Baz { i } => { assert_eq!(i, 2); }
- }
- assert_eq!(Foo::foo(), Foo::Bar(3));
-
- assert_eq!(OptionAlias::Some(4), Option::Some(4));
-}
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-#[derive(Debug, PartialEq, Eq)]
-enum Foo {
- Bar(i32),
- Baz { i: i32 },
-}
-
-type FooAlias = Foo;
-type OptionAlias = Option<i32>;
-
-impl Foo {
- fn foo() -> Self {
- Self::Bar(3)
- }
-}
-
-fn main() {
- let t = FooAlias::Bar(1);
- assert_eq!(t, Foo::Bar(1));
- let t = FooAlias::Baz { i: 2 };
- assert_eq!(t, Foo::Baz { i: 2 });
- match t {
- FooAlias::Bar(_i) => {}
- FooAlias::Baz { i } => { assert_eq!(i, 2); }
- }
- assert_eq!(Foo::foo(), Foo::Bar(3));
-
- assert_eq!(OptionAlias::Some(4), Option::Some(4));
-}
#[derive(Clone)]
struct Foo;
+#[allow(deprecated)]
pub fn main() {
unsafe {
let _x: Foo = mem::uninitialized();
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(extern_types)]
// compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// an empty crate still has one item to document: the crate root
// compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
//! (remember the crate root is still a module)
// compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(doc_keyword)]
// compile-flags:-Z unstable-options --show-coverage --document-private-items
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
// compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
//! gotta make sure we can count statics and consts correctly, too
// compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(trait_alias)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![doc(no_default_passes, passes = "collapse-docs unindent-comments")]
// ignore-tidy-cr
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This file checks the spans of intra-link warnings in a file with CRLF line endings. The
// .gitattributes file in this directory should enforce it.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
//! Test with [Foo::baz], [Bar::foo], ...
//! , [Uniooon::X] and [Qux::Z].
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
/// ```
/// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(private_doc_tests)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Foo {
/**
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test purpose is to check that unused_imports lint isn't fired
// by rustdoc. Why would it? Because when rustdoc is running, it uses
impl<U: Unsigned> Add<U> for UTerm {
type Output = U;
fn add(self, _: U) -> Self::Output {
+ #[allow(deprecated)]
unsafe { ::std::mem::uninitialized() }
}
}
/// Err("This is returned from `main`, leading to panic")?;
/// Ok::<(), &'static str>(())
/// ```
-///
-/// This also works with `Option<()>`s now:
-///
-/// ```rust
-/// Some(())
-/// ```
-///
-/// ```rust,should_panic
-/// let x: &[u32] = &[];
-/// let _ = x.iter().next()?;
-/// Some(())
-/// ```
pub fn check_process_termination() {}
extern crate rustc;
extern crate rustc_plugin;
-use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
- LintArray};
+use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc_plugin::Registry;
use syntax::ast;
declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
Warn, "Warn about other stuff"
);
-declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP]);
+declare_tool_lint!(
+ /// Some docs
+ pub rustc::TEST_RUSTC_TOOL_LINT,
+ Deny,
+ "Deny internal stuff"
+);
+
+declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP, TEST_RUSTC_TOOL_LINT]);
impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use std::collections::{HashMap, HashSet};
-#[deny(default_hash_types)]
+#[deny(rustc::default_hash_types)]
fn main() {
let _map: HashMap<String, String> = HashMap::default();
//~^ ERROR Prefer FxHashMap over HashMap, it has better performance
note: lint level defined here
--> $DIR/default_hash_types.rs:10:8
|
-LL | #[deny(default_hash_types)]
- | ^^^^^^^^^^^^^^^^^^
+LL | #[deny(rustc::default_hash_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
error: Prefer FxHashMap over HashMap, it has better performance
--- /dev/null
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_private)]
+#![deny(rustc::lint_pass_impl_without_macro)]
+
+extern crate rustc;
+
+use rustc::lint::{LintArray, LintPass};
+use rustc::{declare_lint, declare_lint_pass, impl_lint_pass, lint_array};
+
+declare_lint! {
+ pub TEST_LINT,
+ Allow,
+ "test"
+}
+
+struct Foo;
+
+impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
+ fn get_lints(&self) -> LintArray {
+ lint_array!(TEST_LINT)
+ }
+
+ fn name(&self) -> &'static str {
+ "Foo"
+ }
+}
+
+macro_rules! custom_lint_pass_macro {
+ () => {
+ struct Custom;
+
+ impl LintPass for Custom { //~ERROR implementing `LintPass` by hand
+ fn get_lints(&self) -> LintArray {
+ lint_array!(TEST_LINT)
+ }
+
+ fn name(&self) -> &'static str {
+ "Custom"
+ }
+ }
+ };
+}
+
+custom_lint_pass_macro!();
+
+struct Bar;
+
+impl_lint_pass!(Bar => [TEST_LINT]);
+
+declare_lint_pass!(Baz => [TEST_LINT]);
+
+fn main() {}
--- /dev/null
+error: implementing `LintPass` by hand
+ --> $DIR/lint_pass_impl_without_macro.rs:19:6
+ |
+LL | impl LintPass for Foo {
+ | ^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/lint_pass_impl_without_macro.rs:4:9
+ |
+LL | #![deny(rustc::lint_pass_impl_without_macro)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
+
+error: implementing `LintPass` by hand
+ --> $DIR/lint_pass_impl_without_macro.rs:33:14
+ |
+LL | impl LintPass for Custom {
+ | ^^^^^^^^
+...
+LL | custom_lint_pass_macro!();
+ | -------------------------- in this macro invocation
+ |
+ = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
+
+error: aborting due to 2 previous errors
+
// compile-flags: -Z unstable-options
#![feature(rustc_private)]
-#![deny(ty_pass_by_reference)]
+#![deny(rustc::ty_pass_by_reference)]
#![allow(unused)]
extern crate rustc;
note: lint level defined here
--> $DIR/pass_ty_by_ref.rs:4:9
|
-LL | #![deny(ty_pass_by_reference)]
- | ^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rustc::ty_pass_by_reference)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: passing `TyCtxt<'_>` by reference
--> $DIR/pass_ty_by_ref.rs:15:18
// compile-flags: -Z unstable-options
#![feature(rustc_private)]
-#![deny(usage_of_qualified_ty)]
+#![deny(rustc::usage_of_qualified_ty)]
#![allow(unused)]
extern crate rustc;
note: lint level defined here
--> $DIR/qualified_ty_ty_ctxt.rs:4:9
|
-LL | #![deny(usage_of_qualified_ty)]
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rustc::usage_of_qualified_ty)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: usage of qualified `ty::TyCtxt<'_>`
--> $DIR/qualified_ty_ty_ctxt.rs:27:16
use rustc::ty::{self, Ty, TyKind};
-#[deny(usage_of_ty_tykind)]
+#[deny(rustc::usage_of_ty_tykind)]
fn main() {
let sty = TyKind::Bool; //~ ERROR usage of `ty::TyKind::<kind>`
note: lint level defined here
--> $DIR/ty_tykind_usage.rs:9:8
|
-LL | #[deny(usage_of_ty_tykind)]
- | ^^^^^^^^^^^^^^^^^^
+LL | #[deny(rustc::usage_of_ty_tykind)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:14:9
#![warn(anonymous_parameters)]
// Test for the anonymous_parameters deprecation lint (RFC 1685)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2015
// run-rustfix
#![warn(anonymous_parameters)]
// Test for the anonymous_parameters deprecation lint (RFC 1685)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2015
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait ConstDefault {
const DEFAULT: Self;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(associated_type_bounds)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(associated_type_bounds)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(associated_type_bounds)]
}
}
-fn async_closure(x: u8) -> impl Future<Output = u8> {
- (async move |x: u8| -> u8 {
- wake_and_yield_once().await;
- x
- })(x)
-}
-
async fn async_fn(x: u8) -> u8 {
wake_and_yield_once().await;
x
}
impl Foo {
- async fn async_method(x: u8) -> u8 {
+ async fn async_assoc_item(x: u8) -> u8 {
unsafe {
unsafe_async_fn(x).await
}
}
+
+ async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 {
+ unsafe_async_fn(x).await
+ }
}
fn test_future_yields_once_then_returns<F, Fut>(f: F)
test! {
async_block,
async_nonmove_block,
- async_closure,
async_fn,
generic_async_fn,
async_fn_with_internal_borrow,
- Foo::async_method,
+ Foo::async_assoc_item,
|x| {
async move {
unsafe { unsafe_async_fn(x).await }
}
},
+ |x| {
+ async move {
+ unsafe { Foo::async_unsafe_assoc_item(x).await }
+ }
+ },
}
test_with_borrow! {
async_block_with_borrow_named_lifetime,
--- /dev/null
+// build-pass
+// edition:2018
+
+#![feature(async_await, async_closure)]
+
+macro_rules! match_expr {
+ ($x:expr) => {}
+}
+
+fn main() {
+ match_expr!(async || {});
+}
--- /dev/null
+// run-pass
+
+// edition:2018
+// aux-build:arc_wake.rs
+
+#![feature(async_await, async_closure)]
+
+extern crate arc_wake;
+
+use std::pin::Pin;
+use std::future::Future;
+use std::sync::{
+ Arc,
+ atomic::{self, AtomicUsize},
+};
+use std::task::{Context, Poll};
+use arc_wake::ArcWake;
+
+struct Counter {
+ wakes: AtomicUsize,
+}
+
+impl ArcWake for Counter {
+ fn wake(self: Arc<Self>) {
+ Self::wake_by_ref(&self)
+ }
+ fn wake_by_ref(arc_self: &Arc<Self>) {
+ arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+ }
+}
+
+struct WakeOnceThenComplete(bool);
+
+fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
+
+impl Future for WakeOnceThenComplete {
+ type Output = ();
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+ if self.0 {
+ Poll::Ready(())
+ } else {
+ cx.waker().wake_by_ref();
+ self.0 = true;
+ Poll::Pending
+ }
+ }
+}
+
+fn async_closure(x: u8) -> impl Future<Output = u8> {
+ (async move |x: u8| -> u8 {
+ wake_and_yield_once().await;
+ x
+ })(x)
+}
+
+fn test_future_yields_once_then_returns<F, Fut>(f: F)
+where
+ F: FnOnce(u8) -> Fut,
+ Fut: Future<Output = u8>,
+{
+ let mut fut = Box::pin(f(9));
+ let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
+ let waker = ArcWake::into_waker(counter.clone());
+ let mut cx = Context::from_waker(&waker);
+ assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx));
+ assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx));
+}
+
+fn main() {
+ macro_rules! test {
+ ($($fn_name:expr,)*) => { $(
+ test_future_yields_once_then_returns($fn_name);
+ )* }
+ }
+
+ test! {
+ async_closure,
+ }
+}
--- /dev/null
+// edition:2018
+#![feature(async_await)]
+
+// Regression test for issue #62382
+
+use std::future::Future;
+
+fn get_future() -> impl Future<Output = ()> {
+ panic!()
+}
+
+async fn foo() {
+ let a; //~ ERROR type inside `async` object must be known in this context
+ get_future().await;
+}
+
+fn main() {}
--- /dev/null
+error[E0698]: type inside `async` object must be known in this context
+ --> $DIR/async-error-span.rs:13:9
+ |
+LL | let a;
+ | ^ cannot infer type
+ |
+note: the type is part of the `async` object because of this `await`
+ --> $DIR/async-error-span.rs:14:5
+ |
+LL | get_future().await;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0698`.
+++ /dev/null
-// edition:2018
-
-#![feature(arbitrary_self_types, async_await, await_macro, pin)]
-
-use std::ops::Add;
-
-async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
-//~^ ERROR ambiguous lifetime bound in `async fn`
-
-async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
- _: impl for<'a> Add<&'a u8>,
- _: impl for<'b> Add<&'b u8>,
- _: &'c u8,
-) {}
-
-async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
-//~^ ambiguous lifetime bound in `async fn`
-
-fn main() {}
+++ /dev/null
-error: ambiguous lifetime bound in `async fn`
- --> $DIR/async-fn-multiple-lifetimes.rs:7:65
- |
-LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
- | ^ neither `'a` nor `'b` outlives the other
- |
- = note: multiple unrelated lifetimes are not allowed in `async fn`.
- = note: if you're using argument-position elided lifetimes, consider switching to a single named lifetime.
-
-error: ambiguous lifetime bound in `async fn`
- --> $DIR/async-fn-multiple-lifetimes.rs:16:52
- |
-LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
- | ^ the elided lifetimes here do not outlive one another
- |
- = note: multiple unrelated lifetimes are not allowed in `async fn`.
- = note: if you're using argument-position elided lifetimes, consider switching to a single named lifetime.
-
-error: aborting due to 2 previous errors
-
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
#![allow(dead_code)]
struct HasLifetime<'a>(&'a bool);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// compile-flags: --crate-type lib
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
macro_rules! match_expr {
($x:expr) => {}
fn main() {
match_expr!(async {});
- match_expr!(async || {});
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
trait MyClosure {
type Args;
async fn f() {
let messages: MyStream<dyn FnMut()> = unimplemented!();
- await!(get_future(messages));
+ get_future(messages).await;
}
fn main() {}
// edition:2018
#![allow(non_camel_case_types)]
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
mod outer_mod {
pub mod await { //~ ERROR expected identifier, found reserved keyword `await`
// edition:2018
// aux-build:arc_wake.rs
-#![feature(async_await, await_macro)]
+#![feature(async_await, async_closure, await_macro)]
extern crate arc_wake;
--- /dev/null
+// Regression test for #62312
+
+// check-pass
+// edition:2018
+
+#![feature(async_await)]
+
+async fn make_boxed_object() -> Box<dyn Send> {
+ Box::new(()) as _
+}
+
+async fn await_object() {
+ let _ = make_boxed_object().await;
+}
+
+fn main() {}
// run-pass
#![allow(unused_variables)]
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
// Test that the drop order for parameters in a fn and async fn matches up. Also test that
// parameters (used or unused) are not dropped until the async fn completes execution.
// run-pass
#![allow(unused_variables)]
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
// Test that the drop order for parameters in a fn and async fn matches up. Also test that
// parameters (used or unused) are not dropped until the async fn completes execution.
async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
}
+ accept_item! {
+ impl Foo {
+ async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+ }
+ }
+
let inside_closure = || {
async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
};
| ^^^^^
error[E0670]: `async fn` is not permitted in the 2015 edition
- --> $DIR/edition-deny-async-fns-2015.rs:32:9
+ --> $DIR/edition-deny-async-fns-2015.rs:16:5
+ |
+LL | async fn foo() {}
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:20:5
+ |
+LL | async fn foo() {}
+ | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+ --> $DIR/edition-deny-async-fns-2015.rs:38:9
|
LL | async fn bar() {}
| ^^^^^
| ^^^^^
error[E0670]: `async fn` is not permitted in the 2015 edition
- --> $DIR/edition-deny-async-fns-2015.rs:16:5
+ --> $DIR/edition-deny-async-fns-2015.rs:33:13
|
-LL | async fn foo() {}
- | ^^^^^
+LL | async fn bar() {}
+ | ^^^^^
error[E0706]: trait fns cannot be declared `async`
--> $DIR/edition-deny-async-fns-2015.rs:20:5
LL | async fn foo() {}
| ^^^^^^^^^^^^^^^^^
-error[E0670]: `async fn` is not permitted in the 2015 edition
- --> $DIR/edition-deny-async-fns-2015.rs:20:5
- |
-LL | async fn foo() {}
- | ^^^^^
-
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0670`.
--- /dev/null
+// edition:2018
+// gate-test-async_closure
+
+fn f() {
+ let _ = async || {}; //~ ERROR async closures are unstable
+}
+
+fn main() {}
--- /dev/null
+error[E0658]: async closures are unstable
+ --> $DIR/feature-async-closure.rs:5:13
+ |
+LL | let _ = async || {};
+ | ^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62290
+ = help: add #![feature(async_closure)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// compile-flags: --crate-type lib
// while those two fields were at the same offset (which is impossible).
// That is, memory ordering of `(X, ())`, but offsets of `((), X)`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
#![feature(async_await)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(arbitrary_self_types, async_await, await_macro)]
+#![feature(arbitrary_self_types, async_await)]
use std::task::{self, Poll};
use std::future::Future;
async fn __receive<WantFn, Fut>(want: WantFn) -> ()
where Fut: Future<Output = ()>, WantFn: Fn(&Box<dyn Send + 'static>) -> Fut,
{
- await!(lazy(|_| ()));
+ lazy(|_| ()).await;
}
pub fn basic_spawn_receive() {
- async { await!(__receive(|_| async { () })) };
+ async { __receive(|_| async { () }).await };
}
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
use std::sync::Arc;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
use std::future::Future;
#[allow(unused)]
async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 {
- let y = await!(future);
+ let y = future.await;
*x + y
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
struct Xyz {
a: u64,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
use std::future::Future;
// compile-flags: --edition=2018
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
pub enum Uninhabited { }
#[allow(unused)]
async fn contains_never() {
let error = uninhabited_async();
- await!(noop());
+ noop().await;
let error2 = error;
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
#![feature(async_await)]
// Test that existential types are allowed to contain late-bound regions.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
#![feature(async_await, existential_type)]
// aux-build:issue-60674.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
#![feature(async_await)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
//
// Tests that we properly handle StorageDead/StorageLives for temporaries
--- /dev/null
+// edition:2018
+
+#![feature(async_await)]
+
+async fn print_dur() {}
+
+fn main() {
+ async { let (); }.await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+ async {
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+ let task1 = print_dur().await;
+ }.await;
+ (|_| 2333).await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+ //~^^ ERROR
+}
--- /dev/null
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-1.rs:8:5
+ |
+LL | fn main() {
+ | ---- this is not `async`
+LL | async { let (); }.await;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-1.rs:10:5
+ |
+LL | fn main() {
+ | ---- this is not `async`
+...
+LL | / async {
+LL | |
+LL | | let task1 = print_dur().await;
+LL | | }.await;
+ | |___________^ only allowed inside `async` functions and blocks
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-1.rs:14:5
+ |
+LL | fn main() {
+ | ---- this is not `async`
+...
+LL | (|_| 2333).await;
+ | ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]: std::future::Future` is not satisfied
+ --> $DIR/issue-62009-1.rs:14:5
+ |
+LL | (|_| 2333).await;
+ | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]`
+ |
+ = note: required by `std::future::poll_with_tls_context`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// edition:2018
+
+#![feature(async_await, async_closure)]
+
+async fn print_dur() {}
+
+fn main() {
+ (async || 2333)().await;
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
+}
--- /dev/null
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-62009-2.rs:8:5
+ |
+LL | fn main() {
+ | ---- this is not `async`
+LL | (async || 2333)().await;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to previous error
+
+++ /dev/null
-// edition:2018
-
-#![feature(async_await)]
-
-async fn print_dur() {}
-
-fn main() {
- async { let (); }.await;
- //~^ ERROR `await` is only allowed inside `async` functions and blocks
- async {
- //~^ ERROR `await` is only allowed inside `async` functions and blocks
- let task1 = print_dur().await;
- }.await;
- (async || 2333)().await;
- //~^ ERROR `await` is only allowed inside `async` functions and blocks
- (|_| 2333).await;
- //~^ ERROR `await` is only allowed inside `async` functions and blocks
- //~^^ ERROR
-}
+++ /dev/null
-error[E0728]: `await` is only allowed inside `async` functions and blocks
- --> $DIR/issue-62009.rs:8:5
- |
-LL | fn main() {
- | ---- this is not `async`
-LL | async { let (); }.await;
- | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
-
-error[E0728]: `await` is only allowed inside `async` functions and blocks
- --> $DIR/issue-62009.rs:10:5
- |
-LL | fn main() {
- | ---- this is not `async`
-...
-LL | / async {
-LL | |
-LL | | let task1 = print_dur().await;
-LL | | }.await;
- | |___________^ only allowed inside `async` functions and blocks
-
-error[E0728]: `await` is only allowed inside `async` functions and blocks
- --> $DIR/issue-62009.rs:14:5
- |
-LL | fn main() {
- | ---- this is not `async`
-...
-LL | (async || 2333)().await;
- | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
-
-error[E0728]: `await` is only allowed inside `async` functions and blocks
- --> $DIR/issue-62009.rs:16:5
- |
-LL | fn main() {
- | ---- this is not `async`
-...
-LL | (|_| 2333).await;
- | ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
-
-error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied
- --> $DIR/issue-62009.rs:16:5
- |
-LL | (|_| 2333).await;
- | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
- |
- = note: required by `std::future::poll_with_tls_context`
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(async_await)]
+
+async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+
+fn main() {
+ let _ = multiple_elided_lifetimes(&22, &44);
+}
--- /dev/null
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(async_await)]
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {}
+
+fn gimme(_: &u8) { }
+
+fn main() {
+ let _ = multiple_named_lifetimes(&22, &44, gimme);
+}
--- /dev/null
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(async_await)]
+#![allow(dead_code)]
+
+use std::ops::Add;
+
+async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
+ _: impl for<'a> Add<&'a u8>,
+ _: impl for<'b> Add<&'b u8>,
+ _: &'c u8,
+) {}
+
+fn main() {}
--- /dev/null
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(arbitrary_self_types, async_await, await_macro)]
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+
+fn main() {
+ let _ = multiple_named_lifetimes(&22, &44);
+}
--- /dev/null
+// edition:2018
+// run-pass
+
+#![feature(async_await)]
+
+async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32)
+ where 'b: 'a
+{
+ drop((a, c));
+ (b, b)
+}
+
+fn main() {
+ let _ = lotsa_lifetimes(&22, &44, &66);
+}
--- /dev/null
+// edition:2018
+// run-pass
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+#![feature(async_await, member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+ (a, b)
+}
+
+fn main() {
+ let _ = async_ret_impl_trait(&22, &44);
+}
--- /dev/null
+// edition:2018
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+#![feature(async_await)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+ //~^ ERROR ambiguous lifetime bound
+ (a, b)
+}
+
+fn main() {
+ let _ = async_ret_impl_trait(&22, &44);
+}
--- /dev/null
+error: ambiguous lifetime bound in `impl Trait`
+ --> $DIR/ret-impl-trait-no-fg.rs:11:64
+ |
+LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+ | ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+ |
+ = help: add #![feature(member_constraints)] to the crate attributes to enable
+
+error: aborting due to previous error
+
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/ret-impl-trait-one.rs:12:80
+ |
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+ | ________________________________--__--__________________________________________^
+ | | | |
+ | | | lifetime `'b` defined here
+ | | lifetime `'a` defined here
+LL | |
+LL | | (a, b)
+LL | | }
+ | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+#![feature(async_await, member_constraints)]
+
+trait Trait<'a> { }
+impl<T> Trait<'_> for T { }
+
+// Only `'a` permitted in return type, not `'b`.
+async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+ //~^ ERROR lifetime mismatch
+ (a, b)
+}
+
+// As above, but `'b: 'a`, so return type can be inferred to `(&'a u8,
+// &'a u8)`.
+async fn async_ret_impl_trait2<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a>
+where
+ 'b: 'a,
+{
+ (a, b)
+}
+
+fn main() {
+}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ret-impl-trait-one.rs:12:65
+ |
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+ | ------ ^^^^^^^^^^^^^^
+ | | |
+ | | ...but data from `b` is returned here
+ | this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+
+// Test that we get the expected borrow check errors when an async
+// function (which takes multiple lifetimes) only returns data from
+// one of them.
+
+#![feature(async_await)]
+
+async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 {
+ a
+}
+
+// Both are borrowed whilst the future is live.
+async fn future_live() {
+ let mut a = 22;
+ let mut b = 44;
+ let future = multiple_named_lifetimes(&a, &b);
+ a += 1; //~ ERROR cannot assign
+ b += 1; //~ ERROR cannot assign
+ let p = future.await;
+ drop(p);
+}
+
+// Just the return value is live after future is awaited.
+async fn just_return_live() {
+ let mut a = 22;
+ let mut b = 44;
+ let future = multiple_named_lifetimes(&a, &b);
+ let p = future.await;
+ a += 1; //~ ERROR cannot assign
+ b += 1;
+ drop(p);
+}
+
+// Once `p` is dead, both `a` and `b` are unborrowed.
+async fn after_both_dead() {
+ let mut a = 22;
+ let mut b = 44;
+ let future = multiple_named_lifetimes(&a, &b);
+ let p = future.await;
+ drop(p);
+ a += 1;
+ b += 1;
+}
+
+fn main() { }
--- /dev/null
+error[E0506]: cannot assign to `a` because it is borrowed
+ --> $DIR/ret-ref.rs:18:5
+ |
+LL | let future = multiple_named_lifetimes(&a, &b);
+ | -- borrow of `a` occurs here
+LL | a += 1;
+ | ^^^^^^ assignment to borrowed `a` occurs here
+LL | b += 1;
+LL | let p = future.await;
+ | ------ borrow later used here
+
+error[E0506]: cannot assign to `b` because it is borrowed
+ --> $DIR/ret-ref.rs:19:5
+ |
+LL | let future = multiple_named_lifetimes(&a, &b);
+ | -- borrow of `b` occurs here
+LL | a += 1;
+LL | b += 1;
+ | ^^^^^^ assignment to borrowed `b` occurs here
+LL | let p = future.await;
+ | ------ borrow later used here
+
+error[E0506]: cannot assign to `a` because it is borrowed
+ --> $DIR/ret-ref.rs:30:5
+ |
+LL | let future = multiple_named_lifetimes(&a, &b);
+ | -- borrow of `a` occurs here
+LL | let p = future.await;
+LL | a += 1;
+ | ^^^^^^ assignment to borrowed `a` occurs here
+LL | b += 1;
+LL | drop(p);
+ | - borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
--- /dev/null
+// edition:2018
+// run-pass
+
+// Test for async fn where the parameters have distinct lifetime
+// parameters that appear in all possible variances.
+
+#![feature(async_await)]
+
+#[allow(dead_code)]
+async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { }
+
+fn take_any(_: &u8) { }
+fn identify(x: &u8) -> &u8 { x }
+fn give_back() -> &'static u8 { &22 }
+
+fn main() {
+ let _ = lotsa_lifetimes(take_any, identify, give_back);
+}
// edition:2018
-#![feature(async_await, await_macro)]
+#![feature(async_await, async_closure)]
fn main() {
let _ = async |x: u8| {};
--- /dev/null
+// edition:2018
+
+struct S;
+
+impl S {
+ #[cfg(FALSE)]
+ unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found `async`
+}
+
+#[cfg(FALSE)]
+unsafe async fn f() {} //~ ERROR expected one of `extern`, `fn`, or `{`, found `async`
--- /dev/null
+error: expected one of `extern` or `fn`, found `async`
+ --> $DIR/no-unsafe-async.rs:7:12
+ |
+LL | unsafe async fn g() {}
+ | ^^^^^ expected one of `extern` or `fn` here
+
+error: expected one of `extern`, `fn`, or `{`, found `async`
+ --> $DIR/no-unsafe-async.rs:11:8
+ |
+LL | unsafe async fn f() {}
+ | ^^^^^ expected one of `extern`, `fn`, or `{` here
+
+error: aborting due to 2 previous errors
+
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden when using `async` and `await`.
-#![feature(await_macro, async_await, generators)]
+#![feature(async_await)]
async fn recursive_async_function() -> () { //~ ERROR
- await!(recursive_async_function());
+ recursive_async_function().await;
}
fn main() {}
--- /dev/null
+// edition:2018
+// run-rustfix
+
+#![feature(async_await, async_closure)]
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+ 22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_closure() {
+ async || {
+ let x = make_u32();
+ take_u32(x.await)
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION x.await
+ };
+}
+
+fn main() {}
--- /dev/null
+// edition:2018
+// run-rustfix
+
+#![feature(async_await, async_closure)]
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+ 22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_closure() {
+ async || {
+ let x = make_u32();
+ take_u32(x)
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION x.await
+ };
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await-closure.rs:16:18
+ |
+LL | take_u32(x)
+ | ^
+ | |
+ | expected u32, found opaque type
+ | help: consider using `.await` here: `x.await`
+ |
+ = note: expected type `u32`
+ found type `impl std::future::Future`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
//~| SUGGESTION x.await
}
-#[allow(unused)]
-async fn suggest_await_in_async_closure() {
- async || {
- let x = make_u32();
- take_u32(x.await)
- //~^ ERROR mismatched types [E0308]
- //~| HELP consider using `.await` here
- //~| SUGGESTION x.await
- };
-}
-
fn main() {}
//~| SUGGESTION x.await
}
-#[allow(unused)]
-async fn suggest_await_in_async_closure() {
- async || {
- let x = make_u32();
- take_u32(x)
- //~^ ERROR mismatched types [E0308]
- //~| HELP consider using `.await` here
- //~| SUGGESTION x.await
- };
-}
-
fn main() {}
= note: expected type `u32`
found type `impl std::future::Future`
-error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:25:18
- |
-LL | take_u32(x)
- | ^
- | |
- | expected u32, found opaque type
- | help: consider using `.await` here: `x.await`
- |
- = note: expected type `u32`
- found type `impl std::future::Future`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![feature(rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![feature(rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![feature(rustc_attrs)]
struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
-impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
//~^ ERROR trailing attribute after generic parameter
}
-fn main() {
-
-}
+fn main() {}
error: trailing attribute after generic parameter
- --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
+ --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:29
|
-LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
- | ^^^^^^^ attributes must go before parameters
+LL | impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+ | ^^^^^^^ attributes must go before parameters
error: aborting due to previous error
struct RefAny<'a, T>(&'a T);
-impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
+impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {}
//~^ ERROR trailing attribute after generic parameter
fn main() {}
error: trailing attribute after generic parameter
- --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
+ --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:43
|
-LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
- | ^^^^^^^ attributes must go before parameters
+LL | impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {}
+ | ^^^^^^^ attributes must go before parameters
error: aborting due to previous error
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pp-exact - Make sure we actually print the attributes
#![feature(rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
// for completeness since .rs files linked from .rc files support this
// notation to specify their module's attributes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pp-exact - Make sure we print all the attributes
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pp-exact - Make sure we actually print the attributes
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Bastion of the Turbofish
// ------------------------
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
// (for ensuring that NLL respects user-provided lifetime annotations)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(exclusive_range_pattern)]
#![warn(unreachable_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn with_closure<F, A>(_: F)
where F: FnOnce(A, &u32)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn with_closure<F, A>(_: F)
where F: FnOnce(A, &u32)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn test<F: Fn(&u64, &u64)>(f: F) {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(const_err)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(never_type)]
#![allow(unreachable_code)]
// universe transition (#56105) may eventually become an error.
// revisions: old re
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![cfg_attr(re, feature(re_rebalance_coherence))]
// `MyType: !MyTrait` along with other "fundamental" wrappers.
// aux-build:coherence_copy_like_lib.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// skip-codgen
// revisions: old re
// Test that cfg_attr doesn't emit any attributes when the
// configuration variable is false. This mirrors `cfg-attr-multi-true.rs`
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_must_use)]
// This is done by emitting two attributes that cause new warnings, and then
// triggering those warnings.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_must_use)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn foo<const SIZE: usize>() {
let arr: [u8; SIZE] = unsafe {
+ #[allow(deprecated)]
let mut array: [u8; SIZE] = mem::uninitialized();
array
};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
enum Foo {
Bar = { let x = 1; 3 }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Foo {
fn foo(self) -> u32;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
const MIN: i8 = -5;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
enum Foo {
A = 5,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(const_fn, rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::time::Duration;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(extern_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Nullable {
const NULL: Self;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(packed)]
pub struct Num(u64);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct S(pub &'static u32, pub u32);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct Stats;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// https://github.com/rust-lang/rust/issues/51300
#[derive(PartialEq, Eq, Clone, Copy)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
macro_rules! m {
() => {{
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub const STATIC_TRAIT: &dyn Test = &();
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Test that we can handle newtypes wrapping extern types
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// if `X` were used instead of `x`, `X - 10` would result in a lint.
// This file should never produce a lint, no matter how the const
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub fn main() {
let y: &'static mut [u8; 0] = &mut [];
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(const_err)]
#![crate_type = "lib"]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(const_err)]
pub const Z: u32 = 0 - 1;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
const PARSE_BOOL: Option<&'static str> = None;
static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
#![allow(const_err)] // make sure we cannot allow away the errors tested here
+
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+struct Wrap<T>(T);
+
#[repr(usize)]
#[derive(Copy, Clone)]
enum Enum {
}
union TransmuteEnum {
in1: &'static u8,
+ in2: usize,
out1: Enum,
+ out2: Wrap<Enum>,
}
-// A pointer is guaranteed non-null
-const BAD_ENUM: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
+const GOOD_ENUM: Enum = unsafe { TransmuteEnum { in2: 0 }.out1 };
+
+const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
+//~^ ERROR is undefined behavior
+
+const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
+//~^ ERROR is undefined behavior
+
+const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
//~^ ERROR is undefined behavior
// (Potentially) invalid enum discriminant
enum Enum2 {
A = 2,
}
-#[repr(transparent)]
-#[derive(Copy, Clone)]
-struct Wrap<T>(T);
+
union TransmuteEnum2 {
in1: usize,
in2: &'static u8,
}
const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
//~^ ERROR is undefined behavior
-const BAD_ENUM3: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
+const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
//~^ ERROR is undefined behavior
-const BAD_ENUM4: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
+const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
//~^ ERROR is undefined behavior
// Undef enum discriminant.
-const BAD_ENUM_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
+const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
//~^ ERROR is undefined behavior
// Pointer value in an enum with a niche that is not just 0.
-const BAD_ENUM_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
+const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
//~^ ERROR is undefined behavior
// Invalid enum field content (mostly to test printing of paths for enum tuple
b: char,
}
// Need to create something which does not clash with enum layout optimizations.
-const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
//~^ ERROR is undefined behavior
fn main() {
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:14:1
+ --> $DIR/ub-enum.rs:22:1
|
-LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:34:1
+ --> $DIR/ub-enum.rs:25:1
+ |
+LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-enum.rs:28:1
+ |
+LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { TransmuteEnum { in1: &1 }.out2 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:36:1
+ --> $DIR/ub-enum.rs:48:1
|
-LL | const BAD_ENUM3: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:38:1
+ --> $DIR/ub-enum.rs:50:1
|
-LL | const BAD_ENUM4: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be in the range 2..=2
+LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out2 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:42:1
+ --> $DIR/ub-enum.rs:54:1
|
-LL | const BAD_ENUM_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant
+LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:46:1
+ --> $DIR/ub-enum.rs:58:1
|
-LL | const BAD_ENUM_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
+LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { TransmuteEnum2 { in2: &0 }.out3 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:56:1
+ --> $DIR/ub-enum.rs:68:1
|
-LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
+LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0080`.
use std::ptr::NonNull;
use std::num::{NonZeroU8, NonZeroUsize};
+const NON_NULL: NonNull<u8> = unsafe { mem::transmute(1usize) };
+const NON_NULL_PTR: NonNull<u8> = unsafe { mem::transmute(&1) };
+
const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
//~^ ERROR it is undefined behavior to use this value
+const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
+//~^ ERROR it is undefined behavior to use this value
+ let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
+ let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic
+ mem::transmute(out_of_bounds_ptr)
+} };
+
const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
//~^ ERROR it is undefined behavior to use this value
const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:8:1
+ --> $DIR/ub-nonnull.rs:11:1
|
LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:11:1
+ --> $DIR/ub-nonnull.rs:14:1
+ |
+LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
+LL | |
+LL | | let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
+LL | | let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic
+LL | | mem::transmute(out_of_bounds_ptr)
+LL | | } };
+ | |____^ type validation failed: encountered a potentially NULL pointer, but expected something that cannot possibly fail to be greater or equal to 1
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-nonnull.rs:21:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:13:1
+ --> $DIR/ub-nonnull.rs:23:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:20:1
+ --> $DIR/ub-nonnull.rs:30:1
|
LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:28:1
+ --> $DIR/ub-nonnull.rs:38:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:34:1
+ --> $DIR/ub-nonnull.rs:44:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0080`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Some constants that *are* valid
#![feature(const_transmute)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];
// Encountered while testing #44614.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub fn main() {
// Constant of generic type (int)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
const fn i((a, b): (u32, u32)) -> u32 {
a + b
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::num::NonZeroU8;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[derive(PartialEq, Eq)]
enum Cake {
// https://github.com/rust-lang/rust/issues/55454
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct This<T>(T);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:const_fn_lib.rs
extern crate const_fn_lib;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct S(i32);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct AA {
pub data: [u8; 10],
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(const_fn)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct A;
impl Drop for A {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(const_raw_ptr_deref)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// note this was only reproducible with lib crates
// compile-flags: --crate-type=lib
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
assert_eq!(&mut [0; 1][..], &mut []);
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_allow_const_fn_ptr]
-//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
+//~^ ERROR internal implementation detail
const fn compiles(_: fn()) {}
fn main() {}
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
- --> $DIR/allow_const_fn_ptr_feature_gate.rs:7:3
+error[E0658]: internal implementation detail
+ --> $DIR/allow_const_fn_ptr_feature_gate.rs:7:1
|
LL | #[rustc_allow_const_fn_ptr]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::cell::UnsafeCell;
use std::sync::atomic::AtomicU32;
-//compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:promotable_const_fn_lib.rs
extern crate promotable_const_fn_lib;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let x: &'static u8 = &u8::max_value();
// https://github.com/rust-lang/rust/issues/55454
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[derive(PartialEq)]
struct This<T>(T);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let _ = &[("", ""); 3];
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Wrap<T>(T);
unsafe impl<T> Send for Wrap<T> {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
union Uninit {
_never_use: *const u8,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(dead_code)]
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[allow(deprecated, unused_imports)]
use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[allow(deprecated, unused_imports)]
use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(deprecated)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![forbid(deprecated)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Wunused
// ensure there are no special warnings about uninhabited types
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Under the 2015 edition with the keyword_idents lint, `dyn` is
// not entirely acceptable as an identifier.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Under the 2015 edition with the keyword_idents lint, `dyn` is
// not entirely acceptable as an identifier.
// Under the 2015 edition without the keyword_idents lint, `dyn` is
// entirely acceptable as an identifier.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// rust-lang/rust#56327: Some occurrences of `dyn` within a macro are
// not instances of identifiers, and thus should *not* be caught by the
// aux-build:edition-extern-crate-allowed.rs
// edition:2015
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_idioms)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rust_2018_preview)]
// edition:2018
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rust_2018_preview)]
//~^ WARN the feature `rust_2018_preview` is included in the Rust 2018 edition
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// compile-flags:--extern edition_imports_2015
// aux-build:edition-imports-2015.rs
// edition:2015
// aux-build:edition-kw-macro-2015.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(keyword_idents)]
// edition:2018
// aux-build:edition-kw-macro-2015.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(keyword_idents)]
// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-enum Enum<T> { TSVariant(T), SVariant { v: T } }
-type Alias<T> = Enum<T>;
-type AliasFixed = Enum<()>;
-
-impl<T> Enum<T> {
- fn ts_variant() {
- Self::TSVariant(());
- //~^ ERROR mismatched types [E0308]
- Self::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
- Self::<()>::TSVariant(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR mismatched types [E0308]
- Self::<()>::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR type arguments are not allowed for this type [E0109]
- }
-
- fn s_variant() {
- Self::SVariant { v: () };
- //~^ ERROR mismatched types [E0308]
- Self::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR mismatched types [E0308]
- Self::<()>::SVariant { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR mismatched types [E0308]
- Self::<()>::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR type arguments are not allowed for this type [E0109]
- //~^^^ ERROR mismatched types [E0308]
- }
-}
-
-fn main() {
- // Tuple struct variant
-
- Enum::<()>::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
-
- Alias::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
- Alias::<()>::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
-
- AliasFixed::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
- AliasFixed::<()>::TSVariant(());
- //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
- AliasFixed::<()>::TSVariant::<()>(());
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-
- // Struct variant
-
- Enum::<()>::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
-
- Alias::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
- Alias::<()>::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
-
- AliasFixed::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
- AliasFixed::<()>::SVariant { v: () };
- //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
- AliasFixed::<()>::SVariant::<()> { v: () };
- //~^ ERROR type arguments are not allowed for this type [E0109]
- //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/enum-variant-generic-args.rs:9:25
- |
-LL | Self::TSVariant(());
- | ^^ expected type parameter, found ()
- |
- = note: expected type `T`
- found type `()`
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:11:27
- |
-LL | Self::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:13:16
- |
-LL | Self::<()>::TSVariant(());
- | ^^ type argument not allowed
-
-error[E0308]: mismatched types
- --> $DIR/enum-variant-generic-args.rs:13:31
- |
-LL | Self::<()>::TSVariant(());
- | ^^ expected type parameter, found ()
- |
- = note: expected type `T`
- found type `()`
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:16:16
- |
-LL | Self::<()>::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:16:33
- |
-LL | Self::<()>::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0308]: mismatched types
- --> $DIR/enum-variant-generic-args.rs:22:29
- |
-LL | Self::SVariant { v: () };
- | ^^ expected type parameter, found ()
- |
- = note: expected type `T`
- found type `()`
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:24:26
- |
-LL | Self::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0308]: mismatched types
- --> $DIR/enum-variant-generic-args.rs:24:35
- |
-LL | Self::SVariant::<()> { v: () };
- | ^^ expected type parameter, found ()
- |
- = note: expected type `T`
- found type `()`
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:27:16
- |
-LL | Self::<()>::SVariant { v: () };
- | ^^ type argument not allowed
-
-error[E0308]: mismatched types
- --> $DIR/enum-variant-generic-args.rs:27:35
- |
-LL | Self::<()>::SVariant { v: () };
- | ^^ expected type parameter, found ()
- |
- = note: expected type `T`
- found type `()`
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:30:16
- |
-LL | Self::<()>::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:30:32
- |
-LL | Self::<()>::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0308]: mismatched types
- --> $DIR/enum-variant-generic-args.rs:30:41
- |
-LL | Self::<()>::SVariant::<()> { v: () };
- | ^^ expected type parameter, found ()
- |
- = note: expected type `T`
- found type `()`
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:40:29
- |
-LL | Enum::<()>::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:43:24
- |
-LL | Alias::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:45:30
- |
-LL | Alias::<()>::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:48:29
- |
-LL | AliasFixed::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0107]: wrong number of type arguments: expected 0, found 1
- --> $DIR/enum-variant-generic-args.rs:50:18
- |
-LL | AliasFixed::<()>::TSVariant(());
- | ^^ unexpected type argument
-
-error[E0107]: wrong number of type arguments: expected 0, found 1
- --> $DIR/enum-variant-generic-args.rs:52:18
- |
-LL | AliasFixed::<()>::TSVariant::<()>(());
- | ^^ unexpected type argument
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:52:35
- |
-LL | AliasFixed::<()>::TSVariant::<()>(());
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:58:28
- |
-LL | Enum::<()>::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:61:23
- |
-LL | Alias::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:63:29
- |
-LL | Alias::<()>::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:66:28
- |
-LL | AliasFixed::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error[E0107]: wrong number of type arguments: expected 0, found 1
- --> $DIR/enum-variant-generic-args.rs:68:18
- |
-LL | AliasFixed::<()>::SVariant { v: () };
- | ^^ unexpected type argument
-
-error[E0107]: wrong number of type arguments: expected 0, found 1
- --> $DIR/enum-variant-generic-args.rs:70:18
- |
-LL | AliasFixed::<()>::SVariant::<()> { v: () };
- | ^^ unexpected type argument
-
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/enum-variant-generic-args.rs:70:34
- |
-LL | AliasFixed::<()>::SVariant::<()> { v: () };
- | ^^ type argument not allowed
-
-error: aborting due to 28 previous errors
-
-Some errors have detailed explanations: E0107, E0109, E0308.
-For more information about an error, try `rustc --explain E0107`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This is a stub feature that doesn't control anything, so to make tidy happy,
// gate-test-test_2018_feature
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
// aux-build:cross_crate_ice.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
extern crate cross_crate_ice;
// aux-build:cross_crate_ice2.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
extern crate cross_crate_ice2;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(existential_type)]
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Bar {}
struct Dummy;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(existential_type)]
use std::fmt::Debug;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(existential_type)]
use std::fmt::Debug;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(existential_type)]
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
mod my_mod {
use std::fmt::Debug;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[deny(warnings)]
// compile-flags: --explain E0591
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:--extern extern_prelude --extern Vec
// aux-build:extern-prelude.rs
// aux-build:extern-prelude-vec.rs
// `#![macro_escape]` is incompatible with crate-level `#![macro_use]`
// already present in issue-43106-gating-of-builtin-attrs.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![macro_escape]
//~^ WARN macro_escape is a deprecated synonym for macro_use
fn main() {
let _ = async {}; //~ ERROR async blocks are unstable
- let _ = async || {}; //~ ERROR async closures are unstable
}
= note: for more information, see https://github.com/rust-lang/rust/issues/50547
= help: add #![feature(async_await)] to the crate attributes to enable
-error[E0658]: async closures are unstable
- --> $DIR/feature-gate-async-await.rs:18:13
- |
-LL | let _ = async || {};
- | ^^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/50547
- = help: add #![feature(async_await)] to the crate attributes to enable
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0658`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
--- /dev/null
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T {}
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
+ //~^ ERROR ambiguous lifetime bound
+ (x, y)
+}
+
+fn main() { }
--- /dev/null
+error: ambiguous lifetime bound in `impl Trait`
+ --> $DIR/feature-gate-member-constraints.rs:4:43
+ |
+LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
+ | ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+ |
+ = help: add #![feature(member_constraints)] to the crate attributes to enable
+
+error: aborting due to previous error
+
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
-#[rustc_foo]
-//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
+#![feature(decl_macro)]
+mod rustc { pub macro unknown() {} }
+mod unknown { pub macro rustc() {} }
+
+#[rustc::unknown]
+//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+//~| ERROR macro `rustc::unknown` may not be used in attributes
+fn f() {}
+
+#[unknown::rustc]
+//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+//~| ERROR macro `unknown::rustc` may not be used in attributes
+fn g() {}
+
+#[rustc_dummy]
+//~^ ERROR used by the test suite
+#[rustc_unknown]
+//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+//~| ERROR attribute `rustc_unknown` is currently unknown
fn main() {}
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
- --> $DIR/feature-gate-rustc-attrs.rs:3:3
+error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/feature-gate-rustc-attrs.rs:8:3
|
-LL | #[rustc_foo]
- | ^^^^^^^^^
+LL | #[rustc::unknown]
+ | ^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
-error: aborting due to previous error
+error: macro `rustc::unknown` may not be used in attributes
+ --> $DIR/feature-gate-rustc-attrs.rs:8:1
+ |
+LL | #[rustc::unknown]
+ | ^^^^^^^^^^^^^^^^^
+
+error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/feature-gate-rustc-attrs.rs:13:12
+ |
+LL | #[unknown::rustc]
+ | ^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: macro `unknown::rustc` may not be used in attributes
+ --> $DIR/feature-gate-rustc-attrs.rs:13:1
+ |
+LL | #[unknown::rustc]
+ | ^^^^^^^^^^^^^^^^^
+
+error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/feature-gate-rustc-attrs.rs:20:3
+ |
+LL | #[rustc_unknown]
+ | ^^^^^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error[E0658]: The attribute `rustc_unknown` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/feature-gate-rustc-attrs.rs:20:3
+ |
+LL | #[rustc_unknown]
+ | ^^^^^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error[E0658]: used by the test suite
+ --> $DIR/feature-gate-rustc-attrs.rs:18:1
+ |
+LL | #[rustc_dummy]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0658`.
LL | [1, 2, ..] => {}
| ^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62254
= help: add #![feature(slice_patterns)] to the crate attributes to enable
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
LL | [1, .., 5] => {}
| ^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62254
= help: add #![feature(slice_patterns)] to the crate attributes to enable
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
LL | [.., 4, 5] => {}
| ^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62254
= help: add #![feature(slice_patterns)] to the crate attributes to enable
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
LL | [ xs.., 4, 5 ] => {}
| ^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62254
= help: add #![feature(slice_patterns)] to the crate attributes to enable
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
LL | [ 1, xs.., 5 ] => {}
| ^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62254
= help: add #![feature(slice_patterns)] to the crate attributes to enable
error[E0658]: syntax for subslices in slice patterns is not yet stabilized
LL | [ 1, 2, xs.. ] => {}
| ^^
|
- = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+ = note: for more information, see https://github.com/rust-lang/rust/issues/62254
= help: add #![feature(slice_patterns)] to the crate attributes to enable
error: aborting due to 6 previous errors
+++ /dev/null
-enum Foo {
- Bar(i32),
- Baz { i: i32 },
-}
-
-type Alias = Foo;
-
-fn main() {
- let t = Alias::Bar(0);
- //~^ ERROR enum variants on type aliases are experimental
- let t = Alias::Baz { i: 0 };
- //~^ ERROR enum variants on type aliases are experimental
- match t {
- Alias::Bar(_i) => {}
- //~^ ERROR enum variants on type aliases are experimental
- Alias::Baz { i: _i } => {}
- //~^ ERROR enum variants on type aliases are experimental
- }
-}
+++ /dev/null
-error: enum variants on type aliases are experimental
- --> $DIR/feature-gate-type_alias_enum_variants.rs:9:13
- |
-LL | let t = Alias::Bar(0);
- | ^^^^^^^^^^
- |
- = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: enum variants on type aliases are experimental
- --> $DIR/feature-gate-type_alias_enum_variants.rs:11:13
- |
-LL | let t = Alias::Baz { i: 0 };
- | ^^^^^^^^^^
- |
- = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: enum variants on type aliases are experimental
- --> $DIR/feature-gate-type_alias_enum_variants.rs:14:9
- |
-LL | Alias::Bar(_i) => {}
- | ^^^^^^^^^^^^^^
- |
- = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: enum variants on type aliases are experimental
- --> $DIR/feature-gate-type_alias_enum_variants.rs:16:9
- |
-LL | Alias::Baz { i: _i } => {}
- | ^^^^^^^^^^
- |
- = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_must_use)]
// but which encountered the same ICE/error. See `issue-53548.rs`
// for details.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::cell::RefCell;
use std::rc::Rc;
// also analogous to what we would do for higher-ranked regions
// appearing within the trait in other positions).
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(generators)]
// 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.)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
-#![allow(dead_code)]
-
-struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
-struct StTy<#[rustc_ty_struct] I>(I);
-enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
-enum EnTy<#[rustc_ty_enum] J> { A(J), B }
-trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
-type TyLt<#[rustc_lt_type] 'd> = &'d u32;
-type TyTy<#[rustc_ty_type] L> = (L, );
-
-impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
-impl<#[rustc_ty_inherent] M> StTy<M> { }
-impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+
+struct StLt<#[rustc_dummy] 'a>(&'a u32);
+struct StTy<#[rustc_dummy] I>(I);
+enum EnLt<#[rustc_dummy] 'b> { A(&'b u32), B }
+enum EnTy<#[rustc_dummy] J> { A(J), B }
+trait TrLt<#[rustc_dummy] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+trait TrTy<#[rustc_dummy] K> { fn foo(&self, _: K); }
+type TyLt<#[rustc_dummy] 'd> = &'d u32;
+type TyTy<#[rustc_dummy] L> = (L, );
+
+impl<#[rustc_dummy] 'e> StLt<'e> { }
+impl<#[rustc_dummy] M> StTy<M> { }
+impl<#[rustc_dummy] 'f> TrLt<'f> for StLt<'f> {
fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
}
-impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
+impl<#[rustc_dummy] N> TrTy<N> for StTy<N> {
fn foo(&self, _: N) { }
}
-fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-fn f_ty<#[rustc_ty_fn] O>(_: O) { }
+fn f_lt<#[rustc_dummy] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+fn f_ty<#[rustc_dummy] O>(_: O) { }
impl<I> StTy<I> {
- fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
- fn m_ty<#[rustc_ty_meth] P>(_: P) { }
+ fn m_lt<#[rustc_dummy] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+ fn m_ty<#[rustc_dummy] P>(_: P) { }
}
fn hof_lt<Q>(_: Q)
- where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+ where Q: for <#[rustc_dummy] 'i> Fn(&'i [u32]) -> &'i u32
{}
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Test that compiling hello world succeeds with no output of any kind.
// Make sure `$crate` and `crate` work in for basic cases of nested macros.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:intercrate.rs
#![feature(decl_macro, crate_in_paths)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:local_inner_macros.rs
extern crate local_inner_macros;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:transparent-basic.rs
#![feature(decl_macro, rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn macros() {
macro_rules! foo{
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Foo<'a>(&'a u8);
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Bar {}
struct Dummy<U>(U);
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Bar {}
struct Dummy;
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Bar {}
struct Dummy;
// concrete type against the bound, which forces the return type to be
// `&'static i32` here.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn make_identity() -> impl Sized {
|x: &'static i32| x
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(warnings)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::iter::once;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Tests for nested self-reference which caused a stack overflow.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(warnings)]
// This used to ICE because it creates an `impl Trait` that captures a
// hidden empty region.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn server() -> impl FilterBase2 {
segment2(|| { loop { } }).map2(|| "")
// opaque type. As all regions are now required to outlive the bound in an
// opaque type we avoid the issue here.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct A<F>(F);
// Test that multiple liftimes are allowed in impl trait types.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait X<'x>: Sized {}
--- /dev/null
+// compile-flags:-Zborrowck=mir
+
+#![feature(member_constraints)]
+#![feature(existential_type)]
+
+#[derive(Clone)]
+struct CopyIfEq<T, U>(T, U);
+
+impl<T: Copy> Copy for CopyIfEq<T, T> {}
+
+existential type E<'a, 'b>: Sized;
+
+fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+ //~^ ERROR lifetime may not live long enough
+ let v = CopyIfEq::<*mut _, *mut _>(&mut {x}, &mut y);
+ let u = v;
+ let _: *mut &'a i32 = u.1;
+ unsafe { let _: &'b i32 = *u.0; }
+ u.0
+}
+
+fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/error-handling.rs:13:56
+ |
+LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+ | -- lifetime `'a` defined here ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
+ |
+LL | existential type E<'a, 'b>: Sized; + 'a
+ |
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+// run-pass
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Invert<'a> <: Invert<'b>` if `'b: 'a`, unlike most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Invert<'a>(fn(&'a u8));
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e>
+where
+ 'c: 'a,
+ 'c: 'b,
+ 'd: 'c,
+{
+ // Representing the where clauses as a graph, where `A: B` is an
+ // edge `B -> A`:
+ //
+ // ```
+ // 'a -> 'c -> 'd
+ // ^
+ // |
+ // 'b
+ // ```
+ //
+ // Meanwhile we return a value &'0 u8 where we have the constraints:
+ //
+ // ```
+ // '0: 'a
+ // '0: 'b
+ // '0 in ['d, 'e]
+ // ```
+ //
+ // Here, ignoring the "in" constraint, the minimal choice for `'0`
+ // is `'c`, but that is not in the "in set". Still, that reduces
+ // the range of options in the "in set" to just `'d` (`'e: 'c`
+ // does not hold).
+ let p = if condition() { a } else { b };
+ p
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
--- /dev/null
+warning[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/inverse-bounds.rs:16:70
+ |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e>
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: hidden type `Invert<'_>` captures lifetime '_#8r
+ = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+ = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+ = note: for more information, try `rustc --explain E0729`
+
+warning: the feature `pin` has been stable since 1.33.0 and no longer requires an attribute to enable
+ --> $DIR/inverse-bounds.rs:4:60
+ |
+LL | #![feature(arbitrary_self_types, async_await, await_macro, pin)]
+ | ^^^
+ |
+ = note: #[warn(stable_features)] on by default
+
--- /dev/null
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+// Test case where we have elision in the impl trait and we have to
+// pick the right region.
+
+// Ultimately `Trait<'x, 'static>`.
+fn upper_bounds1(a: &u8) -> impl Trait<'_, 'static> {
+ (a, a)
+}
+
+// Ultimately `Trait<'x, 'x>`, so not really multiple bounds.
+fn upper_bounds2(a: &u8) -> impl Trait<'_, '_> {
+ (a, a)
+}
+
+// Kind of a weird annoying case.
+fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> {
+ (a, a)
+}
+
+fn main() { }
--- /dev/null
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+#![feature(existential_type)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+// Here we wind up selecting `'a` and `'b` in the hidden type because
+// those are the types that appear in the original values.
+
+existential type Foo<'a, 'b>: Trait<'a, 'b>;
+
+fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> {
+ // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['a, 'b]
+ // '1 in ['a, 'b]
+ // ```
+ //
+ // We use the fact that `'a: 0'` must hold (combined with the in
+ // constraint) to determine that `'0 = 'a` must be the answer.
+ (a, b)
+}
+
+fn main() { }
--- /dev/null
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+// Here we wind up selecting `'a` and `'b` in the hidden type because
+// those are the types that appear in the original values.
+
+fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+ // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['a, 'b]
+ // '1 in ['a, 'b]
+ // ```
+ //
+ // We use the fact that `'a: 0'` must hold (combined with the in
+ // constraint) to determine that `'0 = 'a` must be the answer.
+ (a, b)
+}
+
+fn main() { }
--- /dev/null
+// edition:2018
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we wind up selecting `'e` in the hidden type because
+// we need something outlived by both `'a` and `'b` and only `'e` applies.
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+where
+ 'a: 'e,
+ 'b: 'e,
+ 'a: 'd,
+{
+ // We return a value:
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['d, 'e]
+ // ```
+ //
+ // but we don't have it.
+ //
+ // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
+ let p = if condition() { a } else { b };
+ p
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
--- /dev/null
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/ordinary-bounds-unrelated.rs:18:74
+ |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
--- /dev/null
+// edition:2018
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we get an error because none of our choices (either `'d` nor `'e`) are outlived
+// by both `'a` and `'b`.
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+where
+ 'a: 'e,
+ 'b: 'd,
+{
+ // Hidden type `Ordinary<'0>` with constraints:
+ //
+ // ```
+ // 'a: '0
+ // 'b: '0
+ // 'a in ['d, 'e]
+ // ```
+ if condition() { a } else { b }
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
--- /dev/null
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/ordinary-bounds-unrelated.rs:18:74
+ |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 23:1
+ --> $DIR/ordinary-bounds-unrelated.rs:23:1
+ |
+LL | / {
+LL | | // Hidden type `Ordinary<'0>` with constraints:
+LL | | //
+LL | | // ```
+... |
+LL | | if condition() { a } else { b }
+LL | | }
+ | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
--- /dev/null
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/ordinary-bounds-unsuited.rs:20:62
+ |
+LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
--- /dev/null
+// edition:2018
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we need something outlived by `'a` *and* outlived by `'b`, but
+// we can only name `'a` and `'b` (and neither suits). So we get an
+// error. Somewhat unfortunate, though, since the caller would have to
+// consider the loans for both `'a` and `'b` alive.
+
+fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+ //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+{
+ // We return a value:
+ //
+ // ```
+ // 'a: '0
+ // 'b: '1
+ // '0 in ['a, 'b]
+ // ```
+ //
+ // but we don't have it.
+ //
+ // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
+ if condition() { a } else { b }
+}
+
+fn condition() -> bool {
+ true
+}
+
+fn main() {}
--- /dev/null
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/ordinary-bounds-unsuited.rs:20:62
+ |
+LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 22:1
+ --> $DIR/ordinary-bounds-unsuited.rs:22:1
+ |
+LL | / {
+LL | | // We return a value:
+LL | | //
+LL | | // ```
+... |
+LL | | if condition() { a } else { b }
+LL | | }
+ | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
+// run-pass
+
+#![feature(member_constraints)]
+
use std::fmt::Debug;
trait MultiRegionTrait<'a, 'b> {}
impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}
fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
-//~^ ERROR ambiguous lifetime bound
+ // Here we have a constraint that:
+ //
+ // (x, y) has type (&'0 u32, &'1 u32)
+ //
+ // where
+ //
+ // 'a: '0
+ //
+ // then we require that `('0 u32, &'1 u32): MultiRegionTrait<'a,
+ // 'b>`, which winds up imposing a requirement that `'0 = 'a` and
+ // `'1 = 'b`.
(x, y)
}
+++ /dev/null
-error: ambiguous lifetime bound in `impl Trait`
- --> $DIR/needs_least_region_or_bound.rs:6:55
- |
-LL | fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
-
-error: aborting due to previous error
-
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Test that `extern crate self;` is accepted
// syntactically as an item for use in a macro.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
extern crate self as foo;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
macro_rules! define_iso { () => {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:--cfg my_feature
#![no_std]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:two_macros.rs
extern crate two_macros;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:two_macros.rs
extern crate two_macros as core;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// aux-build:gensymed.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
mod m {
pub struct S(u8);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:issue-55811.rs
extern crate issue_55811;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
use ::std;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
macro_rules! define_exported { () => {
#[macro_export]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[macro_export(local_inner_macros)]
macro_rules! dollar_crate_exported {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// tests that the following code compiles, but produces a future-compatibility warning
+#![allow(deprecated)]
#![feature(core_intrinsics)]
use std::intrinsics::{init};
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
- --> $DIR/init-unsafe.rs:7:17
+ --> $DIR/init-unsafe.rs:8:17
|
LL | let stuff = init::<isize>();
| ^^^^^^^^^^^^^^^ call to unsafe function
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#[derive(Debug)]
enum Foo<'s> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
pub struct Foo;
pub fn main() {
foo!();
- assert!({one! two()});
- //~^ ERROR macros that expand to items
- //~| ERROR cannot find macro `one!` in this scope
- //~| ERROR mismatched types
+ assert!({one! two()}); //~ ERROR expected open delimiter
// regardless of whether nested macro_rules works, the following should at
// least throw a conventional error.
- assert!({one! two});
- //~^ ERROR expected `(` or `{`, found `}`
+ assert!({one! two}); //~ ERROR expected open delimiter
}
-error: macros that expand to items must be delimited with braces or followed by a semicolon
- --> $DIR/issue-10536.rs:14:22
+error: expected open delimiter
+ --> $DIR/issue-10536.rs:14:19
|
LL | assert!({one! two()});
- | ^^
-help: change the delimiters to curly braces
- |
-LL | assert!({one! two {}});
- | ^^
-help: add a semicolon
- |
-LL | assert!({one! two();});
- | ^
+ | ^^^ expected open delimiter
-error: expected `(` or `{`, found `}`
- --> $DIR/issue-10536.rs:21:22
+error: expected open delimiter
+ --> $DIR/issue-10536.rs:18:19
|
LL | assert!({one! two});
- | ^ expected `(` or `{`
-
-error: cannot find macro `one!` in this scope
- --> $DIR/issue-10536.rs:14:14
- |
-LL | assert!({one! two()});
- | ^^^
-
-error[E0308]: mismatched types
- --> $DIR/issue-10536.rs:14:13
- |
-LL | assert!({one! two()});
- | ^^^^^^^^^^^^ expected bool, found ()
- |
- = note: expected type `bool`
- found type `()`
+ | ^^^ expected open delimiter
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0308`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![deny(missing_docs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Common { fn dummy(&self) { } }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
//! Ensure the private trait Bar isn't complained about.
#![deny(missing_docs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// #11612
// We weren't updating the auto adjustments with all the resolved
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_attributes)]
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Foo {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
use std::slice;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// defining static with struct that contains enum
// with &'static str variant used to cause ICE
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
pub struct Foo<'a, 'b: 'a> { foo: &'a &'b isize }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Foo {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![allow(unused_imports, dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Foo: Sized {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_imports)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#[deny(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Reader {}
enum Wrapper<'a> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
pub type BigRat<T = isize> = T;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_macros)]
#![allow(dead_code)]
#![feature(asm)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![feature(fn_traits, unboxed_closures)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct A<'a> {
a: &'a i32,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait MatrixRow { fn dummy(&self) { }}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Parser<'a, I, O> {
parse: Box<dyn FnMut(I) -> Result<O, String> + 'a>
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
// ignore-cloudabi no std::fs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(box_syntax)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_must_use)]
#[allow(dead_code)]
fn check(a: &str) {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code, warnings)]
static mut x: isize = 3;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct A;
impl Drop for A {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for #17746
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Test that we can parse where clauses on various forms of tuple
// structs.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_imports)]
// These crossed imports should resolve fine, and not block on
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Indexable<T>: std::ops::Index<usize, Output = T> {
fn index2(&self, i: usize) -> &T {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
pub trait Promisable: Send + Sync {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Test that methods in trait impls should override default methods.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#[derive(Eq, PartialEq, PartialOrd, Ord)]
enum Test<'a> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Tup {
type T0;
type T1;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
pub trait Foo : Send { }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Hasher {
type State;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// regression test for #19097
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Handler {
fn handle(&self, _: &mut String);
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_imports)]
#![deny(unused_qualifications)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Trait<Input> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_variables)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait T {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
use std::any::TypeId;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Base {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_variables)]
// Test that `<Type as Trait>::Output` and `Self::Output` are accepted as type annotations in let
// bindings
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(fn_traits, unboxed_closures)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Check that associated types are `Sized`
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(stable_features)]
// ignore-cloudabi no processes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
struct Foo;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_must_use)]
use std::thread;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// test that autoderef of a type like this does not
// cause compiler to loop. Note that no instances
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(stable_features)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-cloudabi no std::fs
// Regression test for #20797.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Subscriber {
type Input;
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Trait where Self::Out: std::fmt::Display {
type Out;
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
trait Trait<'a> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for issue #21245. Check that we are able to infer
// the types in these examples correctly. It used to be that
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#![no_implicit_prelude]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
// not wind up propagating to `T`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(stable_features)]
#![feature(cfg_target_feature)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for #21726: an issue arose around the rules for
// subtyping of projection types that resulted in an unconstrained
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait LineFormatter<'a> {
type Iter: Iterator<Item=&'a str> + 'a;
fn iter(&'a self, line: &'a str) -> Self::Iter;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(type_alias_bounds)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait A<T: A<T>> {}
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(type_alias_bounds)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test is reduced from libsyntax. It is just checking that we
// can successfully deal with a "deep" structure, which the drop-check
// was hitting a recursion limit on at one point.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_variables)]
use std::collections::HashMap;
use std::collections::hash_map::Entry::Vacant;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Test {}
macro_rules! test {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[allow(dead_code)]
static X: &'static str = &*"";
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(non_camel_case_types)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait Inner {
type T;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
use std::marker::PhantomData;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compiler-flags: -g
pub struct Dst {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(core_intrinsics)]
#![allow(warnings)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[derive(PartialEq)]
struct Slice { slice: [u8] }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for #24085. Errors were occurring in region
// inference due to the requirement that `'a:b'`, which was getting
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#[derive(Copy,Clone)]
struct Functions {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This resulted in an ICE. Test for future-proofing
// Issue #24227
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait DictLike<'a> {
type ItemsIterator: Iterator<Item=u8>;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Foo;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:--cfg set1
#![cfg_attr(set1, feature(rustc_attrs))]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#[derive(Debug)]
struct Row<T>([T]);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
enum Sexpression {
Num(()),
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Tests that impls are allowed to have looser, more permissive bounds
// than the traits require.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
use std::ops::{Deref, DerefMut};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(unused_attributes)]
#[repr(C)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
pub struct Foo {
x: isize,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::cell::RefCell;
use std::rc::Rc;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Trait<'a> {
type T;
type U;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_snake_case)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Regression test for issue #27583. Unclear how useful this will be
// going forward, since the issue in question was EXTREMELY sensitive
// to compiler internals (like the precise numbering of nodes), but
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_assignments)]
#![allow(unused_variables)]
// Test that a field can have the same name in different variants
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Minimized version of issue-2804.rs. Both check that callee IDs don't
// clobber the previous node ID in a macro expr
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
use std::rc::Rc;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct Array<T> {
f00: [T; 00],
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// #28600 ICE: pub extern fn with parameter type &str inside struct impl
struct Test;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Regression test for #28871. The problem is that rustc encountered
// two ways to project, one from a where clause and one from the where
// clauses on the trait definition. (In fact, in this case, the where
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub type Session = i32;
pub struct StreamParser<'a, T> {
_tokens: T,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct Xyz<'a, V> {
pub v: (V, &'a u32),
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#[derive(Debug)]
struct Message<'a, P: 'a = &'a [u8]> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// This test ensures that each pointer type `P<X>` is covariant in `X`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_must_use)]
#![allow(dead_code)]
#![allow(unused_mut)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct Chan;
pub struct ChanSelect<'c, T> {
chans: Vec<(&'c Chan, T)>,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct S([u8; { struct Z; 0 }]);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(optin_builtin_traits)]
auto trait NotSame {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[derive(Debug)]
pub struct Config {
pub name: String,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(unused_results)]
#![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for #29740. Inefficient MIR matching algorithms
// generated way too much code for this sort of case, leading to OOM.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let mut i = [1, 2, 3];
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
pub struct Struct<K: 'static> {
pub field: K,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_snake_case)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait Make {
type Out;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait Resources {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(order_dependent_trait_objects)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// only-x86_64
#![allow(dead_code, non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
const A: [u32; 1] = [0];
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Issue 33903:
// Built-in indexing should be used even when the index is not
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct A {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
// rustc --test ignores2.rs && ./ignores2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// #34751 ICE: 'rustc' panicked at 'assertion failed: !substs.has_regions_escaping_depth(0)'
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(stable_features)]
#![feature(associated_consts)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(specialization)]
fn main() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for #35546. Check that we are able to codegen
// this. Before we had problems because of the drop glue signature
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait Canvas {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait DeclarationParser {
type Declaration;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_must_use)]
#![allow(dead_code)]
#![allow(unused_mut)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Tests for an LLVM abort when storing a lifetime-parametric fn into
// context that is expecting one that is not lifetime-parametric
// (i.e., has no `for <'_>`).
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(warnings)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![feature(slice_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Regression test for #37655. The problem was a false edge created by
// coercion that wound up requiring that `'a` (in `split()`) outlive
// `'b`, which shouldn't be necessary.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait Foo {
fn foo(&self);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
type A = for<> fn();
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#[repr(u64)]
enum A {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
// aux-build:issue-38875-b.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
extern crate issue_38875_b;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
fn f<T: ?for<'a> Sized>() {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
macro_rules! expr { () => { () } }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
trait A {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unreachable_code)]
// Regression test for issue #39984.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
macro_rules! m { () => { 0 } }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_mut)]
/*
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
fn f() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
fn f() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
macro_rules! m {
($i:meta) => {
#[derive($i)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Foo;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Function<T, F> { t: T, f: F }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(dead_code)]
#[used]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for #41936. The coerce-unsized trait check in
// coherence was using subtyping, which triggered variance
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Foo<T>(T);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(stable_features)]
#![feature(associated_consts)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
macro_rules! column {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait Trait {
type Output;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
trait VecN {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub trait Foo<'a> {
type Bar;
fn foo(&'a self) -> Self::Bar;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// only-x86_64
// no-prefer-dynamic
// compile-flags: -Ctarget-feature=+avx -Clto
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait T {
type X;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Foo(bool);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
//! dox
#![deny(missing_docs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
macro_rules! a {
() => { "a" }
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
use std::ops::Add;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(non_camel_case_types)]
#[allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
mod my_mod {
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Name<'a> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[repr(C,u8)]
enum Foo {
// See https://github.com/rust-lang/rust/issues/47309
// compile-flags:-Clink-dead-code
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type="rlib"]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_imports)]
use {{}, {}};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct AtomicRefMut<'a> {
value: &'a mut i32,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct WithDrop;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct MyStruct<'a> {
field: &'a mut (),
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Tests that automatic coercions from &mut T to *mut T
// allow borrows of T to expire immediately - essentially, that
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(non_upper_case_globals)]
static mut x: &'static u32 = &0;
// This note is annotated because the purpose of the test
// is to ensure that certain other notes are not generated.
#![deny(unused_unsafe)] //~ NOTE
+#![allow(deprecated)]
// (test that no note is generated on this unsafe fn)
pub unsafe fn a() {
error: unnecessary `unsafe` block
- --> $DIR/issue-48131.rs:8:9
+ --> $DIR/issue-48131.rs:9:9
|
LL | unsafe { /* unnecessary */ }
| ^^^^^^ unnecessary `unsafe` block
| ^^^^^^^^^^^^^
error: unnecessary `unsafe` block
- --> $DIR/issue-48131.rs:19:13
+ --> $DIR/issue-48131.rs:20:13
|
LL | unsafe { /* unnecessary */ }
| ^^^^^^ unnecessary `unsafe` block
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Regression test for #48551. Covers a case where duplicate candidates
// arose during associated type projection.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn iter<'a>(data: &'a [usize]) -> impl Iterator<Item = usize> + 'a {
data.iter()
.map(
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-emscripten no i128 support
fn fibs(n: u32) -> impl Iterator<Item=u128> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(stmt_expr_attributes)]
#![warn(unused_attributes)] //~ NOTE lint level defined here
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(decl_macro)]
// second time. Uncool.
// compile-flags:-Zmir-opt-level=3
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
assert!({false});
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::marker::PhantomData;
struct Meta<A> {
// Confirm that we don't accidentally divide or mod by zero in llvm_type
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
mod a {
pub trait A {}
// compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
#![feature(no_core)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
const PATH_DOT: &[u8] = &[b'.'];
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "lib"]
#![feature(linkage)]
// implied bounds was causing outlives relations that were not
// properly handled.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {}
-//compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Foo {
bar: dyn for<'r> Fn(usize, &'r dyn FnMut())
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
// Regression test for an NLL-related ICE (#53568) -- we failed to
// resolve inference variables in "custom type-ops".
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Future {
type Item;
// rust-lang/rust#53675: At one point the compiler errored when a test
// named `panic` used the `assert!` macro in expression position.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: --test
mod in_expression_position {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct GstRc {
_obj: *const (),
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test checks that the `remove extra angle brackets` error doesn't happen for some
// potential edge-cases..
// This test is a minimal version of an ICE in the dropck-eyepatch tests
// found in the fix for #54943.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn foo<T>(_t: T) {
}
// found in the fix for #54943. In particular, this test is in unreachable
// code as the initial fix for this ICE only worked if the code was reachable.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn foo<T>(_t: T) {
}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// FIXME(#54943) This test targets the scenario where proving the WF requirements requires
// knowing the value of the `_` type present in the user type annotation - unfortunately, figuring
// out the value of that `_` requires type-checking the surrounding code, but that code is dead,
// is OK because the test is here to check that the compiler doesn't ICE (cf.
// #5500).
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct TrieMapIterator<'a> {
node: &'a usize
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
// Regression test for #56128. When this `pub(super) use...` gets
// exploded in the HIR, we were not handling ids correctly.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
mod bar {
pub(super) use self::baz::{x, y};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait FooTrait {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct T {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Foo<Args> {
type Output;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Foo {}
impl Foo for dyn Send {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Originally from #53925.
// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(improper_ctypes)]
+++ /dev/null
-// compile-pass
-
-#![feature(type_alias_enum_variants)]
-
-enum Outer<T> {
- A(T)
-}
-
-enum Inner {
- A(i32)
-}
-
-type OuterAlias = Outer<Inner>;
-
-fn ice(x: OuterAlias) {
- // Fine
- match x {
- OuterAlias::A(Inner::A(_)) => (),
- }
- // Not fine
- match x {
- OuterAlias::A(Inner::A(y)) => (),
- }
-}
-
-fn main() {}
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-pub enum Enum {
- A(usize),
-}
-
-impl Enum {
- fn foo(&self) -> () {
- match self {
- Self::A => (),
- //~^ ERROR expected unit struct/variant or constant, found tuple variant
- }
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0533]: expected unit struct/variant or constant, found tuple variant `<Self>::A`
- --> $DIR/issue-58006.rs:9:13
- |
-LL | Self::A => (),
- | ^^^^^^^
-
-error: aborting due to previous error
-
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z unpretty=hir
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z unpretty=hir
#![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
#[derive(PartialEq)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(improper_ctypes)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// pretty-expanded FIXME #23616
use std::mem;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Foo1 {}
trait A {}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
#![allow(non_snake_case)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Regression test for issue 9243
#![allow(non_upper_case_globals)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
// compile-flags: -A bad-style
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let _InappropriateCamelCasing = true;
// compile-flags: -W bad-style
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let _InappropriateCamelCasing = true;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// run-rustfix
#![warn(ellipsis_inclusive_range_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// run-rustfix
#![warn(ellipsis_inclusive_range_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(box_syntax)]
#![feature(box_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_parens)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![forbid(non_camel_case_types)]
#![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(ellipsis_inclusive_range_patterns)]
#![allow(unreachable_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Issue #7526: lowercase static constants in patterns look like bindings
// This is similar to lint-lowercase-static-const-pattern.rs, except it
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(non_camel_case_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// This is ok because we often use the trailing underscore to mean 'prime'
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// aux-build:lint_output_format.rs
#![feature(unstable_test_feature)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
extern crate lint_output_format;
use lint_output_format::{foo, bar};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:lint_stability.rs
// aux-build:inherited_stability.rs
// aux-build:stability_cfg1.rs
// FIXME(#44232) we should warn that this isn't used.
#![feature(rust1)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() { }
// FIXME(#44232) we should warn that this isn't used.
#![feature(rust1)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {}
// aux-build:lints-in-foreign-macros.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
#![warn(missing_docs)]
// Issue #50124 - Test warning for unused operator expressions
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_must_use)]
--- /dev/null
+#![deny(unused_must_use)]
+
+#[must_use]
+struct S;
+
+struct A;
+
+#[must_use]
+trait T {}
+
+impl T for A {}
+
+fn empty() -> [S; 0] {
+ []
+}
+
+fn singleton() -> [S; 1] {
+ [S]
+}
+
+fn many() -> [S; 4] {
+ [S, S, S, S]
+}
+
+fn array_of_impl_trait() -> [impl T; 2] {
+ [A, A]
+}
+
+fn impl_array() -> [(u8, Box<dyn T>); 2] {
+ [(0, Box::new(A)), (0, Box::new(A))]
+}
+
+fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
+ [[[S], [S]]]
+}
+
+fn main() {
+ empty(); // ok
+ singleton(); //~ ERROR unused array of `S` that must be used
+ many(); //~ ERROR unused array of `S` that must be used
+ ([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used
+ array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used
+ impl_array();
+ //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used
+ array_of_arrays_of_arrays();
+ //~^ ERROR unused array of arrays of arrays of `S` that must be used
+}
--- /dev/null
+error: unused array of `S` that must be used
+ --> $DIR/must_use-array.rs:39:5
+ |
+LL | singleton();
+ | ^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/must_use-array.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused array of `S` that must be used
+ --> $DIR/must_use-array.rs:40:5
+ |
+LL | many();
+ | ^^^^^^^
+
+error: unused array of `S` in tuple element 0 that must be used
+ --> $DIR/must_use-array.rs:41:6
+ |
+LL | ([S], 0, ());
+ | ^^^
+
+error: unused array of implementers of `T` that must be used
+ --> $DIR/must_use-array.rs:42:5
+ |
+LL | array_of_impl_trait();
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused array of boxed `T` trait objects in tuple element 1 that must be used
+ --> $DIR/must_use-array.rs:43:5
+ |
+LL | impl_array();
+ | ^^^^^^^^^^^^^
+
+error: unused array of arrays of arrays of `S` that must be used
+ --> $DIR/must_use-array.rs:45:5
+ |
+LL | array_of_arrays_of_arrays();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
Anon {}
}
+fn get_boxed_critical() -> Box<dyn Critical> {
+ Box::new(Anon {})
+}
+
+fn get_nested_boxed_critical() -> Box<Box<dyn Critical>> {
+ Box::new(Box::new(Anon {}))
+}
+
+fn get_critical_tuple() -> (u32, Box<dyn Critical>, impl Critical, ()) {
+ (0, get_boxed_critical(), get_critical(), ())
+}
+
fn main() {
get_critical(); //~ ERROR unused implementer of `Critical` that must be used
+ get_boxed_critical(); //~ ERROR unused boxed `Critical` trait object that must be used
+ get_nested_boxed_critical();
+ //~^ ERROR unused boxed boxed `Critical` trait object that must be used
+ get_critical_tuple(); //~ ERROR unused boxed `Critical` trait object in tuple element 1
+ //~^ ERROR unused implementer of `Critical` in tuple element 2
}
error: unused implementer of `Critical` that must be used
- --> $DIR/must_use-trait.rs:21:5
+ --> $DIR/must_use-trait.rs:33:5
|
LL | get_critical();
| ^^^^^^^^^^^^^^^
LL | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: unused boxed `Critical` trait object that must be used
+ --> $DIR/must_use-trait.rs:34:5
+ |
+LL | get_boxed_critical();
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: unused boxed boxed `Critical` trait object that must be used
+ --> $DIR/must_use-trait.rs:35:5
+ |
+LL | get_nested_boxed_critical();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused boxed `Critical` trait object in tuple element 1 that must be used
+ --> $DIR/must_use-trait.rs:37:5
+ |
+LL | get_critical_tuple();
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: unused implementer of `Critical` in tuple element 2 that must be used
+ --> $DIR/must_use-trait.rs:37:5
+ |
+LL | get_critical_tuple();
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// this tests the `unknown_lint` lint, especially the suggestions
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(lint_reasons)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(overflowing_literals)]
fn main() {
// suggestions to use `crate` given when it is on). When that feature becomes
// stable, this test can be deleted.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(crate_visibility_modifier)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_imports)] // Warning explanation here, it's OK
// should also deal with the edge cases where a label is shadowed,
// within nested loops
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(label_break_value)]
#![warn(unused_labels)]
// compile-flags: --error-format pretty-json -Zunstable-options
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested
"spans": [
{
"file_name": "$DIR/unused_parens_json_suggestion.rs",
- "byte_start": 576,
- "byte_end": 589,
+ "byte_start": 611,
+ "byte_end": 624,
"line_start": 15,
"line_end": 15,
"column_start": 14,
"spans": [
{
"file_name": "$DIR/unused_parens_json_suggestion.rs",
- "byte_start": 422,
- "byte_end": 435,
+ "byte_start": 457,
+ "byte_end": 470,
"line_start": 10,
"line_end": 10,
"column_start": 9,
"spans": [
{
"file_name": "$DIR/unused_parens_json_suggestion.rs",
- "byte_start": 576,
- "byte_end": 589,
+ "byte_start": 611,
+ "byte_end": 624,
"line_start": 15,
"line_end": 15,
"column_start": 14,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused_imports)]
use crate::foo::Bar; //~ WARNING first import
--- /dev/null
+// Regression test for #62312
+// check-pass
+
+fn main() {
+ let _ = loop {
+ break Box::new(()) as Box<dyn Send>;
+ };
+}
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-tidy-linelength
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-tidy-linelength
// Issue #21633: reject duplicate loop labels in function bodies.
// This is testing interaction between lifetime-params and labels.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code, unused_variables)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code, unused_variables)]
// ignore-emscripten no asm! support
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(asm)]
#![allow(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(extern_prelude)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:macro-in-other-crate.rs
#![feature(decl_macro)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
macro_rules! foo {
// aux-build:two_macros.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
fn f() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Wunused
// make sure write!() can't hide its unused Result
// compile-flags: -Z trace-macros
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
println!("Hello, World!");
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[doc] //~ WARN attribute must be of the form
#[ignore()] //~ WARN attribute must be of the form
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct S<T>(*const T) where T: ?Sized;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
struct S;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Check that method probing ObjectCandidate works in the presence of
// auto traits and/or HRTBs.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
macro_rules! m {
// Test that an assignment of type ! makes the rest of the block dead code.
#![feature(never_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type="lib"]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Test that we propagate region relations from closures precisely when there is
// more than one non-local lower bound.
// regions is erased.
// compile-flags:-Zborrowck=mir -Zverbose
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
// arbitrary types without ICEs.
// compile-flags:-Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
const HI: &str = "hi";
// including) the call to `use_x`. The `else` branch is not included.
// compile-flags:-Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
#![feature(dropck_eyepatch)]
// `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for
// the unexpected region.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait T {}
fn f() where dyn T: {}
// extra unused mut lint tests for #51918
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(generators, nll)]
#![deny(unused_mut)]
// over a yield -- because the data that is borrowed (`*x`) is not
// stored on the stack.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn foo(x: &mut u32) {
move || {
// |
// = note: move occurs because the value has type `A`, which does not implement the `Copy` trait
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(box_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::collections::HashMap;
use std::sync::Mutex;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn from_stdin(min: u64) -> Vec<u64> {
use std::io::BufRead;
// rust-lang/rust#22323: regression test demonstrating that NLL
// precisely tracks temporary destruction order.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let _s = construct().borrow().consume_borrowed();
// Regression test for #30104
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::ops::{Deref, DerefMut};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// rust-lang/rust#32382: Borrow checker used to complain about
// `foobar_3` in the `impl` below, presumably due to some interaction
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::borrow::Cow;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct LoadedObject {
bodies: Vec<Body>,
// bounds derived from `Sized` requirements” that checks that the fixed compiler
// accepts this code fragment with both AST and MIR borrow checkers.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Qey<Q: ?Sized>(Q);
// of the closure, as they were not present in the closure's generic
// declarations otherwise.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn creash<'a>() {
let x: &'a () = &();
// between `'a` and `'b` below due to inference variables introduced
// during the normalization process.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Drain<'a, T: 'a> {
_marker: ::std::marker::PhantomData<&'a T>,
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::ops::Deref;
// parameter `x` -- since `'b` cannot be expressed in the caller's
// space, that got promoted th `'static`.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::cell::{RefCell, Ref};
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(unused_mut)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(untagged_unions)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Foo<'a> {
const C: &'a u32;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Foo {
const BLAH: &'static str;
// Regression test for #61311
// We would ICE after failing to normalize `Self::Proj` in the `impl` below.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct Unit;
trait Obj {}
// Regression test for #61320
// This is the same issue as #61311, just a larger test case.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
pub struct AndThen<A, B, F>
where
// compile-flags: -Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
// compile-flags:-Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
// another -- effectively, the single lifetime `'a` is just inferred
// to be the intersection of the two distinct lifetimes.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:-Zno-leak-check
#![feature(nll)]
// function returning always its first argument can be upcast to one
// that returns either first or second argument.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:-Zno-leak-check
#![feature(nll)]
// placeholder region, but in NLL land it would fail because we had
// rewritten `'static` to a region variable.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Foo {
fn foo(&self) { }
// Regression test for #53789.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::collections::BTreeMap;
// Regression test for #53789.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::collections::BTreeMap;
use std::ops::Range;
// Fixed by tweaking the solver to recognize that the constraint from
// the environment duplicates one from the trait.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type="lib"]
// Test that when we infer the lifetime to a subset of the fn body, it
// works out.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait MyTrait<'a> {
type Output;
-// compile-flags:-Zborrowck=mir -Zverbose
-
// Test that we can deduce when projections like `T::Item` outlive the
// function body. Test that this does not imply that `T: 'a` holds.
-#![allow(warnings)]
-#![feature(rustc_attrs)]
+// compile-flags:-Zborrowck=mir -Zverbose
use std::cell::Cell;
f(&value, Cell::new(&n));
}
-#[rustc_errors]
fn generic1<T: Iterator>(value: T) {
// No error here:
twice(value, |value_ref, item| invoke1(item));
{
}
-#[rustc_errors]
fn generic2<T: Iterator>(value: T) {
twice(value, |value_ref, item| invoke2(value_ref, item));
//~^ ERROR the parameter type `T` may not live long enough
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/projection-implied-bounds.rs:35:18
+ --> $DIR/projection-implied-bounds.rs:30:18
|
LL | twice(value, |value_ref, item| invoke2(value_ref, item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// we don't even propagate constraints from the closures to the callers.
// compile-flags:-Zborrowck=mir -Zverbose
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
#![feature(rustc_attrs)]
//
// Regression test for #53121.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait MyTrait<'a> {
type Output;
// MyTrait<'a>>::Output: 'a` outlives `'a` (because the trait says
// so).
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait MyTrait<'a> {
type Output: 'a;
// compile-flags:-Zborrowck=mir -Zverbose
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Test that we assume that universal types like `T` outlive the
// function body.
-#![allow(warnings)]
-#![feature(rustc_attrs)]
-
use std::cell::Cell;
fn twice<F, T>(value: T, mut f: F)
f(Cell::new(&value));
}
-#[rustc_errors]
fn generic<T>(value: T) {
// No error here:
twice(value, |r| invoke(r));
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Check that we don't try to downcast `_` when type-checking the annotation.
fn main() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test is reduced from a scenario pnkfelix encountered while
// bootstrapping the compiler.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Foo(String);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
mod x;
-error: 'a,Ambiguous
- --> $DIR/object-lifetime-default.rs:24:1
+error: BaseDefault
+ --> $DIR/object-lifetime-default.rs:6:1
|
-LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | struct A<T>(T);
+ | ^^^^^^^^^^^^^^^
-error: 'a,'b
- --> $DIR/object-lifetime-default.rs:21:1
+error: BaseDefault
+ --> $DIR/object-lifetime-default.rs:9:1
|
-LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | struct B<'a,T>(&'a (), T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: 'b
- --> $DIR/object-lifetime-default.rs:18:1
+error: 'a
+ --> $DIR/object-lifetime-default.rs:12:1
|
-LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | struct C<'a,T:'a>(&'a T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: Ambiguous
--> $DIR/object-lifetime-default.rs:15:1
LL | struct D<'a,'b,T:'a+'b>(&'a T, &'b T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: 'a
- --> $DIR/object-lifetime-default.rs:12:1
+error: 'b
+ --> $DIR/object-lifetime-default.rs:18:1
|
-LL | struct C<'a,T:'a>(&'a T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: BaseDefault
- --> $DIR/object-lifetime-default.rs:9:1
+error: 'a,'b
+ --> $DIR/object-lifetime-default.rs:21:1
|
-LL | struct B<'a,T>(&'a (), T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: BaseDefault
- --> $DIR/object-lifetime-default.rs:6:1
+error: 'a,Ambiguous
+ --> $DIR/object-lifetime-default.rs:24:1
|
-LL | struct A<T>(T);
- | ^^^^^^^^^^^^^^^
+LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 7 previous errors
// Check that a trait with by-value self is considered object-safe.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(trivial_casts)]
// Check that `Self` appearing in a phantom fn does not make a trait not object safe.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait Baz {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![crate_type = "rlib"]
#![no_std]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(bare_trait_objects)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z parse-only
impl <*const u8>::AssocTy {} // OK
fn main() {
- foo! bar < //~ ERROR expected `(` or `{`, found `<`
+ foo! bar < //~ ERROR expected open delimiter
}
-error: expected `(` or `{`, found `<`
- --> $DIR/macro-bad-delimiter-ident.rs:2:14
+error: expected open delimiter
+ --> $DIR/macro-bad-delimiter-ident.rs:2:10
|
LL | foo! bar <
- | ^ expected `(` or `{`
+ | ^^^ expected open delimiter
error: aborting due to previous error
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(box_syntax)]
#![allow(bare_trait_objects)]
// Fixes issue where `+` in generics weren't parsed if they were part of a `+=`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Whitespace<T: Clone + = ()> { t: T }
struct TokenSplit<T: Clone += ()> { t: T }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
let _ = "Foo"_;
+++ /dev/null
-// run-pass
-
-#![feature(type_alias_enum_variants)]
-
-#![allow(irrefutable_let_patterns)]
-
-#[allow(dead_code)]
-enum Enum<T> { TSVariant(T), SVariant { v: T } }
-type Alias<T> = Enum<T>;
-type AliasFixed = Enum<()>;
-
-macro_rules! is_variant {
- (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
- (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
- (@check $variant:ident, $matcher:tt, $expr:expr) => (
- assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
- "expr does not have correct type");
- );
-}
-
-fn main() {
- // Tuple struct variant
-
- is_variant!(TSVariant, Enum::TSVariant(()));
- is_variant!(TSVariant, Enum::TSVariant::<()>(()));
- is_variant!(TSVariant, Enum::<()>::TSVariant(()));
-
- is_variant!(TSVariant, Alias::TSVariant(()));
- is_variant!(TSVariant, Alias::<()>::TSVariant(()));
-
- is_variant!(TSVariant, AliasFixed::TSVariant(()));
-
- // Struct variant
-
- is_variant!(SVariant, Enum::SVariant { v: () });
- is_variant!(SVariant, Enum::SVariant::<()> { v: () });
- is_variant!(SVariant, Enum::<()>::SVariant { v: () });
-
- is_variant!(SVariant, Alias::SVariant { v: () });
- is_variant!(SVariant, Alias::<()>::SVariant { v: () });
-
- is_variant!(SVariant, AliasFixed::SVariant { v: () });
-}
// (#55495: The --error-format is to sidestep an issue in our test harness)
// compile-flags: --error-format human -Z print-fuel=foo
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct S1(u8, u16, u8);
struct S2(u8, u16, u8);
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// All of the types that occur in this function are uninteresting, in
// that one cannot control the sizes of these types with the same sort
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This file illustrates that when multiple structural types occur in
// a function, every one of them is included in the output.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This file illustrates how padding is handled: alignment
// requirements can lead to the introduction of padding, either before
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// This file illustrates two things:
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:issue-57264-1.rs
extern crate issue_57264_1;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:issue-57264-2.rs
extern crate issue_57264_2;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(existential_type)]
#![deny(private_in_public)]
// Patterns and expressions are not interface parts and don't produce private-in-public errors.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct Priv1(usize);
struct Priv2;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
mod foo {
// aux-build:attributes-included.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test-macros.rs
// aux-build:derive-helper-shadowed-2.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test-macros.rs
extern crate test_macros;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// aux-build:test-macros.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// aux-build:edition-imports-2015.rs
// aux-build:derive-unstable-2.rs
-#![allow(warnings)]
-
#[macro_use]
extern crate derive_unstable_2;
#[derive(Unstable)]
-//~^ ERROR: reserved for internal compiler
+//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+//~| ERROR attribute `rustc_foo` is currently unknown to the compiler
+
struct A;
fn main() {
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
- --> $DIR/expand-to-unstable-2.rs:8:10
+error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/expand-to-unstable-2.rs:6:10
|
LL | #[derive(Unstable)]
| ^^^^^^^^
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: The attribute `rustc_foo` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/expand-to-unstable-2.rs:6:10
+ |
+LL | #[derive(Unstable)]
+ | ^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = 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`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
extern crate proc_macro;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test-macros.rs
#[macro_use(Empty)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test-macros.rs
#[macro_use]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test-macros.rs
#[macro_use]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test-macros.rs
#![feature(proc_macro_hygiene)]
//! Verify that the `decls` module implicitly added by the compiler does not cause `missing_docs`
//! warnings.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// force-host
// no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::ops::*;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::ops::*;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
use std::ops::*;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_variables)]
#![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused_variables)]
#![allow(dead_code)]
// follow the same lifetime-elision rules used elsehwere. See
// rust-lang/rust#56537
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str {
let free_dumb = |_x| { p }; // no type annotation at all
// Test related to #22779. In this case, the impl is an inherent impl,
// so it doesn't have to match any trait, so no error results.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct MySlice<'a, T:'a>(&'a mut [T]);
// Test related to #22779, but where the `'a:'b` relation
// appears in the trait too. No error here.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Tr<'a, T> {
fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b;
// Various tests related to testing how region inference works
// with respect to the object receivers.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
trait Foo {
// Various tests related to testing how region inference works
// with respect to the object receivers.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(warnings)]
trait Foo {
// "projection gap": in this test, we know that `T: 'x`, and that is
// enough to conclude that `T::Foo: 'x`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
// "projection gap": in this test, we know that `T::Foo: 'x`, and that
// is (naturally) enough to conclude that `T::Foo: 'x`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
// "projection gap": in this test, we know that `T: 'x`, and that
// is (naturally) enough to conclude that `T: 'x`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
#![allow(unused_variables)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-//compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
//
// Rule OutlivesNominalType from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
#![allow(dead_code)]
// `'r` is bound, that leads to badness. This test checks that
// everything works.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait TheTrait {
// Test that `<F as Foo<'a>>::Type: 'b`, where `trait Foo<'a> { Type:
// 'a; }`, does not require that `F: 'b`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
trait SomeTrait<'a> {
// Test that scalar values outlive all regions.
// Rule OutlivesScalar from RFC 1214.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
struct Foo<'a> {
// edition:2018
// aux-build:removing-extern-crate.rs
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_idioms)]
#![allow(unused_imports)]
// edition:2018
// aux-build:removing-extern-crate.rs
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_idioms)]
#![allow(unused_imports)]
#[rustc_attribute_should_be_reserved]
-//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
+//~^ ERROR attribute `rustc_attribute_should_be_reserved` is currently unknown
+//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+
macro_rules! foo {
() => (());
}
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
+error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
--> $DIR/reserved-attr-on-macro.rs:1:3
|
LL | #[rustc_attribute_should_be_reserved]
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
+error[E0658]: The attribute `rustc_attribute_should_be_reserved` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/reserved-attr-on-macro.rs:1:3
+ |
+LL | #[rustc_attribute_should_be_reserved]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
error: cannot determine resolution for the macro `foo`
- --> $DIR/reserved-attr-on-macro.rs:8:5
+ --> $DIR/reserved-attr-on-macro.rs:10:5
|
LL | foo!();
| ^^^
|
= note: import resolution is stuck, try simplifying macro imports
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct S(u8);
// rust-lang/rust#2329), that starts passing with this feature in
// place.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(bind_by_move_pattern_guards)]
#![feature(bind_by_move_pattern_guards)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct A { a: Box<i32> }
// aux-build:uninhabited.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(unreachable_patterns)]
#![feature(exhaustive_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:variants.rs
extern crate variants;
// strange errors. This test ensures that we do not give compilation
// errors.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait MyIterator<'a>: Iterator where Self::Item: 'a { }
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:underscore-imports.rs
#![warn(unused_imports, unused_extern_crates)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:duplicate.rs
extern crate duplicate;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:underscore-imports.rs
extern crate underscore_imports;
// This test should pass since 'identity' is const fn.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
fn main() {
const _FOO: u8 = ::std::convert::identity(42u8);
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z unpretty=expanded
fn main() {
use ::std::prelude::v1::*;
#[macro_use]
extern crate std;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z unpretty=expanded
fn main() { if let 0 = 1 { } }
// compile-flags: --cfg something
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(param_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z parse-only
#![feature(generic_associated_types)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Z parse-only
#![feature(generic_associated_types)]
//FIXME(#44265): The lifetime shadowing and type parameter shadowing
// should cause an error. Now it compiles (erroneously) and this will be addressed
// by a future PR. Then remove the following:
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
trait Shadow<'a> {
type Bar<'a>; // Error: shadowed lifetime
// compile-flags: --emit=metadata
// aux-build:rmeta-rlib.rs
// no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Check that building a metadata crate works with a dependent, rlib crate.
// This is a cfail test since there is no executable to run.
// compile-flags: --emit=metadata
// aux-build:rmeta-meta.rs
// no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Check that building a metadata crate works with a dependent, metadata-only
// crate.
// compile-flags: --emit=metadata
// no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#[deny(warnings)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// compile-flags:--extern edition_lint_paths
// aux-build:edition-lint-paths.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(unused)]
#![deny(explicit_outlives_requirements)]
// aux-build:macro-use-warned-against.rs
// aux-build:macro-use-warned-against2.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(macro_use_extern_crate, unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// force-host
// no-prefer-dynamic
// run-rustfix
// edition:2018
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:remove-extern-crate.rs
// compile-flags:--extern remove_extern_crate
// run-rustfix
// edition:2018
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:remove-extern-crate.rs
// compile-flags:--extern remove_extern_crate
// edition:2015
// run-rustfix
// rustfix-only-machine-applicable
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rust_2018_preview)]
#![warn(rust_2018_compatibility)]
// edition:2015
// run-rustfix
// rustfix-only-machine-applicable
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rust_2018_preview)]
#![warn(rust_2018_compatibility)]
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_compatibility)]
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_compatibility)]
// Test that `try!` macros are rewritten.
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_compatibility)]
#![allow(unused_variables)]
// Test that `try!` macros are rewritten.
// run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(rust_2018_compatibility)]
#![allow(unused_variables)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
fn main() {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
#![feature(decl_macro)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// compile-flags: --extern issue_56596_2
// aux-build:issue-56596-2.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
// Macro imported with `#[macro_use] extern crate`
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: -Zsave-analysis -Zemit-artifact-notifications
// compile-flags: --crate-type rlib --error-format=json
// ignore-pass
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// Test to make sure that explicit self params work inside closures
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(untagged_unions)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
// pretty-expanded FIXME #23616
// (Normally, using `'static` would be preferred, but there are
// times when that is not what you want.)
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(single_use_lifetimes)]
// even when they are only used once (since to not use a named
// lifetime is illegal!)
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(single_use_lifetimes)]
#![allow(dead_code)]
// Test that we DO NOT warn when lifetime name is used in
// both the argument and return.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(single_use_lifetimes)]
#![allow(dead_code)]
// Test that we DO NOT warn when lifetime name is used multiple
// arguments, or more than once in a single argument.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(single_use_lifetimes)]
#![allow(dead_code)]
// Test that we DO NOT warn for a lifetime used twice in an impl.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(single_use_lifetimes)]
#![allow(dead_code)]
// Test that we DO NOT warn for a lifetime on an impl used in both
// header and in an associated type.
//
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(single_use_lifetimes)]
#![allow(dead_code)]
//! A test to ensure that helpful `note` messages aren't emitted more often
//! than necessary.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Although there are three warnings, we should only get two "lint level defined
// here" notes pointing at the `warnings` span, one for each error type.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![warn(unused)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(extern_types)]
pub mod a {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(no_core, lang_items)]
#![no_core]
-#[deprcated] //~ ERROR E0658
-fn foo() {} //~| HELP a built-in attribute with a similar name exists
- //~| SUGGESTION deprecated
- //~| HELP add #![feature(custom_attribute)] to the crate attributes to enable
+#[deprcated] //~ ERROR attribute `deprcated` is currently unknown
+fn foo() {}
-#[tests] //~ ERROR E0658
-fn bar() {} //~| HELP a built-in attribute with a similar name exists
- //~| SUGGESTION test
- //~| HELP add #![feature(custom_attribute)] to the crate attributes to enable
+#[tests] //~ ERROR attribute `tests` is currently unknown to the compiler
+fn bar() {}
-#[rustc_err] //~ ERROR E0658
-fn main() {} //~| HELP add #![feature(rustc_attrs)] to the crate attributes to enable
- // don't suggest rustc attributes
+#[rustc_err]
+//~^ ERROR attribute `rustc_err` is currently unknown
+//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+
+fn main() {}
-error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
- --> $DIR/attribute-typos.rs:11:3
+error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/attribute-typos.rs:7:3
|
LL | #[rustc_err]
| ^^^^^^^^^
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
+error[E0658]: The attribute `rustc_err` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/attribute-typos.rs:7:3
+ |
+LL | #[rustc_err]
+ | ^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+ = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future
- --> $DIR/attribute-typos.rs:6:3
+ --> $DIR/attribute-typos.rs:4:3
|
LL | #[tests]
| ^^^^^ help: a built-in attribute with a similar name exists: `test`
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.
// aux-build:foo.rs
// compile-flags:--extern foo
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// edition:2018
#![deny(unused_extern_crates)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags:--test
#![deny(warnings)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// aux-build:test_macro.rs
// compile-flags:--test
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// compile-flags: --test
#[test]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// #39665
fn batches(n: &u32) -> impl Iterator<Item=&u32> {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// Regression test related to #56288. Check that a supertrait projection (of
// `Output`) that references `Self` can be ok if it is referencing a projection (of
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// FIXME(eddyb) shorten the name so windows doesn't choke on it.
#![crate_name = "trait_test"]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
mod foo {
pub use self::bar::T;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// #55266
struct VTable<DST: ?Sized> {
// types are required. This test now just compiles fine, since the
// relevant rules that triggered the overflow were removed.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
use std::marker::PhantomData;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code, unused)]
+++ /dev/null
-// ignore-tidy-linelength
-
-#![feature(type_alias_enum_variants)]
-
-#![allow(unreachable_code)]
-
-enum Enum { Variant {} }
-type Alias = Enum;
-
-fn main() {
- Alias::Variant;
- //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
- let Alias::Variant = panic!();
- //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
- let Alias::Variant(..) = panic!();
- //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Variant` [E0164]
-}
+++ /dev/null
-error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
- --> $DIR/type-alias-enum-variants-panic.rs:11:5
- |
-LL | Alias::Variant;
- | ^^^^^^^^^^^^^^
-
-error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
- --> $DIR/type-alias-enum-variants-panic.rs:13:9
- |
-LL | let Alias::Variant = panic!();
- | ^^^^^^^^^^^^^^
-
-error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Variant`
- --> $DIR/type-alias-enum-variants-panic.rs:15:9
- |
-LL | let Alias::Variant(..) = panic!();
- | ^^^^^^^^^^^^^^^^^^ not a tuple variant or struct
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0164`.
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-enum E {
- V(u8)
-}
-
-impl E {
- fn V() {}
-}
-
-fn main() {
- <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
-}
+++ /dev/null
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
- --> $DIR/type-alias-enum-variants-priority-2.rs:12:5
- |
-LL | V(u8)
- | ----- defined here
-...
-LL | <E>::V();
- | ^^^^^^^^ expected 1 parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0061`.
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-enum E {
- V
-}
-
-fn check() -> <E>::V {}
-//~^ ERROR expected type, found variant `V`
-
-fn main() {}
+++ /dev/null
-error: expected type, found variant `V`
- --> $DIR/type-alias-enum-variants-priority-3.rs:7:15
- |
-LL | fn check() -> <E>::V {}
- | ^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-enum E {
- V
-}
-
-trait Tr {
- type V;
- fn f() -> Self::V;
-}
-
-impl Tr for E {
- type V = u8;
- fn f() -> Self::V { 0 }
- //~^ ERROR ambiguous associated item
- //~| WARN this was previously accepted
-}
-
-fn main() {}
+++ /dev/null
-error: ambiguous associated item
- --> $DIR/type-alias-enum-variants-priority.rs:14:15
- |
-LL | fn f() -> Self::V { 0 }
- | ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
- |
- = note: #[deny(ambiguous_associated_items)] on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
-note: `V` could refer to variant defined here
- --> $DIR/type-alias-enum-variants-priority.rs:4:5
- |
-LL | V
- | ^
-note: `V` could also refer to associated type defined here
- --> $DIR/type-alias-enum-variants-priority.rs:8:5
- |
-LL | type V;
- | ^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-#![feature(type_alias_enum_variants)]
-
-type Alias<T> = Option<T>;
-
-fn main() {
- let _ = Option::<u8>::None; // OK
- let _ = Option::None::<u8>; // OK (Lint in future!)
- let _ = Alias::<u8>::None; // OK
- let _ = Alias::None::<u8>; // Error
- //~^ type arguments are not allowed for this type
-}
+++ /dev/null
-error[E0109]: type arguments are not allowed for this type
- --> $DIR/type-alias-enum-variants.rs:9:27
- |
-LL | let _ = Alias::None::<u8>; // Error
- | ^^ type argument not allowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0109`.
--- /dev/null
+// run-pass
+
+// Check that resolving, in the value namespace, to an `enum` variant
+// through a type alias is well behaved in the presence of generics.
+// We check for situations with:
+// 1. a generic type `Alias<T>`, we can type-apply `Alias` when referring to a variant.
+// 2. a monotype `AliasFixed` of generic `Enum<T>`, we can refer to variants
+// and the type-application of `T` in `AliasFixed` is kept.
+
+#![allow(irrefutable_let_patterns)]
+
+enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+type Alias<T> = Enum<T>;
+type AliasFixed = Enum<()>;
+
+macro_rules! is_variant {
+ (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
+ (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
+ (UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr));
+ (@check $variant:ident, $matcher:tt, $expr:expr) => (
+ assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
+ "expr does not have correct type");
+ );
+}
+
+fn main() {
+ // Tuple struct variant
+
+ is_variant!(TSVariant, Enum::TSVariant(()));
+ is_variant!(TSVariant, Enum::TSVariant::<()>(()));
+ is_variant!(TSVariant, Enum::<()>::TSVariant(()));
+
+ is_variant!(TSVariant, Alias::TSVariant(()));
+ is_variant!(TSVariant, Alias::<()>::TSVariant(()));
+
+ is_variant!(TSVariant, AliasFixed::TSVariant(()));
+
+ // Struct variant
+
+ is_variant!(SVariant, Enum::SVariant { v: () });
+ is_variant!(SVariant, Enum::SVariant::<()> { v: () });
+ is_variant!(SVariant, Enum::<()>::SVariant { v: () });
+
+ is_variant!(SVariant, Alias::SVariant { v: () });
+ is_variant!(SVariant, Alias::<()>::SVariant { v: () });
+
+ is_variant!(SVariant, AliasFixed::SVariant { v: () });
+
+ // Unit variant
+
+ is_variant!(UVariant, Enum::UVariant);
+ is_variant!(UVariant, Enum::UVariant::<()>);
+ is_variant!(UVariant, Enum::<()>::UVariant);
+
+ is_variant!(UVariant, Alias::UVariant);
+ is_variant!(UVariant, Alias::<()>::UVariant);
+
+ is_variant!(UVariant, AliasFixed::UVariant);
+}
--- /dev/null
+// Checks that applied type arguments of enums, and aliases to them, are respected.
+// For example, `Self` is never a type constructor. Therefore, no types can be applied to it.
+//
+// We also check that the variant to an type-aliased enum cannot be type applied whether
+// that alias is generic or monomorphic.
+
+enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+type Alias<T> = Enum<T>;
+type AliasFixed = Enum<()>;
+
+impl<T> Enum<T> {
+ fn ts_variant() {
+ Self::TSVariant(());
+ //~^ ERROR mismatched types [E0308]
+ Self::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ Self::<()>::TSVariant(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR mismatched types [E0308]
+ Self::<()>::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR type arguments are not allowed for this type [E0109]
+ }
+
+ fn s_variant() {
+ Self::SVariant { v: () };
+ //~^ ERROR mismatched types [E0308]
+ Self::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR mismatched types [E0308]
+ Self::<()>::SVariant { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR mismatched types [E0308]
+ Self::<()>::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^^ ERROR mismatched types [E0308]
+ }
+
+ fn u_variant() {
+ Self::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ Self::<()>::UVariant;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ Self::<()>::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR type arguments are not allowed for this type [E0109]
+ }
+}
+
+fn main() {
+ // Tuple struct variant
+
+ Enum::<()>::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+
+ Alias::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ Alias::<()>::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+
+ AliasFixed::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ AliasFixed::<()>::TSVariant(());
+ //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+ AliasFixed::<()>::TSVariant::<()>(());
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+ // Struct variant
+
+ Enum::<()>::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+
+ Alias::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ Alias::<()>::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+
+ AliasFixed::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ AliasFixed::<()>::SVariant { v: () };
+ //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+ AliasFixed::<()>::SVariant::<()> { v: () };
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+ // Unit variant
+
+ Enum::<()>::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+
+ Alias::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ Alias::<()>::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+
+ AliasFixed::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ AliasFixed::<()>::UVariant;
+ //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+ AliasFixed::<()>::UVariant::<()>;
+ //~^ ERROR type arguments are not allowed for this type [E0109]
+ //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-generic-args.rs:13:25
+ |
+LL | Self::TSVariant(());
+ | ^^ expected type parameter, found ()
+ |
+ = note: expected type `T`
+ found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:15:27
+ |
+LL | Self::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:17:16
+ |
+LL | Self::<()>::TSVariant(());
+ | ^^ type argument not allowed
+
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-generic-args.rs:17:31
+ |
+LL | Self::<()>::TSVariant(());
+ | ^^ expected type parameter, found ()
+ |
+ = note: expected type `T`
+ found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:20:16
+ |
+LL | Self::<()>::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:20:33
+ |
+LL | Self::<()>::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-generic-args.rs:26:29
+ |
+LL | Self::SVariant { v: () };
+ | ^^ expected type parameter, found ()
+ |
+ = note: expected type `T`
+ found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:28:26
+ |
+LL | Self::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-generic-args.rs:28:35
+ |
+LL | Self::SVariant::<()> { v: () };
+ | ^^ expected type parameter, found ()
+ |
+ = note: expected type `T`
+ found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:31:16
+ |
+LL | Self::<()>::SVariant { v: () };
+ | ^^ type argument not allowed
+
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-generic-args.rs:31:35
+ |
+LL | Self::<()>::SVariant { v: () };
+ | ^^ expected type parameter, found ()
+ |
+ = note: expected type `T`
+ found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:34:16
+ |
+LL | Self::<()>::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:34:32
+ |
+LL | Self::<()>::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-generic-args.rs:34:41
+ |
+LL | Self::<()>::SVariant::<()> { v: () };
+ | ^^ expected type parameter, found ()
+ |
+ = note: expected type `T`
+ found type `()`
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:41:26
+ |
+LL | Self::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:43:16
+ |
+LL | Self::<()>::UVariant;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:45:16
+ |
+LL | Self::<()>::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:45:32
+ |
+LL | Self::<()>::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:54:29
+ |
+LL | Enum::<()>::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:57:24
+ |
+LL | Alias::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:59:30
+ |
+LL | Alias::<()>::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:62:29
+ |
+LL | AliasFixed::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+ --> $DIR/enum-variant-generic-args.rs:64:18
+ |
+LL | AliasFixed::<()>::TSVariant(());
+ | ^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+ --> $DIR/enum-variant-generic-args.rs:66:18
+ |
+LL | AliasFixed::<()>::TSVariant::<()>(());
+ | ^^ unexpected type argument
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:66:35
+ |
+LL | AliasFixed::<()>::TSVariant::<()>(());
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:72:28
+ |
+LL | Enum::<()>::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:75:23
+ |
+LL | Alias::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:77:29
+ |
+LL | Alias::<()>::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:80:28
+ |
+LL | AliasFixed::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+ --> $DIR/enum-variant-generic-args.rs:82:18
+ |
+LL | AliasFixed::<()>::SVariant { v: () };
+ | ^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+ --> $DIR/enum-variant-generic-args.rs:84:18
+ |
+LL | AliasFixed::<()>::SVariant::<()> { v: () };
+ | ^^ unexpected type argument
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:84:34
+ |
+LL | AliasFixed::<()>::SVariant::<()> { v: () };
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:90:28
+ |
+LL | Enum::<()>::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:93:23
+ |
+LL | Alias::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:95:29
+ |
+LL | Alias::<()>::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:98:28
+ |
+LL | AliasFixed::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+ --> $DIR/enum-variant-generic-args.rs:100:18
+ |
+LL | AliasFixed::<()>::UVariant;
+ | ^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+ --> $DIR/enum-variant-generic-args.rs:102:18
+ |
+LL | AliasFixed::<()>::UVariant::<()>;
+ | ^^ unexpected type argument
+
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/enum-variant-generic-args.rs:102:34
+ |
+LL | AliasFixed::<()>::UVariant::<()>;
+ | ^^ type argument not allowed
+
+error: aborting due to 39 previous errors
+
+Some errors have detailed explanations: E0107, E0109, E0308.
+For more information about an error, try `rustc --explain E0107`.
--- /dev/null
+// Check that an `enum` variant is resolved, in the value namespace,
+// with higher priority than other inherent items when there is a conflict.
+
+enum E {
+ V(u8)
+}
+
+impl E {
+ fn V() {}
+}
+
+enum E2 {
+ V,
+}
+
+impl E2 {
+ const V: u8 = 0;
+}
+
+fn main() {
+ <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+ let _: u8 = <E2>::V; //~ ERROR mismatched types
+}
--- /dev/null
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+ --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
+ |
+LL | V(u8)
+ | ----- defined here
+...
+LL | <E>::V();
+ | ^^^^^^^^ expected 1 parameter
+
+error[E0308]: mismatched types
+ --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
+ |
+LL | let _: u8 = <E2>::V;
+ | ^^^^^^^ expected u8, found enum `E2`
+ |
+ = note: expected type `u8`
+ found type `E2`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
--- /dev/null
+// Check that a projection `Self::V` in a trait implementation,
+// with an associated type named `V`, for an `enum` with a variant named `V`,
+// results in triggering the deny-by-default lint `ambiguous_associated_items`.
+// The lint suggests that qualified syntax should be used instead.
+// That is, the user would write `<Self as Tr>::V`.
+//
+// The rationale for this is that while `enum` variants do currently
+// not exist in the type namespace but solely in the value namespace,
+// RFC #2593 "Enum variant types", would add enum variants to the type namespace.
+// However, currently `enum` variants are resolved with high priority as
+// they are resolved as inherent associated items.
+// Should #2953 therefore be implemented, `Self::V` would suddenly switch
+// from referring to the associated type `V` instead of the variant `V`.
+// The lint exists to keep us forward compatible with #2593.
+//
+// As a closing note, provided that #2933 was implemented and
+// if `enum` variants were given lower priority than associated types,
+// it would be impossible to refer to the `enum` variant `V` whereas
+// the associated type could be referred to with qualified syntax as seen above.
+
+enum E {
+ V
+}
+
+trait Tr {
+ type V;
+ fn f() -> Self::V;
+}
+
+impl Tr for E {
+ type V = u8;
+ fn f() -> Self::V { 0 }
+ //~^ ERROR ambiguous associated item
+ //~| WARN this was previously accepted
+}
+
+fn main() {}
--- /dev/null
+error: ambiguous associated item
+ --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
+ |
+LL | fn f() -> Self::V { 0 }
+ | ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
+ |
+ = note: #[deny(ambiguous_associated_items)] on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to variant defined here
+ --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5
+ |
+LL | V
+ | ^
+note: `V` could also refer to associated type defined here
+ --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5
+ |
+LL | type V;
+ | ^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+pub enum Enum {
+ A(usize),
+}
+
+impl Enum {
+ fn foo(&self) -> () {
+ match self {
+ Self::A => (),
+ //~^ ERROR expected unit struct/variant or constant, found tuple variant
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0533]: expected unit struct/variant or constant, found tuple variant `<Self>::A`
+ --> $DIR/incorrect-variant-form-through-Self-issue-58006.rs:8:13
+ |
+LL | Self::A => (),
+ | ^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// ignore-tidy-linelength
+
+// Check that creating/matching on an enum variant through an alias with
+// the wrong braced/unit form is caught as an error.
+
+enum Enum { Braced {}, Unit, Tuple() }
+type Alias = Enum;
+
+fn main() {
+ Alias::Braced;
+ //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Braced` [E0533]
+ let Alias::Braced = panic!();
+ //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Braced` [E0533]
+ let Alias::Braced(..) = panic!();
+ //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Braced` [E0164]
+
+ Alias::Unit();
+ //~^ ERROR expected function, found enum variant `<Alias>::Unit`
+ let Alias::Unit() = panic!();
+ //~^ ERROR expected tuple struct/variant, found unit variant `<Alias>::Unit` [E0164]
+}
--- /dev/null
+error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Braced`
+ --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:5
+ |
+LL | Alias::Braced;
+ | ^^^^^^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Braced`
+ --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9
+ |
+LL | let Alias::Braced = panic!();
+ | ^^^^^^^^^^^^^
+
+error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Braced`
+ --> $DIR/incorrect-variant-form-through-alias-caught.rs:14:9
+ |
+LL | let Alias::Braced(..) = panic!();
+ | ^^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error[E0618]: expected function, found enum variant `<Alias>::Unit`
+ --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:5
+ |
+LL | enum Enum { Braced {}, Unit, Tuple() }
+ | ---- `<Alias>::Unit` defined here
+...
+LL | Alias::Unit();
+ | ^^^^^^^^^^^--
+ | |
+ | call expression requires function
+help: `<Alias>::Unit` is a unit variant, you need to write it without the parenthesis
+ |
+LL | <Alias>::Unit;
+ | ^^^^^^^^^^^^^
+
+error[E0164]: expected tuple struct/variant, found unit variant `<Alias>::Unit`
+ --> $DIR/incorrect-variant-form-through-alias-caught.rs:19:9
+ |
+LL | let Alias::Unit() = panic!();
+ | ^^^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0164, E0618.
+For more information about an error, try `rustc --explain E0164`.
--- /dev/null
+// build-pass (FIXME(62277): could be check-pass?)
+
+enum Outer<T> {
+ A(T)
+}
+
+enum Inner {
+ A(i32)
+}
+
+type OuterAlias = Outer<Inner>;
+
+fn ice(x: OuterAlias) {
+ // Fine
+ match x {
+ OuterAlias::A(Inner::A(_)) => (),
+ }
+ // Not fine
+ match x {
+ OuterAlias::A(Inner::A(y)) => (),
+ }
+}
+
+fn main() {}
// In this regression test we check that a path pattern referring to a unit variant
// through a type alias is successful in inferring the generic argument.
-// compile-pass
-
-#![feature(type_alias_enum_variants)]
+// build-pass (FIXME(62277): could be check-pass?)
enum Opt<T> {
N,
--- /dev/null
+// Check that a generic type for an `enum` admits type application
+// on both the type constructor and the generic type's variant.
+//
+// Also check that a type alias to said generic type admits type application
+// on the type constructor but *NOT* the variant.
+
+type Alias<T> = Option<T>;
+
+fn main() {
+ let _ = Option::<u8>::None; // OK
+ let _ = Option::None::<u8>; // OK (Lint in future!)
+ let _ = Alias::<u8>::None; // OK
+ let _ = Alias::None::<u8>; //~ ERROR type arguments are not allowed for this type
+}
--- /dev/null
+error[E0109]: type arguments are not allowed for this type
+ --> $DIR/no-type-application-on-aliased-enum-variant.rs:13:27
+ |
+LL | let _ = Alias::None::<u8>;
+ | ^^ type argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0109`.
--- /dev/null
+// Check that the compiler will resolve `<E>::V` to the variant `V` in the type namespace
+// but will reject this because `enum` variants do not exist in the type namespace.
+
+enum E {
+ V
+}
+
+fn check() -> <E>::V {}
+//~^ ERROR expected type, found variant `V`
+
+fn main() {}
--- /dev/null
+error: expected type, found variant `V`
+ --> $DIR/resolve-to-enum-variant-in-type-namespace-and-error.rs:8:15
+ |
+LL | fn check() -> <E>::V {}
+ | ^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+// Check that it is possible to resolve, in the value namespace,
+// to an `enum` variant through a type alias. This includes `Self`.
+// Type qualified syntax `<Type>::Variant` also works when syntactically valid.
+
+#[derive(Debug, PartialEq, Eq)]
+enum Foo {
+ Bar(i32),
+ Baz { i: i32 },
+ Qux,
+}
+
+type FooAlias = Foo;
+type OptionAlias = Option<i32>;
+
+macro_rules! check_pat {
+ ($x:expr, $p:pat) => {
+ assert!(if let $p = $x { true } else { false });
+ };
+}
+
+impl Foo {
+ fn bar() -> Self {
+ let x = Self::Bar(3);
+ assert_eq!(x, <Self>::Bar(3));
+ check_pat!(x, Self::Bar(3));
+ x
+ }
+
+ fn baz() -> Self {
+ let x = Self::Baz { i: 42 };
+ check_pat!(x, Self::Baz { i: 42 });
+ x
+ }
+
+ fn qux() -> Self {
+ let x = Self::Qux;
+ assert_eq!(x, <Self>::Qux);
+ check_pat!(x, Self::Qux);
+ check_pat!(x, <Self>::Qux);
+ x
+ }
+}
+
+fn main() {
+ let bar = Foo::Bar(1);
+ assert_eq!(bar, FooAlias::Bar(1));
+ assert_eq!(bar, <FooAlias>::Bar(1));
+ check_pat!(bar, FooAlias::Bar(1));
+
+ let baz = FooAlias::Baz { i: 2 };
+ assert_eq!(baz, Foo::Baz { i: 2 });
+ check_pat!(baz, FooAlias::Baz { i: 2 });
+
+ let qux = Foo::Qux;
+ assert_eq!(qux, FooAlias::Qux);
+ assert_eq!(qux, <FooAlias>::Qux);
+ check_pat!(qux, FooAlias::Qux);
+ check_pat!(qux, <FooAlias>::Qux);
+
+ assert_eq!(Foo::bar(), Foo::Bar(3));
+ assert_eq!(Foo::baz(), Foo::Baz { i: 42 });
+ assert_eq!(Foo::qux(), Foo::Qux);
+
+ let some = Option::Some(4);
+ assert_eq!(some, OptionAlias::Some(4));
+ check_pat!(some, OptionAlias::Some(4));
+}
// Test `ignored_generic_bounds` lint warning about bounds in type aliases.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![allow(dead_code)]
use std::rc::Rc;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// rust-lang/rust#55810: types for a binding in a match arm can be
// inferred from arms that come later in the match.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![deny(unused_variables)]
+#![allow(deprecated)]
+
enum Void {}
fn main() {
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/uninhabited-matches-feature-gated.rs:5:19
+ --> $DIR/uninhabited-matches-feature-gated.rs:7:19
|
LL | let _ = match x {
| ^ pattern `Err(_)` not covered
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
- --> $DIR/uninhabited-matches-feature-gated.rs:10:19
+ --> $DIR/uninhabited-matches-feature-gated.rs:12:19
|
LL | let _ = match x {};
| ^
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
- --> $DIR/uninhabited-matches-feature-gated.rs:13:19
+ --> $DIR/uninhabited-matches-feature-gated.rs:15:19
|
LL | let _ = match x {};
| ^
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
- --> $DIR/uninhabited-matches-feature-gated.rs:16:19
+ --> $DIR/uninhabited-matches-feature-gated.rs:18:19
|
LL | let _ = match x {};
| ^
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `&[_]` not covered
- --> $DIR/uninhabited-matches-feature-gated.rs:19:19
+ --> $DIR/uninhabited-matches-feature-gated.rs:21:19
|
LL | let _ = match x {
| ^ pattern `&[_]` not covered
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/uninhabited-matches-feature-gated.rs:27:19
+ --> $DIR/uninhabited-matches-feature-gated.rs:29:19
|
LL | let _ = match x {
| ^ pattern `Err(_)` not covered
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
- --> $DIR/uninhabited-matches-feature-gated.rs:32:9
+ --> $DIR/uninhabited-matches-feature-gated.rs:34:9
|
LL | let Ok(x) = x;
| ^^^^^ pattern `Err(_)` not covered
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(const_fn_union)]
union U {
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(never_type, exhaustive_patterns)]
#![warn(unreachable_code)]
#![warn(unreachable_patterns)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
#![feature(rustc_attrs)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
// `std::ops::Index` has an `: ?Sized` bound on the `Idx` type param. This is
// an accidental left-over from the times when it `Index` was by-reference.
-#![allow(unused_macros)]
+// check-pass
-macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
+macro_rules! macro_rules { () => { struct S; } } // OK
-fn main() {}
+macro_rules! {} // OK, calls the macro defined above
+
+fn main() {
+ let s = S;
+}
+++ /dev/null
-error: user-defined macros may not be named `macro_rules`
- --> $DIR/user-defined-macro-rules.rs:3:1
- |
-LL | macro_rules! macro_rules { () => {} }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
// they permit lifetimes to be approximated as expected.
#![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct SomeStruct<T>(fn(T));
// be shortened.
#![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
struct SomeStruct<T>(T);
} else if config.parse_name_directive(ln, "build-pass") {
check_no_run("build-pass");
Some(PassMode::Build)
- } else if config.parse_name_directive(ln, "compile-pass") /* compatibility */ {
- check_no_run("compile-pass");
- Some(PassMode::Build)
} else if config.parse_name_directive(ln, "run-pass") {
if config.mode != Mode::Ui && config.mode != Mode::RunPass /* compatibility */ {
panic!("`run-pass` header is only supported in UI tests")
-Subproject commit 945f007c0d305c3ec069b5e5d911ef783f6d70e7
+Subproject commit d2df509867fbbbd35730c90aef54a8e73b046cd6
-Subproject commit 597c9be8c75be3e664f189c4325c96cf9b464dc3
+Subproject commit 124483dd2f10fe3ba32f7f5b75f32224c77f9010
-Subproject commit ccdc47b657a7600cbd0c2858eb52a8d712cfce18
+Subproject commit 85958b001dbff8523396809bfa844fc34a7869a8