os: osx
osx_image: xcode8.2
install: &osx_install_sccache >
- travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-apple-darwin &&
+ travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-apple-darwin &&
chmod +x /usr/local/bin/sccache &&
travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
chmod +x /usr/local/bin/stamp
- set PATH=C:\Python27;%PATH%
# Download and install sccache
- - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-pc-windows-msvc
- - mv 2017-04-29-sccache-x86_64-pc-windows-msvc sccache.exe
+ - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-pc-windows-msvc
+ - mv 2017-05-12-sccache-x86_64-pc-windows-msvc sccache.exe
- set PATH=%PATH%;%CD%
# Download and install ninja
// do that we pass a weird flag to the compiler to get it to do
// so. Note that this is definitely a hack, and we should likely
// flesh out rpath support more fully in the future.
+ //
+ // FIXME: remove condition after next stage0
if stage != "0" {
cmd.arg("-Z").arg("osx-rpath-install-name");
}
cmd.arg("-Z").arg("unstable-options");
cmd.arg("-C").arg("target-feature=+crt-static");
}
+
+ // Force all crates compiled by this compiler to (a) be unstable and (b)
+ // allow the `rustc_private` feature to link to other unstable crates
+ // also in the sysroot.
+ //
+ // FIXME: remove condition after next stage0
+ if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
+ if stage != "0" {
+ cmd.arg("-Z").arg("force-unstable-if-unmarked");
+ }
+ }
}
if verbose > 1 {
let table = match p.parse() {
Some(table) => table,
None => {
- println!("failed to parse TOML configuration:");
+ println!("failed to parse TOML configuration '{}':", file.to_str().unwrap());
for err in p.errors.iter() {
let (loline, locol) = p.to_linecol(err.lo);
let (hiline, hicol) = p.to_linecol(err.hi);
[rust]
# Whether or not to optimize the compiler and standard library
+# Note: the slowness of the non optimized compiler compiling itself usually
+# outweighs the time gains in not doing optimizations, therefore a
+# full bootstrap takes much more time with optimize set to false.
#optimize = true
# Number of codegen units to use for each compiler invocation. A value of 0
// compiled with debuginfo.
if mode != Mode::Tool {
cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
- .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string());
+ .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
+ .env("RUSTC_FORCE_UNSTABLE", "1");
}
// Enable usage of unstable features
// the comipiler, libs, and tests are stable and we don't want to make
// their deps unstable (since this would break the first invariant
// above).
- if mode != Mode::Tool {
+ //
+ // FIXME: remove this after next stage0
+ if mode != Mode::Tool && stage == 0 {
cargo.env("RUSTBUILD_UNSTABLE", "1");
}
configure.arg("no-ssl3");
let os = match target {
+ "aarch64-linux-android" => "linux-aarch64",
"aarch64-unknown-linux-gnu" => "linux-aarch64",
+ "arm-linux-androideabi" => "android",
"arm-unknown-linux-gnueabi" => "linux-armv4",
"arm-unknown-linux-gnueabihf" => "linux-armv4",
+ "armv7-linux-androideabi" => "android-armv7",
"armv7-unknown-linux-gnueabihf" => "linux-armv4",
"i686-apple-darwin" => "darwin-i386-cc",
+ "i686-linux-android" => "android-x86",
"i686-unknown-freebsd" => "BSD-x86-elf",
"i686-unknown-linux-gnu" => "linux-elf",
"i686-unknown-linux-musl" => "linux-elf",
"powerpc64le-unknown-linux-gnu" => "linux-ppc64le",
"s390x-unknown-linux-gnu" => "linux64-s390x",
"x86_64-apple-darwin" => "darwin64-x86_64-cc",
+ "x86_64-linux-android" => "linux-x86_64",
"x86_64-unknown-freebsd" => "BSD-x86_64",
"x86_64-unknown-linux-gnu" => "linux-x86_64",
"x86_64-unknown-linux-musl" => "linux-x86_64",
for flag in build.cflags(target) {
configure.arg(flag);
}
+ // There is no specific os target for android aarch64 or x86_64,
+ // so we need to pass some extra cflags
+ if target == "aarch64-linux-android" || target == "x86_64-linux-android" {
+ configure.arg("-mandroid");
+ configure.arg("-fomit-frame-pointer");
+ }
+ // Make PIE binaries
+ // Non-PIE linker support was removed in Lollipop
+ // https://source.android.com/security/enhancements/enhancements50
+ if target == "i686-linux-android" {
+ configure.arg("no-asm");
+ }
configure.current_dir(&obj);
println!("Configuring openssl for {}", target);
build.run_quiet(&mut configure);
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
# Install NDK
RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
rm dumb-init_*.deb
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=i686-unknown-linux-gnu
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
RUN ./build-powerpc64le-toolchain.sh
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV \
ENTRYPOINT ["/rustroot/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV HOSTS=x86_64-unknown-linux-gnu
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV RUST_CONFIGURE_ARGS \
USER root
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
ENV PATH=$PATH:/x-tools/x86_64-unknown-netbsd/bin
lib32stdc++6
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
pkg-config
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
xz-utils
RUN curl -o /usr/local/bin/sccache \
- https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-04-29-sccache-x86_64-unknown-linux-musl && \
+ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \
chmod +x /usr/local/bin/sccache
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
-Subproject commit 11bfb0dcf85f7aa92abd30524bb1e42e18d108c6
+Subproject commit 3288e0659c08fb5006f6d6dd4b5675ed0c2c432a
.env("AR", &ar)
.env("RANLIB", format!("{} s", ar.display()));
- if target.contains("windows") {
- // A bit of history here, this used to be --enable-lazy-lock added in
- // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
- // was also reported to MinGW:
- //
- // http://sourceforge.net/p/mingw-w64/bugs/395/
- //
- // When updating jemalloc to 4.0, however, it was found that binaries
- // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
- // that a thread was unlocking a mutex it never locked. Disabling this
- // "lazy lock" option seems to fix the issue, but it was enabled by
- // default for MinGW targets in 13473c7 for jemalloc.
- //
- // As a result of all that, force disabling lazy lock on Windows, and
- // after reading some code it at least *appears* that the initialization
- // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
- // hopefully...
- //
- // tl;dr: make windows behave like other platforms by disabling lazy
- // locking, but requires passing an option due to a historical
- // default with jemalloc.
- cmd.arg("--disable-lazy-lock");
- } else if target.contains("ios") {
+ if target.contains("ios") {
cmd.arg("--disable-tls");
} else if target.contains("android") {
// We force android to have prefixed symbols because apparently
//! objects of a single type.
#![crate_name = "arena"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(generic_param_attrs)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]
#![allow(deprecated)]
#[unstable(feature = "fused", issue = "35602")]
impl<'a> FusedIterator for EncodeUtf16<'a> {}
-// Return the initial codepoint accumulator for the first byte.
-// The first byte is special, only want bottom 5 bits for width 2, 4 bits
-// for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte {
- ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-}
-
-// return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte {
- ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63) as u32)
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<str> for String {
#[inline]
/// // exactly wouldn't be possible without executing filter().
/// assert_eq!((0, Some(10)), iter.size_hint());
///
- /// // Let's add one five more numbers with chain()
+ /// // Let's add five more numbers with chain()
/// let iter = (0..10).filter(|x| x % 2 == 0).chain(15..20);
///
/// // now both bounds are increased by five
#[macro_use]
mod internal_macros;
-#[path = "num/float_macros.rs"]
-#[macro_use]
-mod float_macros;
-
#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![doc(hidden)]
-
-macro_rules! assert_approx_eq {
- ($a:expr, $b:expr) => ({
- use num::Float;
- let (a, b) = (&$a, &$b);
- assert!((*a - *b).abs() < 1.0e-6,
- "{} is not approximately equal to {}", *a, *b);
- })
-}
pub mod bignum;
pub mod diy_float;
-macro_rules! checked_op {
- ($U:ty, $op:path, $x:expr, $y:expr) => {{
- let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
- if overflowed { None } else { Some(result as Self) }
- }}
-}
-
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr,
/// }
/// ```
///
+/// Here is an example of the same `Point` struct implementing the `Add` trait
+/// using generics.
+///
+/// ```
+/// use std::ops::Add;
+///
+/// #[derive(Debug)]
+/// struct Point<T> {
+/// x: T,
+/// y: T,
+/// }
+///
+/// // Notice that the implementation uses the `Output` associated type
+/// impl<T: Add<Output=T>> Add for Point<T> {
+/// type Output = Point<T>;
+///
+/// fn add(self, other: Point<T>) -> Point<T> {
+/// Point {
+/// x: self.x + other.x,
+/// y: self.y + other.y,
+/// }
+/// }
+/// }
+///
+/// impl<T: PartialEq> PartialEq for Point<T> {
+/// fn eq(&self, other: &Self) -> bool {
+/// self.x == other.x && self.y == other.y
+/// }
+/// }
+///
+/// fn main() {
+/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
+/// Point { x: 3, y: 3 });
+/// }
+/// ```
+///
/// Note that `RHS = Self` by default, but this is not mandatory. For example,
/// [std::time::SystemTime] implements `Add<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime + Duration`.
/// invalid pointers, types, and double drops.
#[stable(feature = "drop_in_place", since = "1.8.0")]
#[lang="drop_in_place"]
-#[inline]
#[allow(unconditional_recursion)]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
// Code here does not matter - this is replaced by the
//! [mz]: https://code.google.com/p/miniz/
#![crate_name = "flate"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(libc)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![feature(unique)]
#![cfg_attr(test, feature(rand))]
//! generated instead.
#![crate_name = "fmt_macros"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
test(attr(deny(warnings))))]
#![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![feature(unicode)]
pub use self::Piece::*;
//! ```
#![crate_name = "getopts"]
-#![unstable(feature = "rustc_private",
+#![cfg_attr(stage0, unstable(feature = "rustc_private",
reason = "use the crates.io `getopts` library instead",
- issue = "27812")]
+ issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(missing_docs)]
#![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
use self::Name::*;
use self::HasArg::*;
//! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
#![crate_name = "graphviz"]
-#![unstable(feature = "rustc_private", issue = "27812")]
-#![feature(staged_api)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
//! }
//! ```
#![crate_name = "proc_macro_plugin"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![feature(plugin_registrar)]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
+#![cfg_attr(stage0, feature(rustc_private))]
extern crate rustc_plugin;
extern crate syntax;
use rustc_data_structures::graph;
use cfg::*;
+use middle::region::CodeExtent;
use ty::{self, TyCtxt};
use syntax::ast;
use syntax::ptr::P;
scope_id: ast::NodeId,
to_index: CFGIndex) {
let mut data = CFGEdgeData { exiting_scopes: vec![] };
- let mut scope = self.tcx.node_extent(from_expr.id);
- let target_scope = self.tcx.node_extent(scope_id);
+ let mut scope = CodeExtent::Misc(from_expr.id);
+ let target_scope = CodeExtent::Misc(scope_id);
let region_maps = self.tcx.region_maps(self.owner_def_id);
while scope != target_scope {
data.exiting_scopes.push(scope.node_id());
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::RegionKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
db.depth.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);
}
- ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
+ ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
+ def_id.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
Free(call_site_scope_data, decl)
});
-impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
- fn_id,
- body_id
-});
-
impl_stable_hash_for!(struct ty::DebruijnIndex {
depth
});
FnPtrAddrCast
});
-impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
{
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
hasher: &mut StableHasher<W>) {
- use middle::region::CodeExtentData;
+ use middle::region::CodeExtent;
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
- CodeExtentData::Misc(node_id) |
- CodeExtentData::DestructionScope(node_id) => {
+ CodeExtent::Misc(node_id) |
+ CodeExtent::DestructionScope(node_id) => {
node_id.hash_stable(hcx, hasher);
}
- CodeExtentData::CallSiteScope { fn_id, body_id } |
- CodeExtentData::ParameterScope { fn_id, body_id } => {
- fn_id.hash_stable(hcx, hasher);
+ CodeExtent::CallSiteScope(body_id) |
+ CodeExtent::ParameterScope(body_id) => {
body_id.hash_stable(hcx, hasher);
}
- CodeExtentData::Remainder(block_remainder) => {
+ CodeExtent::Remainder(block_remainder) => {
block_remainder.hash_stable(hcx, hasher);
}
}
custom_kind
});
-impl_stable_hash_for!(struct ty::FreeRegion<'tcx> {
+impl_stable_hash_for!(struct ty::FreeRegion {
scope,
bound_region
});
return Ok(r);
}
- // Early-bound regions should really have been substituted away before
- // we get to this point.
- ty::ReEarlyBound(..) => {
- span_bug!(
- self.span,
- "Encountered early bound region when generalizing: {:?}",
- r);
- }
-
// Always make a fresh region variable for skolemized regions;
// the higher-ranked decision procedures rely on this.
ty::ReSkolemized(..) => { }
ty::ReStatic |
ty::ReScope(..) |
ty::ReVar(..) |
+ ty::ReEarlyBound(..) |
ty::ReFree(..) => {
match self.ambient_variance {
ty::Invariant => return Ok(r),
return;
}
};
- let scope_decorated_tag = match *scope {
- region::CodeExtentData::Misc(_) => tag,
- region::CodeExtentData::CallSiteScope { .. } => {
+ let scope_decorated_tag = match scope {
+ region::CodeExtent::Misc(_) => tag,
+ region::CodeExtent::CallSiteScope(_) => {
"scope of call-site for function"
}
- region::CodeExtentData::ParameterScope { .. } => {
+ region::CodeExtent::ParameterScope(_) => {
"scope of function body"
}
- region::CodeExtentData::DestructionScope(_) => {
+ region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
&new_string[..]
}
- region::CodeExtentData::Remainder(r) => {
+ region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
r.first_statement_index);
&new_string[..]
explain_span(self, scope_decorated_tag, span)
}
- ty::ReFree(ref fr) => {
- let prefix = match fr.bound_region {
- ty::BrAnon(idx) => {
- format!("the anonymous lifetime #{} defined on", idx + 1)
+ ty::ReEarlyBound(_) |
+ ty::ReFree(_) => {
+ let scope = match *region {
+ ty::ReEarlyBound(ref br) => {
+ self.parent_def_id(br.def_id).unwrap()
}
- ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
- _ => {
- format!("the lifetime {} as defined on",
- fr.bound_region)
+ ty::ReFree(ref fr) => fr.scope,
+ _ => bug!()
+ };
+ let prefix = match *region {
+ ty::ReEarlyBound(ref br) => {
+ format!("the lifetime {} as defined on", br.name)
+ }
+ ty::ReFree(ref fr) => {
+ match fr.bound_region {
+ ty::BrAnon(idx) => {
+ format!("the anonymous lifetime #{} defined on", idx + 1)
+ }
+ ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
+ _ => {
+ format!("the lifetime {} as defined on",
+ fr.bound_region)
+ }
+ }
}
+ _ => bug!()
};
- let node = fr.scope.map(|s| s.node_id())
+ let node = self.hir.as_local_node_id(scope)
.unwrap_or(DUMMY_NODE_ID);
let unknown;
let tag = match self.hir.find(node) {
Some(_) => {
unknown = format!("unexpected node ({}) for scope {:?}. \
Please report a bug.",
- self.hir.node_to_string(node), fr.scope);
+ self.hir.node_to_string(node), scope);
&unknown
}
None => {
unknown = format!("unknown node for scope {:?}. \
- Please report a bug.", fr.scope);
+ Please report a bug.", scope);
&unknown
}
};
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
- ty::ReEarlyBound(ref data) => (data.name.to_string(), None),
-
// FIXME(#13998) ReSkolemized should probably print like
// ReFree rather than dumping Debug output on the user.
//
}
let mut err = match *sub {
+ ty::ReEarlyBound(_) |
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(self.tcx.sess,
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReEarlyBound(..) |
ty::ReLateBound(..) => {
// leave bound regions alone
r
}
ty::ReStatic |
+ ty::ReEarlyBound(..) |
ty::ReFree(_) |
ty::ReScope(_) |
ty::ReVar(_) |
-> ty::Region<'tcx> {
// Regions that pre-dated the LUB computation stay as they are.
if !is_var_in_set(new_vars, r0) {
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
debug!("generalize_region(r0={:?}): not new variable", r0);
return r0;
}
debug!("generalize_region(r0={:?}): \
non-new-variables found in {:?}",
r0, tainted);
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
return r0;
}
r0: ty::Region<'tcx>)
-> ty::Region<'tcx> {
if !is_var_in_set(new_vars, r0) {
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
return r0;
}
return rev_lookup(infcx, span, a_map, a_r.unwrap());
} else if a_r.is_none() && b_r.is_none() {
// Not related to bound variables from either fn:
- assert!(!r0.is_bound());
+ assert!(!r0.is_late_bound());
return r0;
} else {
// Other:
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
Option<ty::ParameterEnvironment<'tcx>>) {
- let item_id = tcx.hir.body_owner(self);
- (Some(tcx.typeck_tables_of(tcx.hir.local_def_id(item_id))),
+ let def_id = tcx.hir.body_owner_def_id(self);
+ (Some(tcx.typeck_tables_of(def_id)),
None,
- Some(ty::ParameterEnvironment::for_item(tcx, item_id)))
+ Some(tcx.parameter_environment(def_id)))
}
}
}
pub fn add_given(&self,
- sub: ty::FreeRegion<'tcx>,
+ sub: ty::Region<'tcx>,
sup: ty::RegionVid)
{
self.region_vars.add_given(sub, sup);
pub fn resolve_regions_and_report_errors(&self,
region_context: DefId,
- region_map: &RegionMaps<'tcx>,
+ region_map: &RegionMaps,
free_regions: &FreeRegionMap<'tcx>) {
let region_rels = RegionRelations::new(self.tcx,
region_context,
graph_name: String,
region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
- node_ids: FxHashMap<Node<'tcx>, usize>,
+ node_ids: FxHashMap<Node, usize>,
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
-enum Node<'tcx> {
+enum Node {
RegionVid(ty::RegionVid),
- Region(ty::RegionKind<'tcx>),
+ Region(ty::RegionKind),
}
// type Edge = Constraint;
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
Constraint(Constraint<'tcx>),
- EnclScope(CodeExtent<'tcx>, CodeExtent<'tcx>),
+ EnclScope(CodeExtent, CodeExtent),
}
impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
}
impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
- type Node = Node<'tcx>;
+ type Node = Node;
type Edge = Edge<'tcx>;
fn graph_id(&self) -> dot::Id {
dot::Id::new(&*self.graph_name).unwrap()
}
}
-fn constraint_to_nodes<'tcx>(c: &Constraint<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
match *c {
Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
(Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
}
}
-fn edge_to_nodes<'tcx>(e: &Edge<'tcx>) -> (Node<'tcx>, Node<'tcx>) {
+fn edge_to_nodes(e: &Edge) -> (Node, Node) {
match *e {
Edge::Constraint(ref c) => constraint_to_nodes(c),
Edge::EnclScope(sub, sup) => {
}
impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
- type Node = Node<'tcx>;
+ type Node = Node;
type Edge = Edge<'tcx>;
- fn nodes(&self) -> dot::Nodes<Node<'tcx>> {
+ fn nodes(&self) -> dot::Nodes<Node> {
let mut set = FxHashSet();
for node in self.node_ids.keys() {
set.insert(*node);
debug!("region graph has {} edges", v.len());
Cow::Owned(v)
}
- fn source(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+ fn source(&self, edge: &Edge<'tcx>) -> Node {
let (n1, _) = edge_to_nodes(edge);
debug!("edge {:?} has source {:?}", edge, n1);
n1
}
- fn target(&self, edge: &Edge<'tcx>) -> Node<'tcx> {
+ fn target(&self, edge: &Edge<'tcx>) -> Node {
let (_, n2) = edge_to_nodes(edge);
debug!("edge {:?} has target {:?}", edge, n2);
n2
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
use std::cell::{Cell, RefCell};
-use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::fmt;
use std::mem;
use std::u32;
AddVerify(usize),
/// We added the given `given`
- AddGiven(ty::FreeRegion<'tcx>, ty::RegionVid),
+ AddGiven(Region<'tcx>, ty::RegionVid),
/// We added a GLB/LUB "combinaton variable"
AddCombination(CombineMapType, TwoRegions<'tcx>),
// record the fact that `'a <= 'b` is implied by the fn signature,
// and then ignore the constraint when solving equations. This is
// a bit of a hack but seems to work.
- givens: RefCell<FxHashSet<(ty::FreeRegion<'tcx>, ty::RegionVid)>>,
+ givens: RefCell<FxHashSet<(Region<'tcx>, ty::RegionVid)>>,
lubs: RefCell<CombineMap<'tcx>>,
glbs: RefCell<CombineMap<'tcx>>,
self.add_edge(a, b);
}
&AddGiven(a, b) => {
- self.add_edge(tcx.mk_region(ReFree(a)),
- tcx.mk_region(ReVar(b)));
+ self.add_edge(a, tcx.mk_region(ReVar(b)));
}
&AddVerify(i) => {
verifys[i].bound.for_each_region(&mut |b| {
}
}
- pub fn add_given(&self, sub: ty::FreeRegion<'tcx>, sup: ty::RegionVid) {
+ pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
// cannot add givens once regions are resolved
assert!(self.values_are_none());
origin);
match (sub, sup) {
- (&ReEarlyBound(..), _) |
(&ReLateBound(..), _) |
- (_, &ReEarlyBound(..)) |
(_, &ReLateBound(..)) => {
span_bug!(origin.span(),
"cannot relate bound region: {:?} <= {:?}",
match (a, b) {
(&ReLateBound(..), _) |
(_, &ReLateBound(..)) |
- (&ReEarlyBound(..), _) |
- (_, &ReEarlyBound(..)) |
(&ReErased, _) |
(_, &ReErased) => {
bug!("cannot relate region: LUB({:?}, {:?})", a, b);
b);
}
- (&ReFree(fr), &ReScope(s_id)) |
- (&ReScope(s_id), &ReFree(fr)) => {
+ (&ReEarlyBound(_), &ReScope(s_id)) |
+ (&ReScope(s_id), &ReEarlyBound(_)) |
+ (&ReFree(_), &ReScope(s_id)) |
+ (&ReScope(s_id), &ReFree(_)) => {
// A "free" region can be interpreted as "some region
- // at least as big as the block fr.scope_id". So, we can
+ // at least as big as fr.scope". So, we can
// reasonably compare free regions and scopes:
- if let Some(fr_scope) = fr.scope {
- let r_id = region_rels.region_maps.nearest_common_ancestor(fr_scope, s_id);
- if r_id == fr_scope {
- // if the free region's scope `fr.scope_id` is bigger than
- // the scope region `s_id`, then the LUB is the free
- // region itself:
- return self.tcx.mk_region(ReFree(fr));
+ let fr_scope = match (a, b) {
+ (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
+ region_rels.region_maps.early_free_extent(self.tcx, br)
+ }
+ (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
+ region_rels.region_maps.free_extent(self.tcx, fr)
+ }
+ _ => bug!()
+ };
+ let r_id = region_rels.region_maps.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
+ // region itself:
+ match (a, b) {
+ (_, &ReScope(_)) => return a,
+ (&ReScope(_), _) => return b,
+ _ => bug!()
}
}
self.tcx.mk_region(ReScope(lub))
}
+ (&ReEarlyBound(_), &ReEarlyBound(_)) |
+ (&ReFree(_), &ReEarlyBound(_)) |
+ (&ReEarlyBound(_), &ReFree(_)) |
(&ReFree(_), &ReFree(_)) => {
region_rels.lub_free_regions(a, b)
}
let mut givens = self.givens.borrow_mut();
let seeds: Vec<_> = givens.iter().cloned().collect();
- for (fr, vid) in seeds {
+ for (r, vid) in seeds {
let seed_index = NodeIndex(vid.index as usize);
for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
let succ_index = succ_index.0 as u32;
if succ_index < self.num_vars() {
let succ_vid = RegionVid { index: succ_index };
- givens.insert((fr, succ_vid));
+ givens.insert((r, succ_vid));
}
}
}
// Check if this relationship is implied by a given.
match *a_region {
- ty::ReFree(fr) => {
- if self.givens.borrow().contains(&(fr, b_vid)) {
+ ty::ReEarlyBound(_) |
+ ty::ReFree(_) => {
+ if self.givens.borrow().contains(&(a_region, b_vid)) {
debug!("given");
return false;
}
// We place free regions first because we are special casing
// SubSupConflict(ReFree, ReFree) when reporting error, and so
// the user will more likely get a specific suggestion.
- fn free_regions_first(a: &RegionAndOrigin, b: &RegionAndOrigin) -> Ordering {
- match (a.region, b.region) {
- (&ReFree(..), &ReFree(..)) => Equal,
- (&ReFree(..), _) => Less,
- (_, &ReFree(..)) => Greater,
- (..) => Equal,
+ fn region_order_key(x: &RegionAndOrigin) -> u8 {
+ match *x.region {
+ ReEarlyBound(_) => 0,
+ ReFree(_) => 1,
+ _ => 2
}
}
- lower_bounds.sort_by(|a, b| free_regions_first(a, b));
- upper_bounds.sort_by(|a, b| free_regions_first(a, b));
+ lower_bounds.sort_by_key(region_order_key);
+ upper_bounds.sort_by_key(region_order_key);
for lower_bound in &lower_bounds {
for upper_bound in &upper_bounds {
//! This API is completely unstable and subject to change.
#![crate_name = "rustc"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(nonzero)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(specialization)]
-#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(discriminant_value)]
#![feature(sort_unstable)]
#![feature(trace_macros)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#![recursion_limit="128"]
extern crate arena;
run_lints!(self, check_ident, early_passes, sp, id);
}
- fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, n: ast::NodeId) {
+ fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
run_lints!(self, check_mod, early_passes, m, s, n);
ast_visit::walk_mod(self, m);
run_lints!(self, check_mod_post, early_passes, m, s, n);
fn export_macros(&self, cnum: CrateNum);
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
- fn is_staged_api(&self, cnum: CrateNum) -> bool;
fn is_allocator(&self, cnum: CrateNum) -> bool;
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
{ bug!("lang_items") }
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>
{ bug!("missing_lang_items") }
- fn is_staged_api(&self, cnum: CrateNum) -> bool { bug!("is_staged_api") }
fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
-> Self
{
pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
options: mc::MemCategorizationOptions)
-> Self
{
pub context: DefId,
/// region maps for the given context
- pub region_maps: &'a RegionMaps<'tcx>,
+ pub region_maps: &'a RegionMaps,
/// free-region relationships
pub free_regions: &'a FreeRegionMap<'tcx>,
pub fn new(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
context: DefId,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
free_regions: &'a FreeRegionMap<'tcx>,
) -> Self {
Self {
(&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
self.region_maps.is_subscope_of(sub_scope, super_scope),
- (&ty::ReScope(sub_scope), &ty::ReFree(fr)) => {
- // 1. It is safe to unwrap `fr.scope` because we
- // should only ever wind up comparing against
- // `ReScope` in the context of a method or
- // body, where `fr.scope` should be `Some`.
- self.region_maps.is_subscope_of(sub_scope, fr.scope.unwrap() /*1*/) ||
- self.is_static(super_region)
+ (&ty::ReScope(sub_scope), &ty::ReEarlyBound(ref br)) => {
+ let fr_scope = self.region_maps.early_free_extent(self.tcx, br);
+ self.region_maps.is_subscope_of(sub_scope, fr_scope)
}
- (&ty::ReFree(_), &ty::ReFree(_)) =>
- self.free_regions.relation.contains(&sub_region, &super_region) ||
- self.is_static(super_region),
+ (&ty::ReScope(sub_scope), &ty::ReFree(ref fr)) => {
+ let fr_scope = self.region_maps.free_extent(self.tcx, fr);
+ self.region_maps.is_subscope_of(sub_scope, fr_scope)
+ }
- (&ty::ReStatic, &ty::ReFree(_)) =>
- self.is_static(super_region),
+ (&ty::ReEarlyBound(_), &ty::ReEarlyBound(_)) |
+ (&ty::ReFree(_), &ty::ReEarlyBound(_)) |
+ (&ty::ReEarlyBound(_), &ty::ReFree(_)) |
+ (&ty::ReFree(_), &ty::ReFree(_)) =>
+ self.free_regions.relation.contains(&sub_region, &super_region),
_ =>
false,
}
};
+ let result = result || self.is_static(super_region);
debug!("is_subregion_of(sub_region={:?}, super_region={:?}) = {:?}",
sub_region, super_region, result);
result
debug!("is_static(super_region={:?})", super_region);
match *super_region {
ty::ReStatic => true,
- ty::ReFree(_) => {
+ ty::ReEarlyBound(_) | ty::ReFree(_) => {
let re_static = self.tcx.mk_region(ty::ReStatic);
self.free_regions.relation.contains(&re_static, &super_region)
}
- _ => bug!("only free regions should be given to `is_static`")
+ _ => false
}
}
for implied_bound in implied_bounds {
debug!("implied bound: {:?}", implied_bound);
match *implied_bound {
- ImpliedBound::RegionSubRegion(a @ &ty::ReFree(_), b @ &ty::ReFree(_)) |
- ImpliedBound::RegionSubRegion(a @ &ty::ReStatic, b @ &ty::ReFree(_)) => {
+ ImpliedBound::RegionSubRegion(a, b) => {
self.relate_regions(a, b);
}
- ImpliedBound::RegionSubRegion(..) |
ImpliedBound::RegionSubParam(..) |
ImpliedBound::RegionSubProjection(..) => {
}
// No region bounds here
}
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
- match (r_a, r_b) {
- // `'static: 'x` is not notable
- (&ty::ReStatic, &ty::ReFree(_)) => {},
-
- (&ty::ReFree(_), &ty::ReStatic) |
- (&ty::ReFree(_), &ty::ReFree(_)) => {
- // Record that `'a:'b`. Or, put another way, `'b <= 'a`.
- self.relate_regions(r_b, r_a);
- }
-
- _ => {
- // All named regions are instantiated with free regions.
- bug!("record_region_bounds: non free region: {:?} / {:?}",
- r_a,
- r_b);
- }
- }
+ self.relate_regions(r_b, r_a);
}
}
}
}
+ // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
+ // (with the exception that `'static: 'x` is not notable)
fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
- assert!(match *sub { ty::ReFree(_) | ty::ReStatic => true, _ => false });
- assert!(match *sup { ty::ReFree(_) | ty::ReStatic => true, _ => false });
- self.relation.add(sub, sup)
+ if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) {
+ self.relation.add(sub, sup)
+ }
}
pub fn lub_free_regions<'a, 'gcx>(&self,
r_a: Region<'tcx>,
r_b: Region<'tcx>)
-> Region<'tcx> {
- assert!(match *r_a { ty::ReFree(_) => true, _ => false });
- assert!(match *r_b { ty::ReFree(_) => true, _ => false });
+ assert!(is_free(r_a));
+ assert!(is_free(r_b));
let result = if r_a == r_b { r_a } else {
match self.relation.postdom_upper_bound(&r_a, &r_b) {
None => tcx.mk_region(ty::ReStatic),
}
}
+fn is_free(r: Region) -> bool {
+ match *r {
+ ty::ReEarlyBound(_) | ty::ReFree(_) => true,
+ _ => false
+ }
+}
+
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
relation
});
//!
//! - `fallthrough_ln`: a live node that represents a fallthrough
//!
-//! - `no_ret_var`: a synthetic variable that is only 'read' from, the
-//! fallthrough node. This allows us to detect functions where we fail
-//! to return explicitly.
//! - `clean_exit_var`: a synthetic variable that is only 'read' from the
//! fallthrough node. It is only live if the function could converge
//! via means other than an explicit `return` expression. That is, it is
use self::VarKind::*;
use hir::def::*;
-use ty::{self, TyCtxt, ParameterEnvironment};
-use traits::{self, Reveal};
-use ty::subst::Subst;
+use ty::{self, TyCtxt};
use lint;
use util::nodemap::NodeMap;
enum VarKind {
Arg(NodeId, ast::Name),
Local(LocalInfo),
- ImplicitRet,
CleanExit
}
Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => {
self.variable_map.insert(node_id, v);
},
- ImplicitRet | CleanExit => {}
+ CleanExit => {}
}
debug!("{:?} is {:?}", v, vk);
Local(LocalInfo { name, .. }) | Arg(_, name) => {
name.to_string()
},
- ImplicitRet => "<implicit-ret>".to_string(),
CleanExit => "<clean-exit>".to_string()
}
}
// check for various error conditions
lsets.visit_body(body);
- lsets.check_ret(id, sp, entry_ln, body);
lsets.warn_about_unused_args(body, entry_ln);
}
struct Specials {
exit_ln: LiveNode,
fallthrough_ln: LiveNode,
- no_ret_var: Variable,
clean_exit_var: Variable
}
let specials = Specials {
exit_ln: ir.add_live_node(ExitNode),
fallthrough_ln: ir.add_live_node(ExitNode),
- no_ret_var: ir.add_variable(ImplicitRet),
clean_exit_var: ir.add_variable(CleanExit)
};
}
impl<'a, 'tcx> Liveness<'a, 'tcx> {
- fn check_ret(&self,
- id: NodeId,
- sp: Span,
- entry_ln: LiveNode,
- body: &hir::Body)
- {
- let fn_ty = self.ir.tcx.type_of(self.ir.tcx.hir.local_def_id(id));
- let fn_sig = match fn_ty.sty {
- ty::TyClosure(closure_def_id, substs) => {
- self.ir.tcx.closure_type(closure_def_id)
- .subst(self.ir.tcx, substs.substs)
- }
- _ => fn_ty.fn_sig()
- };
-
- let fn_ret = fn_sig.output();
-
- // within the fn body, late-bound regions are liberated
- // and must outlive the *call-site* of the function.
- let fn_ret =
- self.ir.tcx.liberate_late_bound_regions(
- Some(self.ir.tcx.call_site_extent(id, body.value.id)),
- &fn_ret);
-
- if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
- let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
- let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs);
- let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| {
- let cause = traits::ObligationCause::dummy();
- traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil()
- });
-
- // for nil return types, it is ok to not return a value expl.
- if !is_nil {
- span_bug!(sp, "not all control paths return a value");
- }
- }
- }
-
fn check_lvalue(&mut self, expr: &'tcx Expr) {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
#[derive(Clone)]
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub region_maps: &'a RegionMaps<'tcx>,
+ pub region_maps: &'a RegionMaps,
options: MemCategorizationOptions,
}
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
/// Context should be the `DefId` we use to fetch region-maps.
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>)
+ region_maps: &'a RegionMaps)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext::with_options(infcx,
region_maps,
}
pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
options: MemCategorizationOptions)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext {
cmt_result: cmt_<'tcx>)
-> cmt_<'tcx>
{
- // Look up the node ID of the closure body so we can construct
- // a free region within it
- let fn_body_id = {
- let fn_expr = match self.tcx().hir.find(upvar_id.closure_expr_id) {
- Some(hir_map::NodeExpr(e)) => e,
- _ => bug!()
- };
-
- match fn_expr.node {
- hir::ExprClosure(.., body_id, _) => body_id,
- _ => bug!()
- }
- };
-
// Region of environment pointer
let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion {
// The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the
// closure itself.
- scope: Some(self.tcx().item_extent(fn_body_id.node_id)),
+ scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id),
bound_region: ty::BrEnv
}));
pub fn temporary_scope(&self, id: ast::NodeId) -> (ty::Region<'tcx>, ty::Region<'tcx>)
{
let (scope, old_scope) =
- self.region_maps.old_and_new_temporary_scope(self.tcx(), id);
+ self.region_maps.old_and_new_temporary_scope(id);
(self.tcx().mk_region(match scope {
Some(scope) => ty::ReScope(scope),
None => ty::ReStatic
use std::mem;
use std::rc::Rc;
-use serialize;
use syntax::codemap;
use syntax::ast;
use syntax_pos::Span;
use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
use mir::transform::MirSource;
-pub type CodeExtent<'tcx> = &'tcx CodeExtentData;
-
-impl<'tcx> serialize::UseSpecializedEncodable for CodeExtent<'tcx> {}
-impl<'tcx> serialize::UseSpecializedDecodable for CodeExtent<'tcx> {}
-
/// CodeExtent represents a statically-describable extent that can be
/// used to bound the lifetime/region for values.
///
/// actually attach a more meaningful ordering to scopes than the one
/// generated via deriving here.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
-pub enum CodeExtentData {
+pub enum CodeExtent {
Misc(ast::NodeId),
// extent of the call-site for a function or closure (outlives
// the parameters as well as the body).
- CallSiteScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+ CallSiteScope(hir::BodyId),
// extent of parameters passed to a function or closure (they
// outlive its body)
- ParameterScope { fn_id: ast::NodeId, body_id: ast::NodeId },
+ ParameterScope(hir::BodyId),
// extent of destructors for temporaries of node-id
DestructionScope(ast::NodeId),
Remainder(BlockRemainder)
}
-/// extent of call-site for a function/method.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
- RustcDecodable, Debug, Copy)]
-pub struct CallSiteScopeData {
- pub fn_id: ast::NodeId, pub body_id: ast::NodeId,
-}
-
-impl CallSiteScopeData {
- pub fn to_code_extent<'a, 'tcx, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CodeExtent<'tcx> {
- tcx.intern_code_extent(
- match *self {
- CallSiteScopeData { fn_id, body_id } =>
- CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id },
- })
- }
-}
-
/// Represents a subscope of `block` for a binding that is introduced
/// by `block.stmts[first_statement_index]`. Such subscopes represent
/// a suffix of the block. Note that each subscope does not include
/// * the subscope with `first_statement_index == 0` is scope of both
/// `a` and `b`; it does not include EXPR_1, but does include
/// everything after that first `let`. (If you want a scope that
-/// includes EXPR_1 as well, then do not use `CodeExtentData::Remainder`,
+/// includes EXPR_1 as well, then do not use `CodeExtent::Remainder`,
/// but instead another `CodeExtent` that encompasses the whole block,
-/// e.g. `CodeExtentData::Misc`.
+/// e.g. `CodeExtent::Misc`.
///
/// * the subscope with `first_statement_index == 1` is scope of `c`,
/// and thus does not include EXPR_2, but covers the `...`.
pub first_statement_index: u32,
}
-impl CodeExtentData {
+impl CodeExtent {
/// Returns a node id associated with this scope.
///
/// NB: likely to be replaced as API is refined; e.g. pnkfelix
/// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
pub fn node_id(&self) -> ast::NodeId {
match *self {
- CodeExtentData::Misc(node_id) => node_id,
+ CodeExtent::Misc(node_id) => node_id,
// These cases all return rough approximations to the
// precise extent denoted by `self`.
- CodeExtentData::Remainder(br) => br.block,
- CodeExtentData::DestructionScope(node_id) => node_id,
- CodeExtentData::CallSiteScope { fn_id: _, body_id } |
- CodeExtentData::ParameterScope { fn_id: _, body_id } => body_id,
+ CodeExtent::Remainder(br) => br.block,
+ CodeExtent::DestructionScope(node_id) => node_id,
+ CodeExtent::CallSiteScope(body_id) |
+ CodeExtent::ParameterScope(body_id) => body_id.node_id,
}
}
match hir_map.find(self.node_id()) {
Some(hir_map::NodeBlock(ref blk)) => {
match *self {
- CodeExtentData::CallSiteScope { .. } |
- CodeExtentData::ParameterScope { .. } |
- CodeExtentData::Misc(_) |
- CodeExtentData::DestructionScope(_) => Some(blk.span),
+ CodeExtent::CallSiteScope(_) |
+ CodeExtent::ParameterScope(_) |
+ CodeExtent::Misc(_) |
+ CodeExtent::DestructionScope(_) => Some(blk.span),
- CodeExtentData::Remainder(r) => {
+ CodeExtent::Remainder(r) => {
assert_eq!(r.block, blk.id);
// Want span for extent starting after the
// indexed statement and ending at end of
}
/// The region maps encode information about region relationships.
-pub struct RegionMaps<'tcx> {
+pub struct RegionMaps {
+ /// If not empty, this body is the root of this region hierarchy.
+ root_body: Option<hir::BodyId>,
+
+ /// The parent of the root body owner, if the latter is an
+ /// an associated const or method, as impls/traits can also
+ /// have lifetime parameters free in this body.
+ root_parent: Option<ast::NodeId>,
+
/// `scope_map` maps from a scope id to the enclosing scope id;
/// this is usually corresponding to the lexical nesting, though
/// in the case of closures the parent scope is the innermost
/// conditional expression or repeating block. (Note that the
/// enclosing scope id for the block associated with a closure is
/// the closure itself.)
- scope_map: FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
+ scope_map: FxHashMap<CodeExtent, CodeExtent>,
/// `var_map` maps from a variable or binding id to the block in
/// which that variable is declared.
- var_map: NodeMap<CodeExtent<'tcx>>,
+ var_map: NodeMap<CodeExtent>,
/// maps from a node-id to the associated destruction scope (if any)
- destruction_scopes: NodeMap<CodeExtent<'tcx>>,
+ destruction_scopes: NodeMap<CodeExtent>,
/// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
/// larger than the default. The map goes from the expression id
/// table, the appropriate cleanup scope is the innermost
/// enclosing statement, conditional expression, or repeating
/// block (see `terminating_scopes`).
- rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+ rvalue_scopes: NodeMap<CodeExtent>,
/// Records the value of rvalue scopes before they were shrunk by
/// #36082, for error reporting.
///
/// FIXME: this should be temporary. Remove this by 1.18.0 or
/// so.
- shrunk_rvalue_scopes: NodeMap<CodeExtent<'tcx>>,
+ shrunk_rvalue_scopes: NodeMap<CodeExtent>,
/// Encodes the hierarchy of fn bodies. Every fn body (including
/// closures) forms its own distinct region hierarchy, rooted in
}
#[derive(Debug, Copy, Clone)]
-pub struct Context<'tcx> {
+pub struct Context {
/// the root of the current region tree. This is typically the id
/// of the innermost fn body. Each fn forms its own disjoint tree
/// in the region hierarchy. These fn bodies are themselves
root_id: Option<ast::NodeId>,
/// the scope that contains any new variables declared
- var_parent: Option<CodeExtent<'tcx>>,
+ var_parent: Option<CodeExtent>,
/// region parent of expressions etc
- parent: Option<CodeExtent<'tcx>>,
+ parent: Option<CodeExtent>,
}
struct RegionResolutionVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Generated maps:
- region_maps: &'a mut RegionMaps<'tcx>,
-
- cx: Context<'tcx>,
+ region_maps: RegionMaps,
- map: &'a hir_map::Map<'tcx>,
+ cx: Context,
/// `terminating_scopes` is a set containing the ids of each
/// statement, or conditional/repeating expression. These scopes
}
-impl<'tcx> RegionMaps<'tcx> {
+impl<'tcx> RegionMaps {
pub fn new() -> Self {
RegionMaps {
+ root_body: None,
+ root_parent: None,
scope_map: FxHashMap(),
destruction_scopes: FxHashMap(),
var_map: NodeMap(),
}
pub fn record_code_extent(&mut self,
- child: CodeExtent<'tcx>,
- parent: Option<CodeExtent<'tcx>>) {
+ child: CodeExtent,
+ parent: Option<CodeExtent>) {
debug!("{:?}.parent = {:?}", child, parent);
if let Some(p) = parent {
}
// record the destruction scopes for later so we can query them
- if let &CodeExtentData::DestructionScope(n) = child {
+ if let CodeExtent::DestructionScope(n) = child {
self.destruction_scopes.insert(n, child);
}
}
- pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent<'tcx>, CodeExtent<'tcx>) {
+ pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(CodeExtent, CodeExtent) {
for (&child, &parent) in &self.scope_map {
e(child, parent)
}
}
- pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent<'tcx>) {
- for (child, parent) in self.var_map.iter() {
+ pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent) {
+ for (child, &parent) in self.var_map.iter() {
e(child, parent)
}
}
- pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent<'tcx>> {
+ pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
self.destruction_scopes.get(&n).cloned()
}
}
}
- fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.var_map.insert(var, lifetime);
}
- fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.rvalue_scopes.insert(var, lifetime);
}
- fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent<'tcx>) {
+ fn record_shrunk_rvalue_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id());
self.shrunk_rvalue_scopes.insert(var, lifetime);
}
- pub fn opt_encl_scope(&self, id: CodeExtent<'tcx>) -> Option<CodeExtent<'tcx>> {
+ pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
//! Returns the narrowest scope that encloses `id`, if any.
self.scope_map.get(&id).cloned()
}
#[allow(dead_code)] // used in cfg
- pub fn encl_scope(&self, id: CodeExtent<'tcx>) -> CodeExtent<'tcx> {
+ pub fn encl_scope(&self, id: CodeExtent) -> CodeExtent {
//! Returns the narrowest scope that encloses `id`, if any.
self.opt_encl_scope(id).unwrap()
}
/// Returns the lifetime of the local variable `var_id`
- pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent<'tcx> {
+ pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
match self.var_map.get(&var_id) {
Some(&r) => r,
None => { bug!("no enclosing scope for id {:?}", var_id); }
}
}
- pub fn temporary_scope2<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> (Option<CodeExtent<'tcx>>, bool) {
- let temporary_scope = self.temporary_scope(tcx, expr_id);
+ pub fn temporary_scope2(&self, expr_id: ast::NodeId)
+ -> (Option<CodeExtent>, bool) {
+ let temporary_scope = self.temporary_scope(expr_id);
let was_shrunk = match self.shrunk_rvalue_scopes.get(&expr_id) {
Some(&s) => {
info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})",
(temporary_scope, was_shrunk)
}
- pub fn old_and_new_temporary_scope<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> (Option<CodeExtent<'tcx>>,
- Option<CodeExtent<'tcx>>)
+ pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId)
+ -> (Option<CodeExtent>,
+ Option<CodeExtent>)
{
- let temporary_scope = self.temporary_scope(tcx, expr_id);
+ let temporary_scope = self.temporary_scope(expr_id);
(temporary_scope,
self.shrunk_rvalue_scopes
.get(&expr_id).cloned()
.or(temporary_scope))
}
- pub fn temporary_scope<'a, 'gcx: 'tcx>(&self,
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
- expr_id: ast::NodeId)
- -> Option<CodeExtent<'tcx>> {
+ pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
//! Returns the scope when temp created by expr_id will be cleaned up
// check for a designated rvalue scope
// if there's one. Static items, for instance, won't
// have an enclosing scope, hence no scope will be
// returned.
- let mut id = tcx.node_extent(expr_id);
+ let mut id = CodeExtent::Misc(expr_id);
- while let Some(&p) = self.scope_map.get(id) {
- match *p {
- CodeExtentData::DestructionScope(..) => {
+ while let Some(&p) = self.scope_map.get(&id) {
+ match p {
+ CodeExtent::DestructionScope(..) => {
debug!("temporary_scope({:?}) = {:?} [enclosing]",
expr_id, id);
return Some(id);
return None;
}
- pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind<'tcx> {
+ pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind {
//! Returns the lifetime of the variable `id`.
let scope = ty::ReScope(self.var_scope(id));
/// Finds the nearest common ancestor (if any) of two scopes. That is, finds the smallest
/// scope which is greater than or equal to both `scope_a` and `scope_b`.
pub fn nearest_common_ancestor(&self,
- scope_a: CodeExtent<'tcx>,
- scope_b: CodeExtent<'tcx>)
- -> CodeExtent<'tcx> {
+ scope_a: CodeExtent,
+ scope_b: CodeExtent)
+ -> CodeExtent {
if scope_a == scope_b { return scope_a; }
/// [1] The initial values for `a_buf` and `b_buf` are not used.
/// is re-initialized with new values (or else fallback to a
/// heap-allocated vector).
let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32];
- let mut a_vec: Vec<CodeExtent<'tcx>> = vec![];
+ let mut a_vec: Vec<CodeExtent> = vec![];
let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
- let mut b_vec: Vec<CodeExtent<'tcx>> = vec![];
+ let mut b_vec: Vec<CodeExtent> = vec![];
let scope_map = &self.scope_map;
let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec);
let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec);
let a_root_scope = a_ancestors[a_index];
let b_root_scope = a_ancestors[a_index];
return match (a_root_scope, b_root_scope) {
- (&CodeExtentData::DestructionScope(a_root_id),
- &CodeExtentData::DestructionScope(b_root_id)) => {
+ (CodeExtent::DestructionScope(a_root_id),
+ CodeExtent::DestructionScope(b_root_id)) => {
if self.fn_is_enclosed_by(a_root_id, b_root_id) {
// `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
scope_b
}
}
- fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent<'tcx>, CodeExtent<'tcx>>,
- scope: CodeExtent<'tcx>,
- buf: &'a mut [CodeExtent<'tcx>; 32],
- vec: &'a mut Vec<CodeExtent<'tcx>>)
- -> &'a [CodeExtent<'tcx>] {
+ fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent, CodeExtent>,
+ scope: CodeExtent,
+ buf: &'a mut [CodeExtent; 32],
+ vec: &'a mut Vec<CodeExtent>)
+ -> &'a [CodeExtent] {
// debug!("ancestors_of(scope={:?})", scope);
let mut scope = scope;
while i < 32 {
buf[i] = scope;
match scope_map.get(&scope) {
- Some(superscope) => scope = superscope,
+ Some(&superscope) => scope = superscope,
_ => return &buf[..i+1]
}
i += 1;
loop {
vec.push(scope);
match scope_map.get(&scope) {
- Some(superscope) => scope = superscope,
+ Some(&superscope) => scope = superscope,
_ => return &*vec
}
}
}
}
+
+ /// Assuming that the provided region was defined within this `RegionMaps`,
+ /// returns the outermost `CodeExtent` that the region outlives.
+ pub fn early_free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ br: &ty::EarlyBoundRegion)
+ -> CodeExtent {
+ let param_owner = tcx.parent_def_id(br.def_id).unwrap();
+
+ let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
+ let body_id = tcx.hir.maybe_body_owned_by(param_owner_id).unwrap_or_else(|| {
+ // The lifetime was defined on node that doesn't own a body,
+ // which in practice can only mean a trait or an impl, that
+ // is the parent of a method, and that is enforced below.
+ assert_eq!(Some(param_owner_id), self.root_parent,
+ "free_extent: {:?} not recognized by the region maps for {:?}",
+ param_owner,
+ self.root_body.map(|body| tcx.hir.body_owner_def_id(body)));
+
+ // The trait/impl lifetime is in scope for the method's body.
+ self.root_body.unwrap()
+ });
+
+ CodeExtent::CallSiteScope(body_id)
+ }
+
+ /// Assuming that the provided region was defined within this `RegionMaps`,
+ /// returns the outermost `CodeExtent` that the region outlives.
+ pub fn free_extent<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeRegion)
+ -> CodeExtent {
+ let param_owner = match fr.bound_region {
+ ty::BoundRegion::BrNamed(def_id, _) => {
+ tcx.parent_def_id(def_id).unwrap()
+ }
+ _ => fr.scope
+ };
+
+ // Ensure that the named late-bound lifetimes were defined
+ // on the same function that they ended up being freed in.
+ assert_eq!(param_owner, fr.scope);
+
+ let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
+ CodeExtent::CallSiteScope(tcx.hir.body_owned_by(param_owner_id))
+ }
}
/// Records the lifetime of a local variable as `cx.var_parent`
debug!("resolve_block(blk.id={:?})", blk.id);
let prev_cx = visitor.cx;
- let block_extent = visitor.new_node_extent_with_dtor(blk.id);
// We treat the tail expression in the block (if any) somewhat
// differently from the statements. The issue has to do with
// `other_argument()` has run and also the call to `quux(..)`
// itself has returned.
- visitor.cx = Context {
- root_id: prev_cx.root_id,
- var_parent: Some(block_extent),
- parent: Some(block_extent),
- };
+ visitor.enter_node_extent_with_dtor(blk.id);
+ visitor.cx.var_parent = visitor.cx.parent;
{
// This block should be kept approximately in sync with
// has the previous subscope in the block as a parent,
// except for the first such subscope, which has the
// block itself as a parent.
- let stmt_extent = visitor.new_code_extent(
- CodeExtentData::Remainder(BlockRemainder {
+ visitor.enter_code_extent(
+ CodeExtent::Remainder(BlockRemainder {
block: blk.id,
first_statement_index: i as u32
})
);
- visitor.cx = Context {
- root_id: prev_cx.root_id,
- var_parent: Some(stmt_extent),
- parent: Some(stmt_extent),
- };
+ visitor.cx.var_parent = visitor.cx.parent;
}
visitor.visit_stmt(statement)
}
}
fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) {
- visitor.new_node_extent(pat.id);
+ visitor.record_code_extent(CodeExtent::Misc(pat.id));
// If this is a binding then record the lifetime of that binding.
if let PatKind::Binding(..) = pat.node {
// statement plus its destructors, and thus the extent for which
// regions referenced by the destructors need to survive.
visitor.terminating_scopes.insert(stmt_id);
- let stmt_extent = visitor.new_node_extent_with_dtor(stmt_id);
let prev_parent = visitor.cx.parent;
- visitor.cx.parent = Some(stmt_extent);
+ visitor.enter_node_extent_with_dtor(stmt_id);
+
intravisit::walk_stmt(visitor, stmt);
+
visitor.cx.parent = prev_parent;
}
fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: &'tcx hir::Expr) {
debug!("resolve_expr(expr.id={:?})", expr.id);
- let expr_extent = visitor.new_node_extent_with_dtor(expr.id);
let prev_cx = visitor.cx;
- visitor.cx.parent = Some(expr_extent);
+ visitor.enter_node_extent_with_dtor(expr.id);
{
let terminating_scopes = &mut visitor.terminating_scopes;
}
hir::ExprMatch(..) => {
- visitor.cx.var_parent = Some(expr_extent);
+ visitor.cx.var_parent = visitor.cx.parent;
}
hir::ExprAssignOp(..) | hir::ExprIndex(..) |
fn record_rvalue_scope_if_borrow_expr<'a, 'tcx>(
visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
expr: &hir::Expr,
- blk_id: CodeExtent<'tcx>)
+ blk_id: CodeExtent)
{
match expr.node {
hir::ExprAddrOf(_, ref subexpr) => {
/// Note: ET is intended to match "rvalues or lvalues based on rvalues".
fn record_rvalue_scope<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
expr: &hir::Expr,
- blk_scope: CodeExtent<'tcx>,
+ blk_scope: CodeExtent,
is_shrunk: bool) {
let mut expr = expr;
loop {
}
impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> {
- pub fn intern_code_extent(&mut self,
- data: CodeExtentData,
- parent: Option<CodeExtent<'tcx>>)
- -> CodeExtent<'tcx> {
- let code_extent = self.tcx.intern_code_extent(data);
- self.region_maps.record_code_extent(code_extent, parent);
- code_extent
- }
-
- pub fn intern_node(&mut self,
- n: ast::NodeId,
- parent: Option<CodeExtent<'tcx>>) -> CodeExtent<'tcx> {
- self.intern_code_extent(CodeExtentData::Misc(n), parent)
- }
-
/// Records the current parent (if any) as the parent of `child_scope`.
- fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent<'tcx> {
+ fn record_code_extent(&mut self, child_scope: CodeExtent) {
let parent = self.cx.parent;
- self.intern_code_extent(child_scope, parent)
+ self.region_maps.record_code_extent(child_scope, parent);
}
- fn new_node_extent(&mut self, child_scope: ast::NodeId) -> CodeExtent<'tcx> {
- self.new_code_extent(CodeExtentData::Misc(child_scope))
+ /// Records the current parent (if any) as the parent of `child_scope`,
+ /// and sets `child_scope` as the new current parent.
+ fn enter_code_extent(&mut self, child_scope: CodeExtent) {
+ self.record_code_extent(child_scope);
+ self.cx.parent = Some(child_scope);
}
- fn new_node_extent_with_dtor(&mut self, id: ast::NodeId) -> CodeExtent<'tcx> {
+ fn enter_node_extent_with_dtor(&mut self, id: ast::NodeId) {
// If node was previously marked as a terminating scope during the
// recursive visit of its parent node in the AST, then we need to
// account for the destruction scope representing the extent of
// the destructors that run immediately after it completes.
if self.terminating_scopes.contains(&id) {
- let ds = self.new_code_extent(
- CodeExtentData::DestructionScope(id));
- self.intern_node(id, Some(ds))
- } else {
- self.new_node_extent(id)
+ self.enter_code_extent(CodeExtent::DestructionScope(id));
}
+ self.enter_code_extent(CodeExtent::Misc(id));
}
}
fn visit_body(&mut self, body: &'tcx hir::Body) {
let body_id = body.id();
- let owner_id = self.map.body_owner(body_id);
+ let owner_id = self.tcx.hir.body_owner(body_id);
debug!("visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
owner_id,
}
self.cx.root_id = Some(body_id.node_id);
- self.cx.parent = Some(self.new_code_extent(
- CodeExtentData::CallSiteScope { fn_id: owner_id, body_id: body_id.node_id }));
- self.cx.parent = Some(self.new_code_extent(
- CodeExtentData::ParameterScope { fn_id: owner_id, body_id: body_id.node_id }));
+ self.enter_code_extent(CodeExtent::CallSiteScope(body_id));
+ self.enter_code_extent(CodeExtent::ParameterScope(body_id));
// The arguments and `self` are parented to the fn.
self.cx.var_parent = self.cx.parent.take();
}
fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
- -> Rc<RegionMaps<'tcx>>
+ -> Rc<RegionMaps>
{
let closure_base_def_id = tcx.closure_base_def_id(def_id);
if closure_base_def_id != def_id {
return tcx.region_maps(closure_base_def_id);
}
- let mut maps = RegionMaps::new();
-
let id = tcx.hir.as_local_node_id(def_id).unwrap();
- if let Some(body) = tcx.hir.maybe_body_owned_by(id) {
+ let maps = if let Some(body) = tcx.hir.maybe_body_owned_by(id) {
let mut visitor = RegionResolutionVisitor {
- tcx: tcx,
- region_maps: &mut maps,
- map: &tcx.hir,
+ tcx,
+ region_maps: RegionMaps::new(),
cx: Context {
root_id: None,
parent: None,
terminating_scopes: NodeSet(),
};
+ visitor.region_maps.root_body = Some(body);
+
+ // If the item is an associated const or a method,
+ // record its impl/trait parent, as it can also have
+ // lifetime parameters free in this body.
+ match tcx.hir.get(id) {
+ hir::map::NodeImplItem(_) |
+ hir::map::NodeTraitItem(_) => {
+ visitor.region_maps.root_parent = Some(tcx.hir.get_parent(id));
+ }
+ _ => {}
+ }
+
visitor.visit_body(tcx.hir.body(body));
- }
+
+ visitor.region_maps
+ } else {
+ RegionMaps::new()
+ };
Rc::new(maps)
}
use session::Session;
use hir::def::Def;
use hir::def_id::DefId;
-use middle::region;
use ty;
use std::cell::Cell;
EarlyBound(/* index */ u32, /* lifetime decl */ ast::NodeId),
LateBound(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId),
LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
- Free(region::CallSiteScopeData, /* lifetime decl */ ast::NodeId),
+ Free(DefId, /* lifetime decl */ ast::NodeId),
}
impl Region {
};
if let Some(mut def) = result {
- if let Some(body_id) = outermost_body {
+ if let Region::EarlyBound(..) = def {
+ // Do not free early-bound regions, only late-bound ones.
+ } else if let Some(body_id) = outermost_body {
let fn_id = self.hir_map.body_owner(body_id);
- let scope_data = region::CallSiteScopeData {
- fn_id: fn_id, body_id: body_id.node_id
- };
match self.hir_map.get(fn_id) {
hir::map::NodeItem(&hir::Item {
node: hir::ItemFn(..), ..
hir::map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), ..
}) => {
- def = Region::Free(scope_data, def.id().unwrap());
+ let scope = self.hir_map.local_def_id(fn_id);
+ def = Region::Free(scope, def.id().unwrap());
}
_ => {}
}
pub use self::StabilityLevel::*;
-use hir::map as hir_map;
use lint;
use hir::def::Def;
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
use ty::{self, TyCtxt};
use middle::privacy::AccessLevels;
+use session::Session;
use syntax::symbol::Symbol;
use syntax_pos::{Span, DUMMY_SP};
use syntax::ast;
item_sp: Span, kind: AnnotationKind, visit_children: F)
where F: FnOnce(&mut Self)
{
- if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
+ if self.index.staged_api[&LOCAL_CRATE] {
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
parent_depr: None,
in_trait_impl: false,
};
+
+ // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
+ // a parent stability annotation which indicates that this is private
+ // with the `rustc_private` feature. This is intended for use when
+ // compiling librustc crates themselves so we can leverage crates.io
+ // while maintaining the invariant that all sysroot crates are unstable
+ // by default and are unable to be used.
+ if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked {
+ let reason = "this crate is being loaded from the sysroot, and \
+ unstable location; did you mean to load this crate \
+ from crates.io via `Cargo.toml` instead?";
+ let stability = tcx.intern_stability(Stability {
+ level: attr::StabilityLevel::Unstable {
+ reason: Some(Symbol::intern(reason)),
+ issue: 27812,
+ },
+ feature: Symbol::intern("rustc_private"),
+ rustc_depr: None,
+ });
+ annotator.parent_stab = Some(stability);
+ }
+
annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, krate.span, AnnotationKind::Required,
|v| intravisit::walk_crate(v, krate));
}
- pub fn new(hir_map: &hir_map::Map) -> Index<'tcx> {
- let krate = hir_map.krate();
-
- let mut is_staged_api = false;
- for attr in &krate.attrs {
- if attr.path == "stable" || attr.path == "unstable" {
- is_staged_api = true;
- break
- }
- }
+ pub fn new(sess: &Session) -> Index<'tcx> {
+ let is_staged_api =
+ sess.opts.debugging_opts.force_unstable_if_unmarked ||
+ sess.features.borrow().staged_api;
let mut staged_api = FxHashMap();
staged_api.insert(LOCAL_CRATE, is_staged_api);
}
}
- let is_staged_api = *self.stability.borrow_mut().staged_api.entry(def_id.krate)
- .or_insert_with(|| self.sess.cstore.is_staged_api(def_id.krate));
+ let is_staged_api = self.lookup_stability(DefId {
+ index: CRATE_DEF_INDEX,
+ ..def_id
+ }).is_some();
if !is_staged_api {
return;
}
match stability {
Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
- if !self.stability.borrow().active_features.contains(feature) {
- let msg = match *reason {
- Some(ref r) => format!("use of unstable library feature '{}': {}",
- feature.as_str(), &r),
- None => format!("use of unstable library feature '{}'", &feature)
- };
- emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
- GateIssue::Library(Some(issue)), &msg);
+ if self.stability.borrow().active_features.contains(feature) {
+ return
}
+
+ // When we're compiling the compiler itself we may pull in
+ // crates from crates.io, but those crates may depend on other
+ // crates also pulled in from crates.io. We want to ideally be
+ // able to compile everything without requiring upstream
+ // modifications, so in the case that this looks like a
+ // rustc_private crate (e.g. a compiler crate) and we also have
+ // the `-Z force-unstable-if-unmarked` flag present (we're
+ // compiling a compiler crate), then let this missing feature
+ // annotation slide.
+ if *feature == "rustc_private" && issue == 27812 {
+ if self.sess.opts.debugging_opts.force_unstable_if_unmarked {
+ return
+ }
+ }
+
+ let msg = match *reason {
+ Some(ref r) => format!("use of unstable library feature '{}': {}",
+ feature.as_str(), &r),
+ None => format!("use of unstable library feature '{}'", &feature)
+ };
+ emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
+ GateIssue::Library(Some(issue)), &msg);
}
Some(_) => {
// Stable APIs are always ok to call and deprecated APIs are
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
- if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api {
+ if tcx.stability.borrow().staged_api[&LOCAL_CRATE] {
let krate = tcx.hir.krate();
let mut missing = MissingStabilityAnnotations {
tcx: tcx,
StorageDead(Lvalue<'tcx>),
InlineAsm {
- asm: InlineAsm,
+ asm: Box<InlineAsm>,
outputs: Vec<Lvalue<'tcx>>,
inputs: Vec<Operand<'tcx>>
},
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Operand<'tcx> {
Consume(Lvalue<'tcx>),
- Constant(Constant<'tcx>),
+ Constant(Box<Constant<'tcx>>),
}
impl<'tcx> Debug for Operand<'tcx> {
substs: &'tcx Substs<'tcx>,
span: Span,
) -> Self {
- Operand::Constant(Constant {
+ Operand::Constant(box Constant {
span: span,
ty: tcx.type_of(def_id).subst(tcx, substs),
literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
/// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
/// that `Foo` has a destructor. These rvalues can be optimized
/// away after type-checking and before lowering.
- Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
+ Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
tuple_fmt.finish()
}
- match *kind {
+ match **kind {
AggregateKind::Array(_) => write!(fmt, "{:?}", lvs),
AggregateKind::Tuple => {
Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
Box(ty) => Box(ty.fold_with(folder)),
Aggregate(ref kind, ref fields) => {
- let kind = match *kind {
+ let kind = box match **kind {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
AggregateKind::Tuple => AggregateKind::Tuple,
AggregateKind::Adt(def, v, substs, n) =>
Discriminant(ref lval) => lval.visit_with(visitor),
Box(ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
- (match *kind {
+ (match **kind {
AggregateKind::Array(ty) => ty.visit_with(visitor),
AggregateKind::Tuple => false,
AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
tcx.mk_box(t)
}
Rvalue::Aggregate(ref ak, ref ops) => {
- match *ak {
+ match **ak {
AggregateKind::Array(ty) => {
tcx.mk_array(ty, ops.len())
}
Rvalue::Aggregate(ref $($mutability)* kind,
ref $($mutability)* operands) => {
+ let kind = &$($mutability)* **kind;
match *kind {
AggregateKind::Array(ref $($mutability)* ty) => {
self.visit_ty(ty);
"add a source pattern to the file path remapping config"),
remap_path_prefix_to: Vec<String> = (vec![], parse_string_push, [TRACKED],
"add a mapping target to the file path remapping config"),
+ force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
+ "force all crates to be `rustc_private` unstable"),
}
pub fn default_lib_output() -> CrateType {
};
// Search for a predicate like `Self : Sized` amongst the trait bounds.
- let free_substs = self.construct_free_substs(def_id, None);
let predicates = self.predicates_of(def_id);
- let predicates = predicates.instantiate(self, free_substs).predicates;
+ let predicates = predicates.instantiate_identity(self).predicates;
elaborate_predicates(self, predicates)
.any(|predicate| {
match predicate {
}
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
- let penv = tcx.construct_parameter_environment(DUMMY_SP,
- impl1_def_id,
- None);
- let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
- .unwrap()
- .subst(tcx, &penv.free_substs);
+ let penv = tcx.parameter_environment(impl1_def_id);
+ let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
// Create a infcx, taking the predicates of impl1 as assumptions:
let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
// I want to be conservative. --nmatsakis
let ty_max = data.skip_binder().0;
let r_min = data.skip_binder().1;
- if r_min.is_bound() {
+ if r_min.is_late_bound() {
return;
}
tcx.outlives_components(ty_max)
.into_iter()
.filter_map(|component| match component {
- Component::Region(r) => if r.is_bound() {
+ Component::Region(r) => if r.is_late_bound() {
None
} else {
Some(ty::Predicate::RegionOutlives(
use hir::map::DisambiguatedDefPathData;
use middle::free_region::FreeRegionMap;
use middle::lang_items;
-use middle::region::{CodeExtent, CodeExtentData};
use middle::resolve_lifetime;
use middle::stability;
use mir::Mir;
type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
- region: RefCell<FxHashSet<Interned<'tcx, RegionKind<'tcx>>>>,
+ region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
}
layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
- code_extent_interner: RefCell<FxHashSet<CodeExtent<'tcx>>>,
-
/// A vector of every trait accessible in the whole crate
/// (i.e. including those from subcrates). This is used only for
/// error reporting, and so is lazily initialised and generally
interned
}
- pub fn node_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::Misc(n))
- }
-
- // Returns the code extent for an item - the destruction scope.
- pub fn item_extent(self, n: ast::NodeId) -> CodeExtent<'gcx> {
- self.intern_code_extent(CodeExtentData::DestructionScope(n))
- }
-
- pub fn call_site_extent(self, fn_id: ast::NodeId, body_id: ast::NodeId) -> CodeExtent<'gcx> {
- assert!(fn_id != body_id);
- self.intern_code_extent(CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id })
- }
-
- pub fn intern_code_extent(self, data: CodeExtentData) -> CodeExtent<'gcx> {
- if let Some(st) = self.code_extent_interner.borrow().get(&data) {
- return st;
- }
-
- let interned = self.global_interners.arena.alloc(data);
- if let Some(prev) = self.code_extent_interner.borrow_mut().replace(interned) {
- bug!("Tried to overwrite interned code-extent: {:?}", prev)
- }
- interned
- }
-
pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
return layout;
data_layout: data_layout,
layout_cache: RefCell::new(FxHashMap()),
layout_interner: RefCell::new(FxHashSet()),
- code_extent_interner: RefCell::new(FxHashSet()),
layout_depth: Cell::new(0),
derive_macros: RefCell::new(NodeMap()),
stability_interner: RefCell::new(FxHashSet()),
}
}
-impl<'a, 'tcx> Lift<'tcx> for ty::FreeRegion<'a> {
- type Lifted = ty::FreeRegion<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- let scope = self.scope.map(|code_extent| tcx.intern_code_extent(*code_extent));
- let bound_region = self.bound_region;
- Some(ty::FreeRegion { scope, bound_region })
- }
-}
-
impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
type Lifted = Region<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'tcx>> {
}
}
-impl<'tcx> Borrow<RegionKind<'tcx>> for Interned<'tcx, RegionKind<'tcx>> {
- fn borrow<'a>(&'a self) -> &'a RegionKind<'tcx> {
+impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
+ fn borrow<'a>(&'a self) -> &'a RegionKind {
&self.0
}
}
&ty::ReVar(_) | &ty::ReSkolemized(..) => true,
_ => false
}
- }) -> RegionKind<'tcx>
+ }) -> RegionKind
);
macro_rules! slice_interners {
//! These methods return true to indicate that the visitor has found what it is looking for
//! and does not need to visit anything else.
-use middle::region;
use ty::subst::Substs;
use ty::adjustment;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
(result, replacer.map)
}
-
- /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
- /// `scope_id`.
- pub fn liberate_late_bound_regions<T>(self,
- all_outlive_scope: Option<region::CodeExtent<'tcx>>,
- value: &Binder<T>)
- -> T
- where T : TypeFoldable<'tcx>
- {
- self.replace_late_bound_regions(value, |br| {
- self.mk_region(ty::ReFree(ty::FreeRegion {
- scope: all_outlive_scope,
- bound_region: br
- }))
- }).0
- }
-
/// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
/// becomes `for<'a,'b> Foo`.
pub fn flatten_late_bound_regions<T>(self, bound2_value: &Binder<Binder<T>>)
// regions. See comment on `shift_regions_through_binders` method in
// `subst.rs` for more details.
-pub fn shift_region<'tcx>(region: ty::RegionKind<'tcx>, amount: u32) -> ty::RegionKind<'tcx> {
+pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
match region {
ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(debruijn.shifted(amount), br)
let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
StructKind::AlwaysSizedUnivariant
} else {
- let param_env = tcx.construct_parameter_environment(DUMMY_SP,
- def.did, None);
+ let param_env = tcx.parameter_environment(def.did);
let fields = &def.variants[0].fields;
let last_field = &fields[fields.len()-1];
- let always_sized = last_field.ty(tcx, param_env.free_substs)
+ let always_sized = tcx.type_of(last_field.did)
.is_sized(tcx, ¶m_env, DUMMY_SP);
if !always_sized { StructKind::MaybeUnsizedUnivariant }
else { StructKind::AlwaysSizedUnivariant }
/// Per-function `RegionMaps`. The `DefId` should be the owner-def-id for the fn body;
/// in the case of closures or "inline" expressions, this will be redirected to the enclosing
/// fn item.
- [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps<'tcx>>,
+ [] region_maps: RegionMaps(DefId) -> Rc<RegionMaps>,
[] mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>,
use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::privacy::AccessLevels;
-use middle::region::CodeExtent;
use middle::resolve_lifetime::ObjectLifetimeDefault;
+use middle::region::CodeExtent;
use mir::Mir;
use traits;
use ty;
impl RegionParameterDef {
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
ty::EarlyBoundRegion {
+ def_id: self.def_id,
index: self.index,
name: self.name,
}
}
+ pub fn to_bound_region(&self) -> ty::BoundRegion {
+ self.to_early_bound_region_data().to_bound_region()
+ }
+}
+
+impl ty::EarlyBoundRegion {
pub fn to_bound_region(&self) -> ty::BoundRegion {
ty::BoundRegion::BrNamed(self.def_id, self.name)
}
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
}
+ pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ -> InstantiatedPredicates<'tcx> {
+ let mut instantiated = InstantiatedPredicates::empty();
+ self.instantiate_identity_into(tcx, &mut instantiated);
+ instantiated
+ }
+
+ fn instantiate_identity_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ instantiated: &mut InstantiatedPredicates<'tcx>) {
+ if let Some(def_id) = self.parent {
+ tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
+ }
+ instantiated.predicates.extend(&self.predicates)
+ }
+
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
poly_trait_ref: &ty::PolyTraitRef<'tcx>)
-> InstantiatedPredicates<'tcx>
/// more distinctions clearer.
#[derive(Clone)]
pub struct ParameterEnvironment<'tcx> {
- /// See `construct_free_substs` for details.
- pub free_substs: &'tcx Substs<'tcx>,
-
- /// Each type parameter has an implicit region bound that
- /// indicates it must outlive at least the function body (the user
- /// may specify stronger requirements). This field indicates the
- /// region of the callee. If it is `None`, then the parameter
- /// environment is for an item or something where the "callee" is
- /// not clear.
- pub implicit_region_bound: Option<ty::Region<'tcx>>,
-
/// Obligations that the caller must satisfy. This is basically
/// the set of bounds on the in-scope type parameters, translated
/// into Obligations, and elaborated and normalized.
pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
- /// Scope that is attached to free regions for this scope. This is
- /// usually the id of the fn body, but for more abstract scopes
- /// like structs we use None or the item extent.
- ///
- /// FIXME(#3696). It would be nice to refactor so that free
- /// regions don't have this implicit scope and instead introduce
- /// relationships in the environment.
- pub free_id_outlive: Option<CodeExtent<'tcx>>,
-
/// A cache for `moves_by_default`.
pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
-> ParameterEnvironment<'tcx>
{
ParameterEnvironment {
- free_substs: self.free_substs,
- implicit_region_bound: self.implicit_region_bound,
caller_bounds: caller_bounds,
- free_id_outlive: self.free_id_outlive,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
}
}
-
- /// Construct a parameter environment given an item, impl item, or trait item
- pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
- -> ParameterEnvironment<'tcx> {
- match tcx.hir.find(id) {
- Some(hir_map::NodeImplItem(ref impl_item)) => {
- match impl_item.node {
- hir::ImplItemKind::Type(_) => {
- // associated types don't have their own entry (for some reason),
- // so for now just grab environment for the impl
- let impl_id = tcx.hir.get_parent(id);
- let impl_def_id = tcx.hir.local_def_id(impl_id);
- tcx.construct_parameter_environment(impl_item.span,
- impl_def_id,
- Some(tcx.item_extent(id)))
- }
- hir::ImplItemKind::Const(_, body) |
- hir::ImplItemKind::Method(_, body) => {
- tcx.construct_parameter_environment(
- impl_item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.call_site_extent(id, body.node_id)))
- }
- }
- }
- Some(hir_map::NodeTraitItem(trait_item)) => {
- match trait_item.node {
- hir::TraitItemKind::Type(..) |
- hir::TraitItemKind::Const(_, None) |
- hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_))=> {
- tcx.construct_parameter_environment(trait_item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.item_extent(id)))
- }
- hir::TraitItemKind::Const(_, Some(body)) |
- hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body)) => {
- tcx.construct_parameter_environment(
- trait_item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.call_site_extent(id, body.node_id)))
- }
- }
- }
- Some(hir_map::NodeItem(item)) => {
- match item.node {
- hir::ItemConst(_, body) |
- hir::ItemStatic(.., body) |
- hir::ItemFn(.., body) => {
- tcx.construct_parameter_environment(
- item.span,
- tcx.hir.local_def_id(id),
- Some(tcx.call_site_extent(id, body.node_id)))
- }
- hir::ItemEnum(..) |
- hir::ItemStruct(..) |
- hir::ItemUnion(..) |
- hir::ItemTy(..) |
- hir::ItemImpl(..) |
- hir::ItemTrait(..) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.construct_parameter_environment(item.span,
- def_id,
- Some(tcx.item_extent(id)))
- }
- _ => {
- span_bug!(item.span,
- "ParameterEnvironment::for_item():
- can't create a parameter \
- environment for this kind of item")
- }
- }
- }
- Some(hir_map::NodeExpr(expr)) => {
- // This is a convenience to allow closures to work.
- if let hir::ExprClosure(.., body, _) = expr.node {
- let def_id = tcx.hir.local_def_id(id);
- let base_def_id = tcx.closure_base_def_id(def_id);
- tcx.construct_parameter_environment(
- expr.span,
- base_def_id,
- Some(tcx.call_site_extent(id, body.node_id)))
- } else {
- tcx.empty_parameter_environment()
- }
- }
- Some(hir_map::NodeForeignItem(item)) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.construct_parameter_environment(item.span,
- def_id,
- None)
- }
- Some(hir_map::NodeStructCtor(..)) |
- Some(hir_map::NodeVariant(..)) => {
- let def_id = tcx.hir.local_def_id(id);
- tcx.construct_parameter_environment(tcx.hir.span(id),
- def_id,
- None)
- }
- it => {
- bug!("ParameterEnvironment::from_item(): \
- `{}` = {:?} is unsupported",
- tcx.hir.node_to_string(id), it)
- }
- }
- }
}
#[derive(Copy, Clone, Debug)]
/// are no free type/lifetime parameters in scope.
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
ty::ParameterEnvironment {
- free_substs: self.intern_substs(&[]),
caller_bounds: Slice::empty(),
- implicit_region_bound: None,
- free_id_outlive: None,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
}
}
- /// Constructs and returns a substitution that can be applied to move from
- /// the "outer" view of a type or method to the "inner" view.
- /// In general, this means converting from bound parameters to
- /// free parameters. Since we currently represent bound/free type
- /// parameters in the same way, this only has an effect on regions.
- pub fn construct_free_substs(self,
- def_id: DefId,
- free_id_outlive: Option<CodeExtent<'gcx>>)
- -> &'gcx Substs<'gcx> {
-
- let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
- // map bound 'a => free 'a
- self.global_tcx().mk_region(ReFree(FreeRegion {
- scope: free_id_outlive,
- bound_region: def.to_bound_region()
- }))
- }, |def, _| {
- // map T => T
- self.global_tcx().mk_param_from_def(def)
- });
-
- debug!("construct_parameter_environment: {:?}", substs);
- substs
- }
-
/// See `ParameterEnvironment` struct def'n for details.
- /// If you were using `free_id: NodeId`, you might try `self.region_maps().item_extent(free_id)`
- /// for the `free_id_outlive` parameter. (But note that this is not always quite right.)
- pub fn construct_parameter_environment(self,
- span: Span,
- def_id: DefId,
- free_id_outlive: Option<CodeExtent<'gcx>>)
- -> ParameterEnvironment<'gcx>
- {
- //
- // Construct the free substs.
- //
-
- let free_substs = self.construct_free_substs(def_id, free_id_outlive);
-
+ pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
//
// Compute the bounds on Self and the type parameters.
//
let tcx = self.global_tcx();
- let generic_predicates = tcx.predicates_of(def_id);
- let bounds = generic_predicates.instantiate(tcx, free_substs);
- let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
+ let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
let predicates = bounds.predicates;
// Finally, we have to normalize the bounds in the environment, in
//
let unnormalized_env = ty::ParameterEnvironment {
- free_substs: free_substs,
- implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
caller_bounds: tcx.intern_predicates(&predicates),
- free_id_outlive: free_id_outlive,
is_copy_cache: RefCell::new(FxHashMap()),
is_sized_cache: RefCell::new(FxHashMap()),
is_freeze_cache: RefCell::new(FxHashMap()),
};
- let body_id = free_id_outlive.map(|f| f.node_id())
- .unwrap_or(DUMMY_NODE_ID);
- let cause = traits::ObligationCause::misc(span, body_id);
+ let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
+ self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+ });
+ let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
}
pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
- self.mk_region(ty::ReScope(self.node_extent(id)))
+ self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
}
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
for r in regions {
- if !r.is_bound() {
+ if !r.is_late_bound() {
out.push(Component::Region(r));
}
}
RustcEncodable, RustcDecodable, Copy)]
/// A "free" region `fr` can be interpreted as "some region
/// at least as big as the scope `fr.scope`".
-///
-/// If `fr.scope` is None, then this is in some context (e.g., an
-/// impl) where lifetimes are more abstract and the notion of the
-/// caller/callee stack frames are not applicable.
-pub struct FreeRegion<'tcx> {
- pub scope: Option<region::CodeExtent<'tcx>>,
+pub struct FreeRegion {
+ pub scope: DefId,
pub bound_region: BoundRegion,
}
/// Fresh bound identifiers created during GLB computations.
BrFresh(u32),
- // Anonymous region for the implicit env pointer parameter
- // to a closure
+ /// Anonymous region for the implicit env pointer parameter
+ /// to a closure
BrEnv,
}
pub region_name: ast::Name,
}
-// NB: If you change this, you'll probably want to change the corresponding
-// AST structure in libsyntax/ast.rs as well.
+/// NB: If you change this, you'll probably want to change the corresponding
+/// AST structure in libsyntax/ast.rs as well.
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum TypeVariants<'tcx> {
/// The primitive boolean type. Written as `bool`.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum ExistentialPredicate<'tcx> {
- // e.g. Iterator
+ /// e.g. Iterator
Trait(ExistentialTraitRef<'tcx>),
- // e.g. Iterator::Item = T
+ /// e.g. Iterator::Item = T
Projection(ExistentialProjection<'tcx>),
- // e.g. Send
+ /// e.g. Send
AutoTrait(DefId),
}
/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
pub struct DebruijnIndex {
- // We maintain the invariant that this is never 0. So 1 indicates
- // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
+ /// We maintain the invariant that this is never 0. So 1 indicates
+ /// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
pub depth: u32,
}
-pub type Region<'tcx> = &'tcx RegionKind<'tcx>;
+pub type Region<'tcx> = &'tcx RegionKind;
/// Representation of regions.
///
/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
-pub enum RegionKind<'tcx> {
+pub enum RegionKind {
// Region bound in a type or fn declaration which will be
// substituted 'early' -- that is, at the same time when type
// parameters are substituted.
/// When checking a function body, the types of all arguments and so forth
/// that refer to bound region parameters are modified to refer to free
/// region parameters.
- ReFree(FreeRegion<'tcx>),
+ ReFree(FreeRegion),
/// A concrete region naming some statically determined extent
/// (e.g. an expression or sequence of statements) within the
/// current function.
- ReScope(region::CodeExtent<'tcx>),
+ ReScope(region::CodeExtent),
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct EarlyBoundRegion {
+ pub def_id: DefId,
pub index: u32,
pub name: Name,
}
}
}
-// Region utilities
-impl<'tcx> RegionKind<'tcx> {
- pub fn is_bound(&self) -> bool {
+/// Region utilities
+impl RegionKind {
+ pub fn is_late_bound(&self) -> bool {
match *self {
- ty::ReEarlyBound(..) => true,
ty::ReLateBound(..) => true,
_ => false,
}
}
/// Returns the depth of `self` from the (1-based) binding level `depth`
- pub fn from_depth(&self, depth: u32) -> RegionKind<'tcx> {
+ pub fn from_depth(&self, depth: u32) -> RegionKind {
match *self {
ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
depth: debruijn.depth - (depth - 1)
}
}
-// Type utilities
+/// Type utilities
impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
match self.sty {
}
}
- // Test whether this is a `()` which was produced by defaulting a
- // diverging type variable with feature(never_type) disabled.
+ /// Test whether this is a `()` which was produced by defaulting a
+ /// diverging type variable with feature(never_type) disabled.
pub fn is_defaulted_unit(&self) -> bool {
match self.sty {
TyTuple(_, true) => true,
}
}
+ /// panics if called on any type other than `Box<T>`
pub fn boxed_ty(&self) -> Ty<'tcx> {
match self.sty {
TyAdt(def, substs) if def.is_box() => substs.type_at(0),
}
}
- /*
- A scalar type is one that denotes an atomic datum, with no sub-components.
- (A TyRawPtr is scalar because it represents a non-managed pointer, so its
- contents are abstract to rustc.)
- */
+ /// A scalar type is one that denotes an atomic datum, with no sub-components.
+ /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its
+ /// contents are abstract to rustc.)
pub fn is_scalar(&self) -> bool {
match self.sty {
TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
}
}
- // Returns the type and mutability of *ty.
- //
- // The parameter `explicit` indicates if this is an *explicit* dereference.
- // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
+ /// Returns the type and mutability of *ty.
+ ///
+ /// The parameter `explicit` indicates if this is an *explicit* dereference.
+ /// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference)
-> Option<TypeAndMut<'tcx>>
{
}
}
- // Returns the type of ty[i]
+ /// Returns the type of ty[i]
pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
match self.sty {
TyArray(ty, _) | TySlice(ty) => Some(ty),
}
}
- // Type accessors for substructures of types
+ /// Type accessors for substructures of types
pub fn fn_args(&self) -> ty::Binder<&'tcx [Ty<'tcx>]> {
self.fn_sig().inputs()
}
self.hash(db.depth);
self.hash(i);
}
- ty::ReEarlyBound(ty::EarlyBoundRegion { index, name }) => {
- self.hash(index);
- self.hash(name.as_str());
+ ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
+ self.def_id(def_id);
}
ty::ReLateBound(..) |
ty::ReFree(..) |
}
}
-impl<'tcx> fmt::Debug for ty::RegionKind<'tcx> {
+impl fmt::Debug for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::ReEarlyBound(ref data) => {
impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ParameterEnvironment(\
- free_substs={:?}, \
- implicit_region_bound={:?}, \
- caller_bounds={:?})",
- self.free_substs,
- self.implicit_region_bound,
- self.caller_bounds)
+ write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
}
}
-impl<'tcx> fmt::Display for ty::RegionKind<'tcx> {
+impl<'tcx> fmt::Display for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if verbose() {
return write!(f, "{:?}", *self);
}
}
-impl<'tcx> fmt::Debug for ty::FreeRegion<'tcx> {
+impl fmt::Debug for ty::FreeRegion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ReFree({:?}, {:?})",
self.scope, self.bound_region)
//! build speedups.
#![crate_name = "rustc_back"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(const_fn)]
#![feature(libc)]
#![feature(rand)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![cfg_attr(test, feature(rand))]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate syntax;
extern crate libc;
extern crate serialize;
#![crate_name = "rustc_bitflags"]
#![feature(associated_consts)]
-#![feature(staged_api)]
#![crate_type = "rlib"]
#![no_std]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![deny(warnings)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
//! A typesafe bitmask flag generator.
})
}
- pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent<'tcx>, mut op: F) -> bool where
+ pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent, mut op: F) -> bool where
F: FnMut(&Loan<'tcx>) -> bool,
{
//! Like `each_issued_loan()`, but only considers loans that are
}
fn each_in_scope_loan_affecting_path<F>(&self,
- scope: region::CodeExtent<'tcx>,
+ scope: region::CodeExtent,
loan_path: &LoanPath<'tcx>,
mut op: F)
-> bool where
let mut ret = UseOk;
self.each_in_scope_loan_affecting_path(
- self.tcx().node_extent(expr_id), use_path, |loan| {
+ region::CodeExtent::Misc(expr_id), use_path, |loan| {
if !compatible_borrow_kinds(loan.kind, borrow_kind) {
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
false
// Check that we don't invalidate any outstanding loans
if let Some(loan_path) = opt_loan_path(&assignee_cmt) {
- let scope = self.tcx().node_extent(assignment_id);
+ let scope = region::CodeExtent::Misc(assignment_id);
self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
self.report_illegal_mutation(assignment_span, &loan_path, loan);
false
type R = Result<(),()>;
pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
- item_scope: region::CodeExtent<'tcx>,
+ item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
cmt: mc::cmt<'tcx>,
bccx: &'a BorrowckCtxt<'a, 'tcx>,
// the scope of the function body for the enclosing item
- item_scope: region::CodeExtent<'tcx>,
+ item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
bccx: bccx,
infcx: &infcx,
all_loans: Vec::new(),
- item_ub: bccx.tcx.node_extent(body.node_id),
+ item_ub: region::CodeExtent::Misc(body.node_id),
move_data: MoveData::new(),
move_error_collector: move_error::MoveErrorCollector::new(),
};
all_loans: Vec<Loan<'tcx>>,
/// `item_ub` is used as an upper-bound on the lifetime whenever we
/// ask for the scope of an expression categorized as an upvar.
- item_ub: region::CodeExtent<'tcx>,
+ item_ub: region::CodeExtent,
}
impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
let loan_scope = match *loan_region {
ty::ReScope(scope) => scope,
- ty::ReFree(ref fr) => fr.scope.unwrap_or(self.item_ub),
+ ty::ReEarlyBound(ref br) => {
+ self.bccx.region_maps.early_free_extent(self.tcx(), br)
+ }
+
+ ty::ReFree(ref fr) => {
+ self.bccx.region_maps.free_extent(self.tcx(), fr)
+ }
ty::ReStatic => self.item_ub,
ty::ReEmpty |
ty::ReLateBound(..) |
- ty::ReEarlyBound(..) |
ty::ReVar(..) |
ty::ReSkolemized(..) |
ty::ReErased => {
};
debug!("loan_scope = {:?}", loan_scope);
- let borrow_scope = self.tcx().node_extent(borrow_id);
+ let borrow_scope = region::CodeExtent::Misc(borrow_id);
let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope);
debug!("gen_scope = {:?}", gen_scope);
}
pub fn compute_gen_scope(&self,
- borrow_scope: region::CodeExtent<'tcx>,
- loan_scope: region::CodeExtent<'tcx>)
- -> region::CodeExtent<'tcx> {
+ borrow_scope: region::CodeExtent,
+ loan_scope: region::CodeExtent)
+ -> region::CodeExtent {
//! Determine when to introduce the loan. Typically the loan
//! is introduced at the point of the borrow, but in some cases,
//! notably method arguments, the loan may be introduced only
}
}
- pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent<'tcx>, lp: &LoanPath<'tcx>)
- -> region::CodeExtent<'tcx> {
+ pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath<'tcx>)
+ -> region::CodeExtent {
//! Determine when the loan restrictions go out of scope.
//! This is either when the lifetime expires or when the
//! local variable which roots the loan-path goes out of scope,
_ => return
}
let id = src.item_id();
- let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
let elaborate_patch = {
let mir = &*mir;
}
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
- Rvalue::Use(Operand::Constant(Constant {
+ Rvalue::Use(Operand::Constant(Box::new(Constant {
span: span,
ty: self.tcx.types.bool,
literal: Literal::Value { value: ConstVal::Bool(val) }
- }))
+ })))
}
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
// steals it, but it forces the `borrowck` query.
let mir = &tcx.mir_validated(def_id).borrow();
- let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(def_id);
let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
// Some in `borrowck_fn` and cleared later
tables: &'a ty::TypeckTables<'tcx>,
- region_maps: Rc<RegionMaps<'tcx>>,
+ region_maps: Rc<RegionMaps>,
owner_def_id: DefId,
}
/// cases, notably method arguments, the loan may be introduced
/// only later, once it comes into scope. See also
/// `GatherLoanCtxt::compute_gen_scope`.
- gen_scope: region::CodeExtent<'tcx>,
+ gen_scope: region::CodeExtent,
/// kill_scope indicates when the loan goes out of scope. This is
/// either when the lifetime expires or when the local variable
/// which roots the loan-path goes out of scope, whichever happens
/// faster. See also `GatherLoanCtxt::compute_kill_scope`.
- kill_scope: region::CodeExtent<'tcx>,
+ kill_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
}
}
impl<'a, 'tcx> LoanPath<'tcx> {
- pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent<'tcx> {
+ pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent {
match self.kind {
LpVar(local_id) => bccx.region_maps.var_scope(local_id),
LpUpvar(upvar_id) => {
let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx);
- bccx.tcx.node_extent(block_id)
+ region::CodeExtent::Misc(block_id)
}
LpDowncast(ref base, _) |
LpExtend(ref base, ..) => base.kill_scope(bccx),
match (&err.code, &err.cause) {
(&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _),
&BorrowViolation(euv::ClosureCapture(span))) |
+ (&err_out_of_scope(&ty::ReScope(_), &ty::ReEarlyBound(..), _),
+ &BorrowViolation(euv::ClosureCapture(span))) |
(&err_out_of_scope(&ty::ReScope(_), &ty::ReFree(..), _),
&BorrowViolation(euv::ClosureCapture(span))) => {
return self.report_out_of_scope_escaping_closure_capture(&err, span);
// except according to those terms.
#![crate_name = "rustc_borrowck"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(associated_consts)]
#![feature(nonzero)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
b: hir::BodyId, s: Span, id: ast::NodeId) {
intravisit::walk_fn(self, fk, fd, b, s, id);
- let region_context = self.tcx.hir.local_def_id(id);
- let region_maps = self.tcx.region_maps(region_context);
+ let def_id = self.tcx.hir.local_def_id(id);
MatchVisitor {
tcx: self.tcx,
tables: self.tcx.body_tables(b),
- region_maps: ®ion_maps,
- param_env: &ty::ParameterEnvironment::for_item(self.tcx, id)
+ region_maps: &self.tcx.region_maps(def_id),
+ param_env: &self.tcx.parameter_environment(def_id)
}.visit_body(self.tcx.hir.body(b));
}
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
param_env: &'a ty::ParameterEnvironment<'tcx>,
- region_maps: &'a RegionMaps<'tcx>,
+ region_maps: &'a RegionMaps,
}
impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_const_eval"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(box_patterns)]
#![feature(const_fn)]
#![feature(i128_type)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate arena;
#[macro_use] extern crate syntax;
#[macro_use] extern crate log;
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_const_math"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(const_fn)]
#![feature(i128)]
#![feature(i128_type)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate syntax;
extern crate serialize as rustc_serialize; // used by deriving
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_data_structures"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(shared)]
#![feature(collections_range)]
#![feature(nonzero)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(fn_traits)]
#![feature(untagged_unions)]
#![feature(manually_drop)]
#![feature(struct_field_attributes)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
"static item recursion checking",
|| static_recursion::check_crate(sess, &hir_map))?;
- let index = stability::Index::new(&hir_map);
+ let index = stability::Index::new(&sess);
let mut local_providers = ty::maps::Providers::default();
borrowck::provide(&mut local_providers);
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_driver"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(set_stdio)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate arena;
extern crate getopts;
node: ast::MetaItemKind::Word,
span: DUMMY_SP,
});
- if !allow_unstable_cfg && gated_cfg.is_some() {
- continue;
+
+ // Note that crt-static is a specially recognized cfg
+ // directive that's printed out here as part of
+ // rust-lang/rust#37406, but in general the
+ // `target_feature` cfg is gated under
+ // rust-lang/rust#29717. For now this is just
+ // specifically allowing the crt-static cfg and that's
+ // it, this is intended to get into Cargo and then go
+ // through to build scripts.
+ let value = value.as_ref().map(|s| s.as_str());
+ let value = value.as_ref().map(|s| s.as_ref());
+ if name != "target_feature" || value != Some("crt-static") {
+ if !allow_unstable_cfg && gated_cfg.is_some() {
+ continue;
+ }
}
- cfgs.push(if let &Some(ref value) = value {
+ cfgs.push(if let Some(value) = value {
format!("{}=\"{}\"", name, value)
} else {
format!("{}", name)
use llvm::LLVMRustHasFeature;
use rustc::session::Session;
use rustc_trans::back::write::create_target_machine;
-use syntax::feature_gate::UnstableFeatures;
use syntax::symbol::Symbol;
use libc::c_char;
}
let requested_features = sess.opts.cg.target_feature.split(',');
- let unstable_options = sess.opts.debugging_opts.unstable_options;
- let is_nightly = UnstableFeatures::from_environment().is_nightly_build();
let found_negative = requested_features.clone().any(|r| r == "-crt-static");
let found_positive = requested_features.clone().any(|r| r == "+crt-static");
found_positive
};
- // If we switched from the default then that's only allowed on nightly, so
- // gate that here.
- if (found_positive || found_negative) && (!is_nightly || !unstable_options) {
- sess.fatal("specifying the `crt-static` target feature is only allowed \
- on the nightly channel with `-Z unstable-options` passed \
- as well");
- }
-
if crt_static {
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
}
use rustc::middle::lang_items;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::region::{CodeExtent, RegionMaps};
-use rustc::middle::region::CodeExtentData;
use rustc::middle::resolve_lifetime;
use rustc::middle::stability;
use rustc::ty::subst::{Kind, Subst};
struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
infcx: &'a infer::InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a mut RegionMaps<'tcx>,
+ region_maps: &'a mut RegionMaps,
}
struct RH<'a> {
// run just enough stuff to build a tcx:
let lang_items = lang_items::collect_language_items(&sess, &hir_map);
let named_region_map = resolve_lifetime::krate(&sess, &hir_map);
- let index = stability::Index::new(&hir_map);
+ let index = stability::Index::new(&sess);
TyCtxt::create_and_enter(&sess,
ty::maps::Providers::default(),
ty::maps::Providers::default(),
self.infcx.tcx
}
- pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent<'tcx>) {
- let me = self.tcx().intern_code_extent(CodeExtentData::Misc(rh.id));
+ pub fn create_region_hierarchy(&mut self, rh: &RH, parent: CodeExtent) {
+ let me = CodeExtent::Misc(rh.id);
self.region_maps.record_code_extent(me, Some(parent));
for child_rh in rh.sub {
self.create_region_hierarchy(child_rh, me);
// children of 1, etc
let node = ast::NodeId::from_u32;
- let dscope = self.tcx().intern_code_extent(CodeExtentData::DestructionScope(node(1)));
+ let dscope = CodeExtent::DestructionScope(node(1));
self.region_maps.record_code_extent(dscope, None);
self.create_region_hierarchy(&RH {
id: node(1),
pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
let name = Symbol::intern(name);
self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
- index: index,
- name: name,
+ def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
+ index,
+ name,
}))
}
}
pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> {
- let r = ty::ReScope(self.tcx().node_extent(ast::NodeId::from_u32(id)));
+ let r = ty::ReScope(CodeExtent::Misc(ast::NodeId::from_u32(id)));
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize)
}
- pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region<'tcx> {
+ pub fn re_free(&self, id: u32) -> ty::Region<'tcx> {
self.infcx.tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: Some(self.tcx().node_extent(nid)),
+ scope: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
bound_region: ty::BrAnon(id),
}))
}
- pub fn t_rptr_free(&self, nid: u32, id: u32) -> Ty<'tcx> {
- let r = self.re_free(ast::NodeId::from_u32(nid), id);
+ pub fn t_rptr_free(&self, id: u32) -> Ty<'tcx> {
+ let r = self.re_free(id);
self.infcx.tcx.mk_imm_ref(r, self.tcx().types.isize)
}
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
let t_rptr_bound1 = env.t_rptr_late_bound(1);
env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
})
env.create_simple_region_hierarchy();
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize));
fn lub_free_free() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
- let t_rptr_free1 = env.t_rptr_free(1, 1);
- let t_rptr_free2 = env.t_rptr_free(1, 2);
+ let t_rptr_free1 = env.t_rptr_free(1);
+ let t_rptr_free2 = env.t_rptr_free(2);
let t_rptr_static = env.t_rptr_static();
env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
fn glb_free_free_with_common_scope() {
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
- let t_rptr_free1 = env.t_rptr_free(1, 1);
- let t_rptr_free2 = env.t_rptr_free(1, 2);
+ let t_rptr_free1 = env.t_rptr_free(1);
+ let t_rptr_free2 = env.t_rptr_free(2);
let t_rptr_scope = env.t_rptr_scope(1);
env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free2], env.tcx().types.isize),
test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| {
env.create_simple_region_hierarchy();
let t_rptr_bound1 = env.t_rptr_late_bound(1);
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize),
env.t_fn(&[t_rptr_free1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
assert!(!env.t_nil().has_escaping_regions());
- let t_rptr_free1 = env.t_rptr_free(1, 1);
+ let t_rptr_free1 = env.t_rptr_free(1);
assert!(!t_rptr_free1.has_escaping_regions());
let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
// except according to those terms.
use CodeSuggestion;
+use Substitution;
use Level;
use RenderSpan;
use std::fmt;
pub code: Option<String>,
pub span: MultiSpan,
pub children: Vec<SubDiagnostic>,
- pub suggestion: Option<CodeSuggestion>,
+ pub suggestions: Vec<CodeSuggestion>,
}
/// For example a note attached to an error.
code: code,
span: MultiSpan::new(),
children: vec![],
- suggestion: None,
+ suggestions: vec![],
}
}
///
/// See `diagnostic::CodeSuggestion` for more information.
pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
- assert!(self.suggestion.is_none());
- self.suggestion = Some(CodeSuggestion {
- msp: sp.into(),
- substitutes: vec![suggestion],
+ self.suggestions.push(CodeSuggestion {
+ substitution_parts: vec![Substitution {
+ span: sp,
+ substitutions: vec![suggestion],
+ }],
+ msg: msg.to_owned(),
+ });
+ self
+ }
+
+ pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
+ self.suggestions.push(CodeSuggestion {
+ substitution_parts: vec![Substitution {
+ span: sp,
+ substitutions: suggestions,
+ }],
msg: msg.to_owned(),
});
self
self.handler.emitter.borrow_mut().emit(&self);
self.cancel();
- self.handler.panic_if_treat_err_as_bug();
+
+ if self.level == Level::Error {
+ self.handler.panic_if_treat_err_as_bug();
+ }
// if self.is_fatal() {
// panic!(FatalError);
msg: &str,
suggestion: String)
-> &mut Self);
+ forward!(pub fn span_suggestions(&mut self,
+ sp: Span,
+ msg: &str,
+ suggestions: Vec<String>)
+ -> &mut Self);
forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
forward!(pub fn code(&mut self, s: String) -> &mut Self);
let mut primary_span = db.span.clone();
let mut children = db.children.clone();
- if let Some(sugg) = db.suggestion.clone() {
- assert_eq!(sugg.msp.primary_spans().len(), sugg.substitutes.len());
- // don't display multispans as labels
- if sugg.substitutes.len() == 1 &&
+ if let Some((sugg, rest)) = db.suggestions.split_first() {
+ if rest.is_empty() &&
+ // don't display multipart suggestions as labels
+ sugg.substitution_parts.len() == 1 &&
+ // don't display multi-suggestions as labels
+ sugg.substitutions() == 1 &&
// don't display long messages as labels
sugg.msg.split_whitespace().count() < 10 &&
// don't display multiline suggestions as labels
- sugg.substitutes[0].find('\n').is_none() {
- let msg = format!("help: {} `{}`", sugg.msg, sugg.substitutes[0]);
- primary_span.push_span_label(sugg.msp.primary_spans()[0], msg);
+ sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
+ let substitution = &sugg.substitution_parts[0].substitutions[0];
+ let msg = format!("help: {} `{}`", sugg.msg, substitution);
+ primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
} else {
- children.push(SubDiagnostic {
- level: Level::Help,
- message: Vec::new(),
- span: MultiSpan::new(),
- render_span: Some(Suggestion(sugg)),
- });
+ // if there are multiple suggestions, print them all in full
+ // to be consistent. We could try to figure out if we can
+ // make one (or the first one) inline, but that would give
+ // undue importance to a semi-random suggestion
+ for sugg in &db.suggestions {
+ children.push(SubDiagnostic {
+ level: Level::Help,
+ message: Vec::new(),
+ span: MultiSpan::new(),
+ render_span: Some(Suggestion(sugg.clone())),
+ });
+ }
}
}
/// maximum number of lines we will print for each error; arbitrary.
pub const MAX_HIGHLIGHT_LINES: usize = 6;
+/// maximum number of suggestions to be shown
+///
+/// Arbitrary, but taken from trait import suggestion limit
+pub const MAX_SUGGESTIONS: usize = 4;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ColorConfig {
multiline_depth: usize,
}
-
-/// Do not use this for messages that end in `\n` – use `println_maybe_styled` instead. See
-/// `EmitterWriter::print_maybe_styled` for details.
-macro_rules! print_maybe_styled {
- ($dst: expr, $style: expr, $($arg: tt)*) => {
- $dst.print_maybe_styled(format_args!($($arg)*), $style, false)
- }
-}
-
-macro_rules! println_maybe_styled {
- ($dst: expr, $style: expr, $($arg: tt)*) => {
- $dst.print_maybe_styled(format_args!($($arg)*), $style, true)
- }
-}
-
impl EmitterWriter {
pub fn stderr(color_config: ColorConfig, code_map: Option<Rc<CodeMapper>>) -> EmitterWriter {
if color_config.use_color() {
-> io::Result<()> {
use std::borrow::Borrow;
- let primary_span = suggestion.msp.primary_span().unwrap();
+ let primary_span = suggestion.substitution_spans().next().unwrap();
if let Some(ref cm) = self.cm {
let mut buffer = StyledBuffer::new();
- buffer.append(0, &level.to_string(), Style::Level(level.clone()));
- buffer.append(0, ": ", Style::HeaderMsg);
- self.msg_to_buffer(&mut buffer,
- &[(suggestion.msg.to_owned(), Style::NoStyle)],
- max_line_num_len,
- "suggestion",
- Some(Style::HeaderMsg));
-
let lines = cm.span_to_lines(primary_span).unwrap();
assert!(!lines.lines.is_empty());
- let complete = suggestion.splice_lines(cm.borrow());
+ buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+ buffer.append(0, ": ", Style::HeaderMsg);
+ self.msg_to_buffer(&mut buffer,
+ &[(suggestion.msg.to_owned(), Style::NoStyle)],
+ max_line_num_len,
+ "suggestion",
+ Some(Style::HeaderMsg));
- // print the suggestion without any line numbers, but leave
- // space for them. This helps with lining up with previous
- // snippets from the actual error being reported.
- let mut lines = complete.lines();
+ let suggestions = suggestion.splice_lines(cm.borrow());
let mut row_num = 1;
- for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
- draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
- buffer.append(row_num, line, Style::NoStyle);
- row_num += 1;
- }
+ for complete in suggestions.iter().take(MAX_SUGGESTIONS) {
+
+ // print the suggestion without any line numbers, but leave
+ // space for them. This helps with lining up with previous
+ // snippets from the actual error being reported.
+ let mut lines = complete.lines();
+ for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+ draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
+ buffer.append(row_num, line, Style::NoStyle);
+ row_num += 1;
+ }
- // if we elided some lines, add an ellipsis
- if let Some(_) = lines.next() {
- buffer.append(row_num, "...", Style::NoStyle);
+ // if we elided some lines, add an ellipsis
+ if let Some(_) = lines.next() {
+ buffer.append(row_num, "...", Style::NoStyle);
+ }
+ }
+ if suggestions.len() > MAX_SUGGESTIONS {
+ let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
+ buffer.append(row_num, &msg, Style::NoStyle);
}
emit_to_destination(&buffer.render(), level, &mut self.dst)?;
}
// except according to those terms.
#![crate_name = "rustc_errors"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(custom_attribute)]
#![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(range_contains)]
#![feature(libc)]
+#![feature(conservative_impl_trait)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate term;
extern crate libc;
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct CodeSuggestion {
- pub msp: MultiSpan,
- pub substitutes: Vec<String>,
+ /// Each substitute can have multiple variants due to multiple
+ /// applicable suggestions
+ ///
+ /// `foo.bar` might be replaced with `a.b` or `x.y` by replacing
+ /// `foo` and `bar` on their own:
+ ///
+ /// ```
+ /// vec![
+ /// (0..3, vec!["a", "x"]),
+ /// (4..7, vec!["b", "y"]),
+ /// ]
+ /// ```
+ ///
+ /// or by replacing the entire span:
+ ///
+ /// ```
+ /// vec![(0..7, vec!["a.b", "x.y"])]
+ /// ```
+ pub substitution_parts: Vec<Substitution>,
pub msg: String,
}
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+/// See the docs on `CodeSuggestion::substitutions`
+pub struct Substitution {
+ pub span: Span,
+ pub substitutions: Vec<String>,
+}
+
pub trait CodeMapper {
fn lookup_char_pos(&self, pos: BytePos) -> Loc;
fn span_to_lines(&self, sp: Span) -> FileLinesResult;
}
impl CodeSuggestion {
- /// Returns the assembled code suggestion.
- pub fn splice_lines(&self, cm: &CodeMapper) -> String {
+ /// Returns the number of substitutions
+ fn substitutions(&self) -> usize {
+ self.substitution_parts[0].substitutions.len()
+ }
+
+ /// Returns the number of substitutions
+ pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
+ self.substitution_parts.iter().map(|sub| sub.span)
+ }
+
+ /// Returns the assembled code suggestions.
+ pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> {
use syntax_pos::{CharPos, Loc, Pos};
fn push_trailing(buf: &mut String,
}
}
- let mut primary_spans = self.msp.primary_spans().to_owned();
-
- assert_eq!(primary_spans.len(), self.substitutes.len());
- if primary_spans.is_empty() {
- return format!("");
+ if self.substitution_parts.is_empty() {
+ return vec![String::new()];
}
+ let mut primary_spans: Vec<_> = self.substitution_parts
+ .iter()
+ .map(|sub| (sub.span, &sub.substitutions))
+ .collect();
+
// Assumption: all spans are in the same file, and all spans
// are disjoint. Sort in ascending order.
- primary_spans.sort_by_key(|sp| sp.lo);
+ primary_spans.sort_by_key(|sp| sp.0.lo);
// Find the bounding span.
- let lo = primary_spans.iter().map(|sp| sp.lo).min().unwrap();
- let hi = primary_spans.iter().map(|sp| sp.hi).min().unwrap();
+ let lo = primary_spans.iter().map(|sp| sp.0.lo).min().unwrap();
+ let hi = primary_spans.iter().map(|sp| sp.0.hi).min().unwrap();
let bounding_span = Span {
lo: lo,
hi: hi,
prev_hi.col = CharPos::from_usize(0);
let mut prev_line = fm.get_line(lines.lines[0].line_index);
- let mut buf = String::new();
+ let mut bufs = vec![String::new(); self.substitutions()];
- for (sp, substitute) in primary_spans.iter().zip(self.substitutes.iter()) {
+ for (sp, substitutes) in primary_spans {
let cur_lo = cm.lookup_char_pos(sp.lo);
- if prev_hi.line == cur_lo.line {
- push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo));
- } else {
- push_trailing(&mut buf, prev_line, &prev_hi, None);
- // push lines between the previous and current span (if any)
- for idx in prev_hi.line..(cur_lo.line - 1) {
- if let Some(line) = fm.get_line(idx) {
- buf.push_str(line);
- buf.push('\n');
+ for (buf, substitute) in bufs.iter_mut().zip(substitutes) {
+ if prev_hi.line == cur_lo.line {
+ push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo));
+ } else {
+ push_trailing(buf, prev_line, &prev_hi, None);
+ // push lines between the previous and current span (if any)
+ for idx in prev_hi.line..(cur_lo.line - 1) {
+ if let Some(line) = fm.get_line(idx) {
+ buf.push_str(line);
+ buf.push('\n');
+ }
+ }
+ if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
+ buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
}
}
- if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
- buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
- }
+ buf.push_str(substitute);
}
- buf.push_str(substitute);
prev_hi = cm.lookup_char_pos(sp.hi);
prev_line = fm.get_line(prev_hi.line - 1);
}
- push_trailing(&mut buf, prev_line, &prev_hi, None);
- // remove trailing newline
- buf.pop();
- buf
+ for buf in &mut bufs {
+ // if the replacement already ends with a newline, don't print the next line
+ if !buf.ends_with('\n') {
+ push_trailing(buf, prev_line, &prev_hi, None);
+ }
+ // remove trailing newline
+ buf.pop();
+ }
+ bufs
}
}
//! Support for serializing the dep-graph and reloading it.
#![crate_name = "rustc_incremental"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(rand)]
#![feature(conservative_impl_trait)]
#![feature(sort_unstable)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate graphviz;
#[macro_use] extern crate rustc;
extern crate rustc_data_structures;
traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
trait_ref.to_poly_trait_predicate());
- // unwrap() is ok here b/c `method` is the method
- // defined in this crate whose body we are
- // checking, so it's always local
- let node_id = tcx.hir.as_local_node_id(method.def_id).unwrap();
-
- let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
+ let param_env = tcx.parameter_environment(method.def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut selcx = traits::SelectionContext::new(&infcx);
match selcx.select(&obligation) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
if let hir::ItemUnion(ref vdata, _) = item.node {
- let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id);
+ let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
for field in vdata.fields() {
let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
if field_ty.needs_drop(ctx.tcx, param_env) {
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_lint"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(i128_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(slice_patterns)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate syntax;
#![allow(dead_code)]
#![crate_name = "rustc_llvm"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(concat_idents)]
#![feature(libc)]
#![feature(link_args)]
-#![feature(staged_api)]
-#![feature(rustc_private)]
#![feature(static_nobundle)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate libc;
#[macro_use]
#[no_link]
self.root.disambiguator
}
- pub fn is_staged_api(&self, dep_graph: &DepGraph) -> bool {
- for attr in self.get_item_attrs(CRATE_DEF_INDEX, dep_graph).iter() {
- if attr.path == "stable" || attr.path == "unstable" {
- return true;
- }
- }
- false
- }
-
pub fn is_allocator(&self, dep_graph: &DepGraph) -> bool {
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, dep_graph);
attr::contains_name(&attrs, "allocator")
self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph)
}
- fn is_staged_api(&self, cnum: CrateNum) -> bool
- {
- self.get_crate_data(cnum).is_staged_api(&self.dep_graph)
- }
-
fn is_allocator(&self, cnum: CrateNum) -> bool
{
self.get_crate_data(cnum).is_allocator(&self.dep_graph)
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::middle::lang_items;
-use rustc::middle::region;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;
}
}
-impl<'a, 'tcx> SpecializedDecoder<region::CodeExtent<'tcx>> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<region::CodeExtent<'tcx>, Self::Error> {
- Ok(self.tcx().intern_code_extent(Decodable::decode(self)?))
- }
-}
-
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
// except according to those terms.
#![crate_name = "rustc_metadata"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(proc_macro_internals)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(specialization)]
-#![feature(staged_api)]
#![feature(discriminant_value)]
+#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate log;
temp: &Lvalue<'tcx>,
constant: Constant<'tcx>) {
self.push_assign(block, source_info, temp,
- Rvalue::Use(Operand::Constant(constant)));
+ Rvalue::Use(Operand::Constant(box constant)));
}
pub fn push_assign_unit(&mut self,
source_info: SourceInfo,
lvalue: &Lvalue<'tcx>) {
self.push_assign(block, source_info, lvalue, Rvalue::Aggregate(
- AggregateKind::Tuple, vec![]
+ box AggregateKind::Tuple, vec![]
));
}
/// The operand is known to be live until the end of `scope`.
pub fn as_operand<M>(&mut self,
block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: M) -> BlockAnd<Operand<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
fn expr_as_operand(&mut self,
mut block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Operand<'tcx>> {
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
match category {
Category::Constant => {
let constant = this.as_constant(expr);
- block.and(Operand::Constant(constant))
+ block.and(Operand::Constant(box constant))
}
Category::Lvalue |
Category::Rvalue(..) => {
}
/// Compile `expr`, yielding an rvalue.
- pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent<'tcx>>, expr: M)
+ pub fn as_rvalue<M>(&mut self, block: BasicBlock, scope: Option<CodeExtent>, expr: M)
-> BlockAnd<Rvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
fn expr_as_rvalue(&mut self,
mut block: BasicBlock,
- scope: Option<CodeExtent<'tcx>>,
+ scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Rvalue<'tcx>> {
debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
.map(|f| unpack!(block = this.as_operand(block, scope, f)))
.collect();
- block.and(Rvalue::Aggregate(AggregateKind::Array(el_ty), fields))
+ block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields))
}
ExprKind::Tuple { fields } => { // see (*) above
// first process the set of fields
.map(|f| unpack!(block = this.as_operand(block, scope, f)))
.collect();
- block.and(Rvalue::Aggregate(AggregateKind::Tuple, fields))
+ block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
}
ExprKind::Closure { closure_id, substs, upvars } => { // see (*) above
let upvars =
upvars.into_iter()
.map(|upvar| unpack!(block = this.as_operand(block, scope, upvar)))
.collect();
- block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
+ block.and(Rvalue::Aggregate(box AggregateKind::Closure(closure_id, substs), upvars))
}
ExprKind::Adt {
adt_def, variant_index, substs, fields, base
field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
};
- let adt = AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
+ let adt =
+ box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
block.and(Rvalue::Aggregate(adt, fields))
}
ExprKind::Assign { .. } |
/// up rvalues so as to freeze the value that will be consumed.
pub fn as_temp<M>(&mut self,
block: BasicBlock,
- temp_lifetime: Option<CodeExtent<'tcx>>,
+ temp_lifetime: Option<CodeExtent>,
expr: M)
-> BlockAnd<Lvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
fn expr_as_temp(&mut self,
mut block: BasicBlock,
- temp_lifetime: Option<CodeExtent<'tcx>>,
+ temp_lifetime: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Lvalue<'tcx>> {
debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
this.cfg.push(block, Statement {
source_info: source_info,
kind: StatementKind::InlineAsm {
- asm: asm.clone(),
+ asm: box asm.clone(),
outputs: outputs,
inputs: inputs
},
let eq_block = self.cfg.start_new_block();
let cleanup = self.diverge_cleanup();
self.cfg.terminate(block, source_info, TerminatorKind::Call {
- func: Operand::Constant(Constant {
+ func: Operand::Constant(box Constant {
span: test.span,
ty: mty,
literal: method
ty: Ty<'tcx>,
literal: Literal<'tcx>)
-> Operand<'tcx> {
- let constant = Constant {
+ let constant = box Constant {
span: span,
ty: ty,
literal: literal,
}
pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
- Rvalue::Aggregate(AggregateKind::Tuple, vec![])
+ Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
}
// Returns a zero literal operand for the appropriate type, works for
use hair::Pattern;
use rustc::hir;
use rustc::hir::def_id::DefId;
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
use rustc::mir::*;
use rustc::mir::transform::MirSource;
use rustc::mir::visit::MutVisitor;
{
let span = tcx.hir.span(ctor_id);
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
- let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
+ let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id));
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
let (mut mir, src) =
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
-> Ty<'tcx> {
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
+ let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
let region = ty::ReFree(ty::FreeRegion {
- scope: Some(tcx.item_extent(body_id.node_id)),
+ scope: closure_def_id,
bound_region: ty::BoundRegion::BrEnv,
});
let region = tcx.mk_region(region);
- match tcx.closure_kind(tcx.hir.local_def_id(closure_expr_id)) {
+ match tcx.closure_kind(closure_def_id) {
ty::ClosureKind::Fn =>
tcx.mk_ref(region,
ty::TypeAndMut { ty: closure_ty,
let span = tcx.hir.span(fn_id);
let mut builder = Builder::new(hir.clone(), span, arguments.len(), return_ty);
- let call_site_extent =
- tcx.intern_code_extent(
- CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body.value.id });
- let arg_extent =
- tcx.intern_code_extent(
- CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.value.id });
+ let call_site_extent = CodeExtent::CallSiteScope(body.id());
+ let arg_extent = CodeExtent::ParameterScope(body.id());
let mut block = START_BLOCK;
unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
unpack!(block = builder.in_scope(arg_extent, block, |builder| {
let span = tcx.hir.span(owner_id);
let mut builder = Builder::new(hir.clone(), span, 0, ty);
- let extent = hir.region_maps.temporary_scope(tcx, ast_expr.id)
- .unwrap_or(tcx.item_extent(owner_id));
let mut block = START_BLOCK;
- let _ = builder.in_scope(extent, block, |builder| {
- let expr = builder.hir.mirror(ast_expr);
- unpack!(block = builder.into(&Lvalue::Local(RETURN_POINTER), block, expr));
+ let expr = builder.hir.mirror(ast_expr);
+ unpack!(block = builder.into_expr(&Lvalue::Local(RETURN_POINTER), block, expr));
- let source_info = builder.source_info(span);
- let return_block = builder.return_block();
- builder.cfg.terminate(block, source_info,
- TerminatorKind::Goto { target: return_block });
- builder.cfg.terminate(return_block, source_info,
- TerminatorKind::Return);
+ let source_info = builder.source_info(span);
+ builder.cfg.terminate(block, source_info, TerminatorKind::Return);
- return_block.unit()
- });
+ // Constants can't `return` so a return block should not be created.
+ assert_eq!(builder.cached_return_block, None);
builder.finish(vec![], ty)
}
fn args_and_body(&mut self,
mut block: BasicBlock,
arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
- argument_extent: CodeExtent<'tcx>,
+ argument_extent: CodeExtent,
ast_body: &'gcx hir::Expr)
-> BlockAnd<()>
{
*/
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
-use rustc::middle::region::{CodeExtent, CodeExtentData};
+use rustc::middle::region::CodeExtent;
use rustc::middle::lang_items;
use rustc::middle::const_val::ConstVal;
use rustc::ty::subst::{Kind, Subst};
visibility_scope: VisibilityScope,
/// the extent of this scope within source code.
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
/// Whether there's anything to do for the cleanup path, that is,
/// when unwinding through this scope. This includes destructors,
free: Option<FreeData<'tcx>>,
/// The cache for drop chain on “normal” exit into a particular BasicBlock.
- cached_exits: FxHashMap<(BasicBlock, CodeExtent<'tcx>), BasicBlock>,
+ cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>,
}
struct DropData<'tcx> {
#[derive(Clone, Debug)]
pub struct BreakableScope<'tcx> {
/// Extent of the loop
- pub extent: CodeExtent<'tcx>,
+ pub extent: CodeExtent,
/// Where the body of the loop begins. `None` if block
pub continue_block: Option<BasicBlock>,
/// Block to branch into when the loop or block terminates (either by being `break`-en out
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
pub fn in_scope<F, R>(&mut self,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock,
f: F)
-> BlockAnd<R>
/// scope and call `pop_scope` afterwards. Note that these two
/// calls must be paired; using `in_scope` as a convenience
/// wrapper maybe preferable.
- pub fn push_scope(&mut self, extent: CodeExtent<'tcx>) {
+ pub fn push_scope(&mut self, extent: CodeExtent) {
debug!("push_scope({:?})", extent);
let vis_scope = self.visibility_scope;
self.scopes.push(Scope {
/// drops onto the end of `block` that are needed. This must
/// match 1-to-1 with `push_scope`.
pub fn pop_scope(&mut self,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock)
-> BlockAnd<()> {
debug!("pop_scope({:?}, {:?})", extent, block);
/// module comment for details.
pub fn exit_scope(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
mut block: BasicBlock,
target: BasicBlock) {
debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
/// resolving `break` and `continue`.
pub fn find_breakable_scope(&mut self,
span: Span,
- label: CodeExtent<'tcx>)
+ label: CodeExtent)
-> &mut BreakableScope<'tcx> {
// find the loop-scope with the correct id
self.breakable_scopes.iter_mut()
/// Returns the extent of the scope which should be exited by a
/// return.
- pub fn extent_of_return_scope(&self) -> CodeExtent<'tcx> {
+ pub fn extent_of_return_scope(&self) -> CodeExtent {
// The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
// We want `scopes[1]`, which is the `ParameterScope`.
assert!(self.scopes.len() >= 2);
- assert!(match *self.scopes[1].extent {
- CodeExtentData::ParameterScope { .. } => true,
+ assert!(match self.scopes[1].extent {
+ CodeExtent::ParameterScope(_) => true,
_ => false,
});
self.scopes[1].extent
/// Returns the topmost active scope, which is known to be alive until
/// the next scope expression.
- pub fn topmost_scope(&self) -> CodeExtent<'tcx> {
+ pub fn topmost_scope(&self) -> CodeExtent {
self.scopes.last().expect("topmost_scope: no scopes present").extent
}
/// `extent`.
pub fn schedule_drop(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
lvalue: &Lvalue<'tcx>,
lvalue_ty: Ty<'tcx>) {
let needs_drop = self.hir.needs_drop(lvalue_ty);
/// There may only be one “free” scheduled in any given scope.
pub fn schedule_box_free(&mut self,
span: Span,
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
value: &Lvalue<'tcx>,
item_ty: Ty<'tcx>) {
for scope in self.scopes.iter_mut().rev() {
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]);
TerminatorKind::Call {
- func: Operand::Constant(Constant {
+ func: Operand::Constant(box Constant {
span: data.span,
ty: tcx.type_of(free_func).subst(tcx, substs),
literal: Literal::Value {
use hair::*;
use hair::cx::Cx;
use hair::cx::to_ref::ToRef;
-use rustc::middle::region::{BlockRemainder, CodeExtentData};
+use rustc::middle::region::{BlockRemainder, CodeExtent};
use rustc::hir;
use syntax::ast;
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
Block {
targeted_by_break: self.targeted_by_break,
- extent: cx.tcx.node_extent(self.id),
+ extent: CodeExtent::Misc(self.id),
span: self.span,
stmts: stmts,
expr: self.expr.to_ref(),
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Expr {
- scope: cx.tcx.node_extent(id),
+ scope: CodeExtent::Misc(id),
expr: expr.to_ref(),
},
})))
// ignore for purposes of the MIR
}
hir::DeclLocal(ref local) => {
- let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
+ let remainder_extent = CodeExtent::Remainder(BlockRemainder {
block: block_id,
first_statement_index: index as u32,
});
- let remainder_extent =
- cx.tcx.intern_code_extent(remainder_extent);
let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat);
result.push(StmtRef::Mirror(Box::new(Stmt {
span: stmt.span,
kind: StmtKind::Let {
remainder_scope: remainder_extent,
- init_scope: cx.tcx.node_extent(id),
+ init_scope: CodeExtent::Misc(id),
pattern: pattern,
initializer: local.init.to_ref(),
},
block: &'tcx hir::Block)
-> ExprRef<'tcx> {
let block_ty = cx.tables().node_id_to_type(block.id);
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, block.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(block.id);
let expr = Expr {
ty: block_ty,
temp_lifetime: temp_lifetime,
use hair::cx::Cx;
use hair::cx::block;
use hair::cx::to_ref::ToRef;
-use rustc::hir::map;
use rustc::hir::def::{Def, CtorKind};
use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, AdtKind, VariantDef, Ty};
type Output = Expr<'tcx>;
fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, self.id);
- let expr_extent = cx.tcx.node_extent(self.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(self.id);
+ let expr_extent = CodeExtent::Misc(self.id);
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
expr: &'tcx hir::Expr)
-> Expr<'tcx> {
let expr_ty = cx.tables().expr_ty(expr);
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let kind = match expr.node {
// Here comes the interesting stuff:
match dest.target_id {
hir::ScopeTarget::Block(target_id) |
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break {
- label: cx.tcx.node_extent(target_id),
+ label: CodeExtent::Misc(target_id),
value: value.to_ref(),
},
hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
match dest.target_id {
hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"),
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue {
- label: cx.tcx.node_extent(loop_id),
+ label: CodeExtent::Misc(loop_id),
},
hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
bug!("invalid loop id for continue: {}", err)
hir::ExprBox(ref value) => {
ExprKind::Box {
value: value.to_ref(),
- value_extents: cx.tcx.node_extent(value.id),
+ value_extents: CodeExtent::Misc(value.id),
}
}
hir::ExprArray(ref fields) => ExprKind::Array { fields: fields.to_ref() },
method_call: ty::MethodCall)
-> Expr<'tcx> {
let callee = cx.tables().method_map[&method_call];
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
expr: &'tcx hir::Expr,
def: Def)
-> ExprKind<'tcx> {
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
match def {
Def::Local(def_id) => {
closure_expr_id);
let var_ty = cx.tables().node_id_to_type(id_var);
- let body_id = match cx.tcx.hir.find(closure_expr_id) {
- Some(map::NodeExpr(expr)) => {
- match expr.node {
- hir::ExprClosure(.., body, _) => body.node_id,
- _ => {
- span_bug!(expr.span, "closure expr is not a closure expr");
- }
- }
- }
- _ => {
- span_bug!(expr.span, "ast-map has garbage for closure expr");
- }
- };
-
// FIXME free regions in closures are not right
let closure_ty = cx.tables().node_id_to_type(closure_expr_id);
// FIXME we're just hard-coding the idea that the
// signature will be &self or &mut self and hence will
// have a bound region with number 0
+ let closure_def_id = cx.tcx.hir.local_def_id(closure_expr_id);
let region = ty::ReFree(ty::FreeRegion {
- scope: Some(cx.tcx.node_extent(body_id)),
+ scope: closure_def_id,
bound_region: ty::BoundRegion::BrAnon(0),
});
let region = cx.tcx.mk_region(region);
- let self_expr = match cx.tcx.closure_kind(cx.tcx.hir.local_def_id(closure_expr_id)) {
+ let self_expr = match cx.tcx.closure_kind(closure_def_id) {
ty::ClosureKind::Fn => {
let ref_closure_ty = cx.tcx.mk_ref(region,
ty::TypeAndMut {
PassArgs::ByRef => {
let region = cx.tcx.node_scope_region(expr.id);
let (temp_lifetime, was_shrunk) =
- cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ cx.region_maps.temporary_scope2(expr.id);
argrefs.extend(args.iter()
.map(|arg| {
let arg_ty = cx.tables().expr_ty_adjusted(arg);
// construct the complete expression `foo()` for the overloaded call,
// which will yield the &T type
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args);
let ref_expr = Expr {
temp_lifetime: temp_lifetime,
closure_expr_id: closure_expr.id,
};
let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
- let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(cx.tcx, closure_expr.id);
+ let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(closure_expr.id);
let var_ty = cx.tables().node_id_to_type(id_var);
let captured_var = Expr {
temp_lifetime: temp_lifetime,
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- pub region_maps: Rc<RegionMaps<'tcx>>,
+ pub region_maps: Rc<RegionMaps>,
constness: hir::Constness,
/// True if this constant/function needs overflow checks.
#[derive(Clone, Debug)]
pub struct Block<'tcx> {
pub targeted_by_break: bool,
- pub extent: CodeExtent<'tcx>,
+ pub extent: CodeExtent,
pub span: Span,
pub stmts: Vec<StmtRef<'tcx>>,
pub expr: Option<ExprRef<'tcx>>,
pub enum StmtKind<'tcx> {
Expr {
/// scope for this statement; may be used as lifetime of temporaries
- scope: CodeExtent<'tcx>,
+ scope: CodeExtent,
/// expression being evaluated in this statement
expr: ExprRef<'tcx>,
Let {
/// scope for variables bound in this let; covers this and
/// remaining statements in block
- remainder_scope: CodeExtent<'tcx>,
+ remainder_scope: CodeExtent,
/// scope for the initialization itself; might be used as
/// lifetime of temporaries
- init_scope: CodeExtent<'tcx>,
+ init_scope: CodeExtent,
/// let <PAT> = ...
pattern: Pattern<'tcx>,
/// lifetime of this expression if it should be spilled into a
/// temporary; should be None only if in a constant context
- pub temp_lifetime: Option<CodeExtent<'tcx>>,
+ pub temp_lifetime: Option<CodeExtent>,
/// whether this temp lifetime was shrunk by #36082.
pub temp_lifetime_was_shrunk: bool,
#[derive(Clone, Debug)]
pub enum ExprKind<'tcx> {
Scope {
- extent: CodeExtent<'tcx>,
+ extent: CodeExtent,
value: ExprRef<'tcx>,
},
Box {
value: ExprRef<'tcx>,
- value_extents: CodeExtent<'tcx>,
+ value_extents: CodeExtent,
},
Call {
ty: ty::Ty<'tcx>,
arg: ExprRef<'tcx>,
},
Break {
- label: CodeExtent<'tcx>,
+ label: CodeExtent,
value: Option<ExprRef<'tcx>>,
},
Continue {
- label: CodeExtent<'tcx>,
+ label: CodeExtent,
},
Return {
value: Option<ExprRef<'tcx>>,
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![deny(warnings)]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(i128_type)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(placement_in_syntax)]
#![feature(collection_placement)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
#[macro_use] extern crate log;
extern crate graphviz as dot;
#[macro_use]
use rustc::mir::*;
use rustc::mir::transform::MirSource;
use rustc::ty::{self, Ty};
-use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::ty::maps::Providers;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
{
debug!("make_shim({:?})", instance);
let did = instance.def_id();
- let span = tcx.def_span(did);
- let param_env = tcx.construct_parameter_environment(span, did, None);
+ let param_env = tcx.parameter_environment(did);
let mut result = match instance {
ty::InstanceDef::Item(..) =>
build_call_shim(
tcx,
- ¶m_env,
def_id,
adjustment,
CallKind::Indirect,
// trans::mir knows to turn to an actual virtual call.
build_call_shim(
tcx,
- ¶m_env,
def_id,
Adjustment::Identity,
CallKind::Direct(def_id),
build_call_shim(
tcx,
- ¶m_env,
call_once,
Adjustment::RefMut,
CallKind::Direct(call_mut),
let substs = if let Some(ty) = ty {
tcx.mk_substs(iter::once(Kind::from(ty)))
} else {
- param_env.free_substs
+ Substs::identity_for_item(tcx, def_id)
};
let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
/// If `untuple_args` is a vec of types, the second argument of the
/// function will be untupled as these types.
fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
def_id: DefId,
rcvr_adjustment: Adjustment,
call_kind: CallKind,
call_kind={:?}, untuple_args={:?})",
def_id, rcvr_adjustment, call_kind, untuple_args);
- let fn_ty = tcx.type_of(def_id).subst(tcx, param_env.free_substs);
+ let fn_ty = tcx.type_of(def_id);
let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
let span = tcx.def_span(def_id);
let (callee, mut args) = match call_kind {
CallKind::Indirect => (rcvr, vec![]),
CallKind::Direct(def_id) => (
- Operand::Constant(Constant {
+ Operand::Constant(box Constant {
span: span,
- ty: tcx.type_of(def_id).subst(tcx, param_env.free_substs),
+ ty: tcx.type_of(def_id),
literal: Literal::Value {
- value: ConstVal::Function(def_id, param_env.free_substs),
+ value: ConstVal::Function(def_id,
+ Substs::identity_for_item(tcx, def_id)),
},
}),
vec![rcvr]
kind: StatementKind::Assign(
Lvalue::Local(RETURN_POINTER),
Rvalue::Aggregate(
- AggregateKind::Adt(adt_def, variant_no, substs, None),
+ box AggregateKind::Adt(adt_def, variant_no, substs, None),
(1..sig.inputs().len()+1).map(|i| {
Operand::Consume(Lvalue::Local(Local::new(i)))
}).collect()
_ => return,
}
- *operand = Operand::Constant(self.constant.clone());
+ *operand = Operand::Constant(box self.constant.clone());
self.uses_replaced += 1
}
}
&Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands),
_ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
};
- let (adt_def, variant, substs) = match agg_kind {
- &AggregateKind::Adt(adt_def, variant, substs, None)
+ let (adt_def, variant, substs) = match **agg_kind {
+ AggregateKind::Adt(adt_def, variant, substs, None)
=> (adt_def, variant, substs),
_ => span_bug!(src_info.span, "expected struct, not {:?}", rhs),
};
&Rvalue::Aggregate(ref kind, ref operands) => (kind, operands),
_ => continue,
};
- let (adt_def, variant) = match kind {
- &AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
+ let (adt_def, variant) = match **kind {
+ AggregateKind::Adt(adt_def, variant, _, None) => (adt_def, variant),
_ => continue,
};
if operands.len() == 0 {
// FIXME: Give a bonus to functions with only a single caller
- let param_env = ty::ParameterEnvironment::for_item(tcx, self.source.item_id());
+ let def_id = tcx.hir.local_def_id(self.source.item_id());
+ let param_env = tcx.parameter_environment(def_id);
let mut first_block = true;
let mut cost = 0;
(if self.keep_original {
rhs.clone()
} else {
- let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]);
+ let unit = Rvalue::Aggregate(box AggregateKind::Tuple, vec![]);
mem::replace(rhs, unit)
}, statement.source_info)
};
fn promote_candidate(mut self, candidate: Candidate) {
let span = self.promoted.span;
- let new_operand = Operand::Constant(Constant {
+ let new_operand = Operand::Constant(box Constant {
span: span,
ty: self.promoted.return_ty,
literal: Literal::Promoted {
}
Rvalue::Aggregate(ref kind, _) => {
- if let AggregateKind::Adt(def, ..) = *kind {
+ if let AggregateKind::Adt(def, ..) = **kind {
if def.has_dtor(self.tcx) {
self.add(Qualif::NEEDS_DROP);
self.deny_drop();
return Qualif::NOT_CONST.bits();
}
- let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
- let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
+ let param_env = tcx.parameter_environment(def_id);
let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
qualifier.qualify_const().bits()
MirSource::Const(_) |
MirSource::Promoted(..) => return
};
- let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(def_id);
if mode == Mode::Fn || mode == Mode::ConstFn {
// This is ugly because Qualifier holds onto mir,
for block in mir.basic_blocks_mut() {
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {
- TerminatorKind::SwitchInt { discr: Operand::Constant(Constant {
+ TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
literal: Literal::Value { ref value }, ..
}), ref values, ref targets, .. } => {
if let Some(ref constint) = value.to_const_int() {
continue
}
},
- TerminatorKind::Assert { target, cond: Operand::Constant(Constant {
+ TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
literal: Literal::Value {
value: ConstVal::Bool(cond)
}, ..
}
}
}
-
fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
match operand {
- &Operand::Constant(Constant {
+ &Operand::Constant(box Constant {
literal: Literal::Value {
value: ConstVal::Function(def_id, _), ..
}, ..
// broken MIR, so try not to report duplicate errors.
return;
}
- let param_env = ty::ParameterEnvironment::for_item(tcx, item_id);
+ let param_env = tcx.parameter_environment(def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut checker = TypeChecker::new(&infcx, item_id);
{
impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
- fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _n: NodeId) {
+ fn visit_mod(&mut self, m: &'v ast::Mod, _s: Span, _a: &[ast::Attribute], _n: NodeId) {
self.record("Mod", Id::None, m);
ast_visit::walk_mod(self, m)
}
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_passes"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(rustc_diagnostic_macros)]
-#![feature(staged_api)]
-#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate rustc;
Rvalue::Aggregate(ref kind, ref _operands) => {
// AggregateKind is not distinguished by visit API, so
// record it. (`super_rvalue` handles `_operands`.)
- self.record(match *kind {
+ self.record(match **kind {
AggregateKind::Array(_) => "AggregateKind::Array",
AggregateKind::Tuple => "AggregateKind::Tuple",
AggregateKind::Adt(..) => "AggregateKind::Adt",
// except according to those terms.
#![crate_name = "rustc_platform_intrinsics"]
-#![unstable(feature = "rustc_private", issue = "27812")]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![deny(warnings)]
#![allow(bad_style)]
//! for more examples.
#![crate_name = "rustc_plugin"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
-#![feature(staged_api)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use] extern crate syntax;
// except according to those terms.
#![crate_name = "rustc_privacy"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate rustc;
#[macro_use] extern crate syntax;
view_path.span,
ResolutionError::SelfImportsOnlyAllowedWithin);
} else if source_name == "$crate" && full_path.segments.len() == 1 {
- let crate_root = self.resolve_crate_var(source.ctxt);
+ let crate_root = self.resolve_crate_var(source.ctxt, item.span);
let crate_name = match crate_root.kind {
ModuleKind::Def(_, name) => name,
ModuleKind::Block(..) => unreachable!(),
// n.b. we don't need to look at the path option here, because cstore already did
let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
- let module = self.get_extern_crate_root(crate_id);
+ let module = self.get_extern_crate_root(crate_id, item.span);
self.populate_module_if_necessary(module);
let used = self.process_legacy_macro_imports(item, module, expansion);
let binding =
no_implicit_prelude: parent.no_implicit_prelude || {
attr::contains_name(&item.attrs, "no_implicit_prelude")
},
- ..ModuleData::new(Some(parent), module_kind, def_id)
+ ..ModuleData::new(Some(parent), module_kind, def_id, item.span)
});
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.module_map.insert(def_id, module);
ItemKind::Enum(ref enum_definition, _) => {
let def = Def::Enum(self.definitions.local_def_id(item.id));
let module_kind = ModuleKind::Def(def, ident.name);
- let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ module_kind,
+ parent.normal_ancestor_id,
+ item.span);
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
for variant in &(*enum_definition).variants {
// Add all the items within to a new module.
let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
- let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ module_kind,
+ parent.normal_ancestor_id,
+ item.span);
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.current_module = module;
}
fn build_reduced_graph_for_block(&mut self, block: &Block) {
let parent = self.current_module;
if self.block_needs_anonymous_module(block) {
- let module =
- self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ ModuleKind::Block(block.id),
+ parent.normal_ancestor_id,
+ block.span);
self.block_map.insert(block.id, module);
self.current_module = module; // Descend into the block.
}
let def = child.def;
let def_id = def.def_id();
let vis = self.session.cstore.visibility(def_id);
+ let span = child.span;
match def {
Def::Mod(..) | Def::Enum(..) => {
- let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id);
+ let module = self.new_module(parent,
+ ModuleKind::Def(def, ident.name),
+ def_id,
+ span);
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
}
Def::Variant(..) | Def::TyAlias(..) => {
}
Def::Trait(..) => {
let module_kind = ModuleKind::Def(def, ident.name);
- let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
+ let module = self.new_module(parent,
+ module_kind,
+ parent.normal_ancestor_id,
+ span);
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
for child in self.session.cstore.item_children(def_id) {
}
}
- fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
+ fn get_extern_crate_root(&mut self, cnum: CrateNum, span: Span) -> Module<'a> {
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
let name = self.session.cstore.crate_name(cnum);
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
let module_kind = ModuleKind::Def(Def::Mod(def_id), name);
let arenas = self.arenas;
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
- arenas.alloc_module(ModuleData::new(None, module_kind, def_id))
+ arenas.alloc_module(ModuleData::new(None, module_kind, def_id, span))
})
}
- pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
+ pub fn macro_def_scope(&mut self, expansion: Mark, span: Span) -> Module<'a> {
let def_id = self.macro_defs[&expansion];
if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id]
self.graph_root
} else {
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
- self.get_extern_crate_root(module_def_id.krate)
+ self.get_extern_crate_root(module_def_id.krate, span)
}
}
} else {
for (name, span) in legacy_imports.imports {
let ident = Ident::with_empty_ctxt(name);
- let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
+ let result = self.resolve_ident_in_module(module, ident, MacroNS,
+ false, false, span);
if let Ok(binding) = result {
let directive = macro_use_directive(span);
self.potentially_unused_imports.push(directive);
for (name, span) in legacy_imports.reexports {
self.session.cstore.export_macros(module.def_id().unwrap().krate);
let ident = Ident::with_empty_ctxt(name);
- let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
+ let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
if let Ok(binding) = result {
self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
} else {
"##,
E0435: r##"
-A non-constant value was used to initialise a constant.
+A non-constant value was used in a constant expression.
Erroneous code example:
```compile_fail,E0435
-let foo = 42u32;
-const FOO : u32 = foo; // error: attempt to use a non-constant value in a
- // constant
+let foo = 42;
+let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
```
To fix this error, please replace the value with a constant. Example:
```
-const FOO : u32 = 42u32; // ok!
+let a: [u8; 42]; // ok!
```
Or:
```
-const OTHER_FOO : u32 = 42u32;
-const FOO : u32 = OTHER_FOO; // ok!
+const FOO: usize = 42;
+let a: [u8; FOO]; // ok!
```
"##,
// E0157, unused error code
// E0257,
// E0258,
- E0402, // cannot use an outer type parameter in this context
+// E0402, // cannot use an outer type parameter in this context
// E0406, merged into 420
// E0410, merged into 408
// E0413, merged into 530
// except according to those terms.
#![crate_name = "rustc_resolve"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(associated_consts)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use]
extern crate log;
enum ResolutionError<'a> {
/// error E0401: can't use type parameters from outer function
TypeParametersFromOuterFunction,
- /// error E0402: cannot use an outer type parameter in this context
- OuterTypeParameterContext,
/// error E0403: the name is already used for a type parameter in this type parameter list
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
/// error E0407: method is not a member of trait
err.span_label(span, "use of type variable from outer function");
err
}
- ResolutionError::OuterTypeParameterContext => {
- struct_span_err!(resolver.session,
- span,
- E0402,
- "cannot use an outer type parameter in this context")
- }
ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => {
let mut err = struct_span_err!(resolver.session,
span,
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
} else if let TyKind::ImplicitSelf = ty.node {
let self_ty = keywords::SelfType.ident();
- let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span))
+ let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span)
.map_or(Def::Err, |d| d.def());
self.record_def(ty.id, PathResolution::new(def));
} else if let TyKind::Array(ref element, ref length) = ty.node {
// access the children must be preceded with a
// `populate_module_if_necessary` call.
populated: Cell<bool>,
+
+ /// Span of the module itself. Used for error reporting.
+ span: Span,
}
pub type Module<'a> = &'a ModuleData<'a>;
impl<'a> ModuleData<'a> {
- fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId) -> Self {
+ fn new(parent: Option<Module<'a>>,
+ kind: ModuleKind,
+ normal_ancestor_id: DefId,
+ span: Span) -> Self {
ModuleData {
parent: parent,
kind: kind,
globs: RefCell::new((Vec::new())),
traits: RefCell::new(None),
populated: Cell::new(normal_ancestor_id.is_local()),
+ span: span,
}
}
let namespace = if is_value { ValueNS } else { TypeNS };
let hir::Path { ref segments, span, ref mut def } = *path;
let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
- match self.resolve_path(&path, Some(namespace), Some(span)) {
+ match self.resolve_path(&path, Some(namespace), true, span) {
PathResult::Module(module) => *def = module.def().unwrap(),
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
*def = path_res.base_def(),
- PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
+ PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
PathResult::Failed(msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
}
let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
let graph_root = arenas.alloc_module(ModuleData {
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
- ..ModuleData::new(None, root_module_kind, root_def_id)
+ ..ModuleData::new(None, root_module_kind, root_def_id, krate.span)
});
let mut module_map = FxHashMap();
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
self.crate_loader.postprocess(krate);
}
- fn new_module(&self, parent: Module<'a>, kind: ModuleKind, normal_ancestor_id: DefId)
- -> Module<'a> {
- self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id))
+ fn new_module(
+ &self,
+ parent: Module<'a>,
+ kind: ModuleKind,
+ normal_ancestor_id: DefId,
+ span: Span,
+ ) -> Module<'a> {
+ self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id, span))
}
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
fn resolve_ident_in_lexical_scope(&mut self,
mut ident: Ident,
ns: Namespace,
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> Option<LexicalScopeBinding<'a>> {
if ns == TypeNS {
ident = ident.unhygienize();
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
// The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Def(
- self.adjust_local_def(ns, i, def, record_used)
+ self.adjust_local_def(ns, i, def, record_used, path_span)
));
}
if let ModuleRibKind(module) = self.ribs[ns][i].kind {
- let item = self.resolve_ident_in_module(module, ident, ns, false, record_used);
+ let item = self.resolve_ident_in_module(module, ident, ns, false,
+ record_used, path_span);
if let Ok(binding) = item {
// The ident resolves to an item.
return Some(LexicalScopeBinding::Item(binding));
if let ModuleKind::Block(..) = module.kind { // We can see through blocks
} else if !module.no_implicit_prelude {
return self.prelude.and_then(|prelude| {
- self.resolve_ident_in_module(prelude, ident, ns, false, None).ok()
+ self.resolve_ident_in_module(prelude, ident, ns, false,
+ false, path_span).ok()
}).map(LexicalScopeBinding::Item)
} else {
return None;
None
}
- fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext) -> Module<'a> {
+ fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext, span: Span) -> Module<'a> {
let mut ctxt_data = crate_var_ctxt.data();
while ctxt_data.prev_ctxt != SyntaxContext::empty() {
ctxt_data = ctxt_data.prev_ctxt.data();
}
- let module = self.macro_def_scope(ctxt_data.outer_mark);
+ let module = self.macro_def_scope(ctxt_data.outer_mark, span);
if module.is_local() { self.graph_root } else { module }
}
this.check_proc_macro_attrs(&trait_item.attrs);
match trait_item.node {
- TraitItemKind::Const(_, ref default) => {
+ TraitItemKind::Const(ref ty, ref default) => {
+ this.visit_ty(ty);
+
// Only impose the restrictions of
- // ConstRibKind if there's an actual constant
+ // ConstRibKind for an actual constant
// expression in a provided default.
- if default.is_some() {
+ if let Some(ref expr) = *default{
this.with_constant_rib(|this| {
- visit::walk_trait_item(this, trait_item)
+ this.visit_expr(expr);
});
- } else {
- visit::walk_trait_item(this, trait_item)
}
}
TraitItemKind::Method(ref sig, _) => {
});
}
- ItemKind::Const(..) | ItemKind::Static(..) => {
- self.with_constant_rib(|this| {
- visit::walk_item(this, item);
+ ItemKind::Static(ref ty, _, ref expr) |
+ ItemKind::Const(ref ty, ref expr) => {
+ self.with_item_rib(|this| {
+ this.visit_ty(ty);
+ this.with_constant_rib(|this| {
+ this.visit_expr(expr);
+ });
});
}
self.label_ribs.pop();
}
+ fn with_item_rib<F>(&mut self, f: F)
+ where F: FnOnce(&mut Resolver)
+ {
+ self.ribs[ValueNS].push(Rib::new(ItemRibKind));
+ self.ribs[TypeNS].push(Rib::new(ItemRibKind));
+ f(self);
+ self.ribs[TypeNS].pop();
+ self.ribs[ValueNS].pop();
+ }
+
fn with_constant_rib<F>(&mut self, f: F)
where F: FnOnce(&mut Resolver)
{
self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
- self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind));
f(self);
- self.ribs[TypeNS].pop();
self.ribs[ValueNS].pop();
}
PatKind::Ident(bmode, ref ident, ref opt_pat) => {
// First try to resolve the identifier as some existing
// entity, then fall back to a fresh binding.
- let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None)
+ let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS,
+ false, pat.span)
.and_then(LexicalScopeBinding::item);
let resolution = binding.map(NameBinding::def).and_then(|def| {
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
(format!(""), format!("the crate root"))
} else {
let mod_path = &path[..path.len() - 1];
- let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), None) {
+ let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) {
PathResult::Module(module) => module.def(),
_ => None,
}.map_or(format!(""), |def| format!("{} ", def.kind_name()));
let name = path.last().unwrap().name;
let candidates = this.lookup_import_candidates(name, ns, is_expected);
if !candidates.is_empty() {
+ let mut module_span = this.current_module.span;
+ module_span.hi = module_span.lo;
// Report import candidates as help and proceed searching for labels.
- show_candidates(&mut err, &candidates, def.is_some());
+ show_candidates(&mut err, module_span, &candidates, def.is_some());
} else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
let enum_candidates = this.lookup_import_candidates(name, ns, is_enum_variant);
let mut enum_candidates = enum_candidates.iter()
}
}
}
- if path.len() == 1 && this.self_type_is_available() {
+ if path.len() == 1 && this.self_type_is_available(span) {
if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) {
- let self_is_available = this.self_value_is_available(path[0].ctxt);
+ let self_is_available = this.self_value_is_available(path[0].ctxt, span);
match candidate {
AssocSuggestion::Field => {
err.span_label(span, format!("did you mean `self.{}`?", path_str));
let mut levenshtein_worked = false;
// Try Levenshtein.
- if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
+ if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) {
err.span_label(ident_span, format!("did you mean `{}`?", candidate));
levenshtein_worked = true;
}
resolution
}
- fn self_type_is_available(&mut self) -> bool {
- let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), TypeNS, None);
+ fn self_type_is_available(&mut self, span: Span) -> bool {
+ let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(),
+ TypeNS, false, span);
if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
}
- fn self_value_is_available(&mut self, ctxt: SyntaxContext) -> bool {
+ fn self_value_is_available(&mut self, ctxt: SyntaxContext, span: Span) -> bool {
let ident = Ident { name: keywords::SelfValue.name(), ctxt: ctxt };
- let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None);
+ let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, span);
if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
}
));
}
- let result = match self.resolve_path(&path, Some(ns), Some(span)) {
+ let result = match self.resolve_path(&path, Some(ns), true, span) {
PathResult::NonModule(path_res) => path_res,
PathResult::Module(module) if !module.is_normal() => {
PathResolution::new(module.def().unwrap())
if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
let unqualified_result = {
- match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
+ match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
PathResult::NonModule(path_res) => path_res.base_def(),
PathResult::Module(module) => module.def().unwrap(),
_ => return Some(result),
fn resolve_path(&mut self,
path: &[Ident],
opt_ns: Option<Namespace>, // `None` indicates a module path
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> PathResult<'a> {
let mut module = None;
let mut allow_super = true;
module = Some(self.graph_root);
continue
} else if i == 0 && ns == TypeNS && ident.name == "$crate" {
- module = Some(self.resolve_crate_var(ident.ctxt));
+ module = Some(self.resolve_crate_var(ident.ctxt, path_span));
continue
}
let binding = if let Some(module) = module {
- self.resolve_ident_in_module(module, ident, ns, false, record_used)
+ self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
} else if opt_ns == Some(MacroNS) {
- self.resolve_lexical_macro_path_segment(ident, ns, record_used)
+ self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
.map(MacroBinding::binding)
} else {
- match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
+ match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) {
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
Some(LexicalScopeBinding::Def(def))
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
def, path.len() - 1
));
}
- _ => Err(if record_used.is_some() { Determined } else { Undetermined }),
+ _ => Err(if record_used { Determined } else { Undetermined }),
}
};
ns: Namespace,
rib_index: usize,
mut def: Def,
- record_used: Option<Span>) -> Def {
+ record_used: bool,
+ span: Span) -> Def {
let ribs = &self.ribs[ns][rib_index + 1..];
// An invalid forward use of a type parameter from a previous default.
if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::ForwardDeclaredTyParam);
}
match def {
Def::Upvar(..) => {
- span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
+ span_bug!(span, "unexpected {:?} in bindings", def)
}
Def::Local(def_id) => {
for rib in ribs {
let depth = vec.len();
def = Def::Upvar(def_id, depth, function_id);
- if let Some(span) = record_used {
+ if record_used {
vec.push(Freevar {
def: prev_def,
span: span,
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
}
}
ConstantItemRibKind => {
// Still doesn't deal with upvars
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::AttemptToUseNonConstantValueInConstant);
}
for rib in ribs {
match rib.kind {
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
- ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
+ ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
+ ConstantItemRibKind => {
// Nothing to do. Continue.
}
ItemRibKind => {
// This was an attempt to use a type parameter outside
// its scope.
- if let Some(span) = record_used {
+ if record_used {
resolve_error(self, span,
ResolutionError::TypeParametersFromOuterFunction);
}
return Def::Err;
}
- ConstantItemRibKind => {
- // see #9186
- if let Some(span) = record_used {
- resolve_error(self, span,
- ResolutionError::OuterTypeParameterContext);
- }
- return Def::Err;
- }
}
}
}
fn lookup_typo_candidate<FilterFn>(&mut self,
path: &[Ident],
ns: Namespace,
- filter_fn: FilterFn)
+ filter_fn: FilterFn,
+ span: Span)
-> Option<Symbol>
where FilterFn: Fn(Def) -> bool
{
} else {
// Search in module.
let mod_path = &path[..path.len() - 1];
- if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
+ if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
+ false, span) {
add_module_candidates(module, &mut names);
}
}
continue
}
let ident = attr.path.segments[0].identifier;
- let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, None);
+ let result = self.resolve_lexical_macro_path_segment(ident,
+ MacroNS,
+ false,
+ attr.path.span);
if let Ok(binding) = result {
if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
attr::mark_known(attr);
/// When an entity with a given name is not available in scope, we search for
/// entities with that name in all crates. This method allows outputting the
/// results of this search in a programmer-friendly way
-fn show_candidates(session: &mut DiagnosticBuilder,
+fn show_candidates(err: &mut DiagnosticBuilder,
+ span: Span,
candidates: &[ImportSuggestion],
better: bool) {
- // don't show more than MAX_CANDIDATES results, so
- // we're consistent with the trait suggestions
- const MAX_CANDIDATES: usize = 4;
// we want consistent results across executions, but candidates are produced
// by iterating through a hash map, so make sure they are ordered:
1 => " is found in another module, you can import it",
_ => "s are found in other modules, you can import them",
};
+ let msg = format!("possible {}candidate{} into scope", better, msg_diff);
+
+ for candidate in &mut path_strings {
+ *candidate = format!("use {};\n", candidate);
+ }
- let end = cmp::min(MAX_CANDIDATES, path_strings.len());
- session.help(&format!("possible {}candidate{} into scope:{}{}",
- better,
- msg_diff,
- &path_strings[0..end].iter().map(|candidate| {
- format!("\n `use {};`", candidate)
- }).collect::<String>(),
- if path_strings.len() > MAX_CANDIDATES {
- format!("\nand {} other candidates",
- path_strings.len() - MAX_CANDIDATES)
- } else {
- "".to_owned()
- }
- ));
+ err.span_suggestions(span, &msg, path_strings);
}
/// A somewhat inefficient routine to obtain the name of a module.
}
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
- struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>);
+ struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span);
impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
let ident = path.segments[0].identifier;
if ident.name == "$crate" {
path.segments[0].identifier.name = keywords::CrateRoot.name();
- let module = self.0.resolve_crate_var(ident.ctxt);
+ let module = self.0.resolve_crate_var(ident.ctxt, self.1);
if !module.is_local() {
let span = path.segments[0].span;
path.segments.insert(1, match module.kind {
}
}
- EliminateCrateVar(self).fold_item(item).expect_one("")
+ EliminateCrateVar(self, item.span).fold_item(item).expect_one("")
}
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool {
return Err(Determinacy::Determined);
}
- let def = match self.resolve_path(&path, Some(MacroNS), None) {
+ let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
PathResult::NonModule(path_res) => match path_res.base_def() {
Def::Err => Err(Determinacy::Determined),
def @ _ => Ok(def),
let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
Ok(Def::Macro(binding.def_id, MacroKind::Bang))
} else {
- match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
+ match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) {
Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
Err(_) => {
pub fn resolve_lexical_macro_path_segment(&mut self,
ident: Ident,
ns: Namespace,
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> Result<MacroBinding<'a>, Determinacy> {
let mut module = Some(self.current_module);
let mut potential_illegal_shadower = Err(Determinacy::Determined);
let determinacy =
- if record_used.is_some() { Determinacy::Determined } else { Determinacy::Undetermined };
+ if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
loop {
let result = if let Some(module) = module {
// Since expanded macros may not shadow the lexical scope and
// globs may not shadow global macros (both enforced below),
// we resolve with restricted shadowing (indicated by the penultimate argument).
- self.resolve_ident_in_module(module, ident, ns, true, record_used)
+ self.resolve_ident_in_module(module, ident, ns, true, record_used, path_span)
.map(MacroBinding::Modern)
} else {
self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
match result.map(MacroBinding::binding) {
Ok(binding) => {
- let span = match record_used {
- Some(span) => span,
- None => return result,
- };
+ if !record_used {
+ return result;
+ }
if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
if shadower.def() != binding.def() {
let name = ident.name;
self.ambiguity_errors.push(AmbiguityError {
- span: span, name: name, b1: shadower, b2: binding, lexical: true,
+ span: path_span,
+ name: name,
+ b1: shadower,
+ b2: binding,
+ lexical: true,
legacy: false,
});
return potential_illegal_shadower;
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
for &(ref path, span) in module.macro_resolutions.borrow().iter() {
- match self.resolve_path(path, Some(MacroNS), Some(span)) {
+ match self.resolve_path(path, Some(MacroNS), true, span) {
PathResult::NonModule(_) => {},
PathResult::Failed(msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() {
let legacy_scope = &self.invocations[&mark].legacy_scope;
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
- let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
+ let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span);
match (legacy_resolution, resolution) {
(Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
let msg1 = format!("`{}` could refer to the macro defined here", ident);
format!("cannot find derive macro `{}` in this scope", ident),
};
let mut err = self.session.struct_span_err(span, &msg);
- self.suggest_macro_name(&ident.name.as_str(), kind, &mut err);
+ self.suggest_macro_name(&ident.name.as_str(), kind, &mut err, span);
err.emit();
},
_ => {},
}
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
- err: &mut DiagnosticBuilder<'a>) {
+ err: &mut DiagnosticBuilder<'a>, span: Span) {
// First check if this is a locally-defined bang macro.
let suggestion = if let MacroKind::Bang = kind {
find_best_match_for_name(self.macro_names.iter(), name, None)
}
};
let ident = Ident::from_str(name);
- self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
+ self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span)
});
if let Some(suggestion) = suggestion {
ident: Ident,
ns: Namespace,
restricted_shadowing: bool,
- record_used: Option<Span>)
+ record_used: bool,
+ path_span: Span)
-> Result<&'a NameBinding<'a>, Determinacy> {
self.populate_module_if_necessary(module);
.try_borrow_mut()
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
- if let Some(span) = record_used {
+ if record_used {
if let Some(binding) = resolution.binding {
if let Some(shadowed_glob) = resolution.shadows_glob {
let name = ident.name;
ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing
binding.def() != shadowed_glob.def() {
self.ambiguity_errors.push(AmbiguityError {
- span: span, name: name, lexical: false, b1: binding, b2: shadowed_glob,
+ span: path_span,
+ name: name,
+ lexical: false,
+ b1: binding,
+ b2: shadowed_glob,
legacy: false,
});
}
}
- if self.record_use(ident, ns, binding, span) {
+ if self.record_use(ident, ns, binding, path_span) {
return Ok(self.dummy_binding);
}
if !self.is_accessible(binding.vis) {
- self.privacy_errors.push(PrivacyError(span, ident.name, binding));
+ self.privacy_errors.push(PrivacyError(path_span, ident.name, binding));
}
}
SingleImport { source, .. } => source,
_ => unreachable!(),
};
- match self.resolve_ident_in_module(module, ident, ns, false, None) {
+ match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
Err(Determined) => {}
_ => return Err(Undetermined),
}
for directive in module.globs.borrow().iter() {
if self.is_accessible(directive.vis.get()) {
if let Some(module) = directive.imported_module.get() {
- let result = self.resolve_ident_in_module(module, ident, ns, false, None);
+ let result = self.resolve_ident_in_module(module,
+ ident,
+ ns,
+ false,
+ false,
+ path_span);
if let Err(Undetermined) = result {
return Err(Undetermined);
}
// For better failure detection, pretend that the import will not define any names
// while resolving its module path.
directive.vis.set(ty::Visibility::Invisible);
- let result = self.resolve_path(&directive.module_path, None, None);
+ let result = self.resolve_path(&directive.module_path, None, false, directive.span);
directive.vis.set(vis);
match result {
let mut indeterminate = false;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
if let Err(Undetermined) = result[ns].get() {
- result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None));
+ result[ns].set(this.resolve_ident_in_module(module,
+ source,
+ ns,
+ false,
+ false,
+ directive.span));
} else {
return
};
self.current_module = directive.parent;
let ImportDirective { ref module_path, span, .. } = *directive;
- let module_result = self.resolve_path(&module_path, None, Some(span));
+ let module_result = self.resolve_path(&module_path, None, true, span);
let module = match module_result {
PathResult::Module(module) => module,
PathResult::Failed(msg, _) => {
let (mut self_path, mut self_result) = (module_path.clone(), None);
if !self_path.is_empty() && !token::Ident(self_path[0]).is_path_segment_keyword() {
self_path[0].name = keywords::SelfValue.name();
- self_result = Some(self.resolve_path(&self_path, None, None));
+ self_result = Some(self.resolve_path(&self_path, None, false, span));
}
return if let Some(PathResult::Module(..)) = self_result {
Some(format!("Did you mean `{}`?", names_to_string(&self_path)))
Some(this.dummy_binding);
}
}
- } else if let Ok(binding) = this.resolve_ident_in_module(module, ident, ns, false, None) {
+ } else if let Ok(binding) = this.resolve_ident_in_module(module,
+ ident,
+ ns,
+ false,
+ false,
+ directive.span) {
legacy_self_import = Some(directive);
let binding = this.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Import {
}
let mut all_ns_failed = true;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
- match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) {
+ match this.resolve_ident_in_module(module, ident, ns, false, true, span) {
Ok(_) => all_ns_failed = false,
_ => {}
}
pub items: Vec<NodeId>,
pub visibility: Visibility,
pub docs: String,
- pub sig: Signature,
+ pub sig: Option<Signature>,
pub attributes: Vec<Attribute>,
}
}
impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, D> {
+ fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
+ // Since we handle explicit modules ourselves in visit_item, this should
+ // only get called for the root module of a crate.
+ assert_eq!(id, ast::CRATE_NODE_ID);
+
+ let qualname = format!("::{}", self.tcx.node_path_str(id));
+
+ let cm = self.tcx.sess.codemap();
+ let filename = cm.span_to_filename(span);
+ self.dumper.mod_data(ModData {
+ id: id,
+ name: String::new(),
+ qualname: qualname,
+ span: span,
+ scope: id,
+ filename: filename,
+ items: m.items.iter().map(|i| i.id).collect(),
+ visibility: Visibility::Public,
+ docs: docs_for_attrs(attrs),
+ sig: None,
+ attributes: attrs.to_owned(),
+ }.lower(self.tcx));
+ self.nest_scope(id, |v| visit::walk_mod(v, m));
+ }
+
fn visit_item(&mut self, item: &'l ast::Item) {
use syntax::ast::ItemKind::*;
self.process_macro_use(item.span, item.id);
pub items: Vec<DefId>,
pub visibility: Visibility,
pub docs: String,
- pub sig: Signature,
+ pub sig: Option<Signature>,
pub attributes: Vec<Attribute>,
}
items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(),
visibility: self.visibility,
docs: self.docs,
- sig: self.sig.lower(tcx),
+ sig: self.sig.map(|s| s.lower(tcx)),
attributes: self.attributes.lower(tcx),
}
}
parent: None,
decl_id: None,
docs: self.docs,
- sig: Some(self.sig.into()),
+ sig: self.sig.map(|s| s.into()),
attributes: vec![],
}),
_ => None,
children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(),
decl_id: None,
docs: data.docs,
- sig: Some(data.sig.into()),
+ sig: data.sig.map(|s| s.into()),
attributes: data.attributes.into_iter().map(|a| a.into()).collect(),
};
if def.span.file_name.to_str().unwrap() != def.value {
// except according to those terms.
#![crate_name = "rustc_save_analysis"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(custom_attribute)]
#![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use] extern crate rustc;
items: m.items.iter().map(|i| i.id).collect(),
visibility: From::from(&item.vis),
docs: docs_for_attrs(&item.attrs),
- sig: self.sig_base(item),
+ sig: Some(self.sig_base(item)),
attributes: item.attrs.clone(),
}))
}
//! comments can also be found below leading through the various code paths.
// A simple macro to make this option mess easier to read
+#[cfg(windows)]
macro_rules! otry {
($expr:expr) => (match $expr {
Some(val) => val,
if is_inline_instance(tcx, instance) {
return true
}
+ if let ty::InstanceDef::DropGlue(..) = instance.def {
+ // Drop glue wants to be instantiated at every translation
+ // unit, but without an #[inline] hint. We should make this
+ // available to normal end-users.
+ return true
+ }
attr::requests_inline(&instance.def.attrs(tcx)[..])
}
//! This API is completely unstable and subject to change.
#![crate_name = "rustc_trans"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
#![feature(slice_patterns)]
-#![feature(staged_api)]
#![feature(unicode)]
#![feature(conservative_impl_trait)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;
pub mod diagnostics;
-#[macro_use]
-mod macros;
-
mod abi;
mod adt;
mod asm;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-macro_rules! unpack_datum {
- ($bcx: ident, $inp: expr) => (
- {
- let db = $inp;
- $bcx = db.bcx;
- db.datum
- }
- )
-}
-
-macro_rules! unpack_result {
- ($bcx: ident, $inp: expr) => (
- {
- let db = $inp;
- $bcx = db.bcx;
- db.val
- }
- )
-}
location: Location) {
match *kind {
mir::TerminatorKind::Call {
- func: mir::Operand::Constant(mir::Constant {
+ func: mir::Operand::Constant(box mir::Constant {
literal: Literal::Value {
value: ConstVal::Function(def_id, _), ..
}, ..
Value(base));
}
if projected_ty.is_bool() {
- unsafe {
- val = llvm::LLVMConstTrunc(val, Type::i1(self.ccx).to_ref());
+ let i1_type = Type::i1(self.ccx);
+ if val_ty(val) != i1_type {
+ unsafe {
+ val = llvm::LLVMConstTrunc(val, i1_type.to_ref());
+ }
}
}
(Base::Value(val), extra)
}
failure?;
- match *kind {
+ match **kind {
mir::AggregateKind::Array(_) => {
self.const_array(dest_ty, &fields)
}
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
- match *kind {
+ match **kind {
mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index)
.to_u128_unchecked() as u64;
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
-> ty::GenericPredicates<'tcx>;
- /// Return an (optional) substitution to convert bound type parameters that
- /// are in scope into free ones. This function should only return Some
- /// within a fn body.
- /// See ParameterEnvironment::free_substs for more information.
- fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
-
/// What lifetime should we use when a lifetime is omitted (and not elided)?
fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
-> Option<ty::Region<'tcx>>;
Some(&rl::Region::EarlyBound(index, id)) => {
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+ def_id: tcx.hir.local_def_id(id),
index: index,
name: name
}))
Some(&rl::Region::Free(scope, id)) => {
let name = tcx.hir.name(id);
tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: Some(scope.to_code_extent(tcx)),
+ scope,
bound_region: ty::BrNamed(tcx.hir.local_def_id(id), name)
}))
}
};
- let trait_ref = if let Some(free_substs) = self.get_free_substs() {
- trait_ref.subst(tcx, free_substs)
- } else {
- trait_ref
- };
-
let candidates =
traits::supertraits(tcx, ty::Binder(trait_ref))
.filter(|r| self.trait_defines_associated_type_named(r.def_id(),
assert_eq!(opt_self_ty, None);
self.prohibit_type_params(&path.segments);
- let ty = tcx.at(span).type_of(def_id);
- if let Some(free_substs) = self.get_free_substs() {
- ty.subst(tcx, free_substs)
- } else {
- ty
- }
+ tcx.at(span).type_of(def_id)
}
Def::SelfTy(Some(_), None) => {
// Self in trait.
use astconv::AstConv;
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::ty::{self, ToPolyTraitRef, Ty};
+use rustc::ty::subst::Substs;
use std::cmp;
use std::iter;
use syntax::abi::Abi;
decl,
Abi::RustCall,
expected_sig);
+ // `deduce_expectations_from_expected_type` introduces late-bound
+ // lifetimes defined elsewhere, which we need to anonymize away.
+ let sig = self.tcx.anonymize_late_bound_regions(&sig);
// Create type variables (for now) to represent the transformed
// types of upvars. These will be unified during the upvar
// inference phase (`upvar.rs`).
+ let base_substs = Substs::identity_for_item(self.tcx,
+ self.tcx.closure_base_def_id(expr_def_id));
let closure_type = self.tcx.mk_closure(expr_def_id,
- self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id,
+ base_substs.extend_to(self.tcx, expr_def_id,
|_, _| span_bug!(expr.span, "closure has region param"),
|_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
)
debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
- let extent = self.tcx.call_site_extent(expr.id, body.value.id);
- let fn_sig = self.tcx.liberate_late_bound_regions(Some(extent), &sig);
+ let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
body.value.id, &fn_sig);
// Create a parameter environment that represents the implementation's
// method.
- let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_m_node_id);
+ let impl_param_env = tcx.parameter_environment(impl_m.def_id);
// Create mapping from impl to skolemized.
- let impl_to_skol_substs = &impl_param_env.free_substs;
+ let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to skolemized.
let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
impl_m.container.id(),
- trait_to_impl_substs.subst(tcx,
- impl_to_skol_substs));
+ trait_to_impl_substs);
debug!("compare_impl_method: trait_to_skol_substs={:?}",
trait_to_skol_substs);
impl_m,
&trait_m_generics,
&impl_m_generics,
- trait_to_skol_substs,
- impl_to_skol_substs)?;
+ trait_to_skol_substs)?;
// Create obligations for each predicate declared by the impl
// definition in the context of the trait's parameter
// however, because we want to replace all late-bound regions with
// region variables.
let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
- let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
+ let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
normalize_cause.clone());
tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
- let inh = Inherited::new(infcx);
+ let inh = Inherited::new(infcx, impl_m.def_id);
let infcx = &inh.infcx;
debug!("compare_impl_method: caller_bounds={:?}",
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
infer::HigherRankedType,
&m_sig(impl_m));
- let impl_sig =
- impl_sig.subst(tcx, impl_to_skol_substs);
let impl_sig =
inh.normalize_associated_types_in(impl_m_span,
impl_m_node_id,
let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
- let trait_sig = tcx.liberate_late_bound_regions(
- infcx.parameter_environment.free_id_outlive,
+ let trait_sig = inh.liberate_late_bound_regions(
+ impl_m.def_id,
&m_sig(trait_m));
let trait_sig =
trait_sig.subst(tcx, trait_to_skol_substs);
impl_m: &ty::AssociatedItem,
trait_generics: &ty::Generics,
impl_generics: &ty::Generics,
- trait_to_skol_substs: &Substs<'tcx>,
- impl_to_skol_substs: &Substs<'tcx>)
+ trait_to_skol_substs: &Substs<'tcx>)
-> Result<(), ErrorReported> {
let trait_params = &trait_generics.regions[..];
let impl_params = &impl_generics.regions[..];
debug!("check_region_bounds_on_impl_method: \
trait_generics={:?} \
impl_generics={:?} \
- trait_to_skol_substs={:?} \
- impl_to_skol_substs={:?}",
+ trait_to_skol_substs={:?}",
trait_generics,
impl_generics,
- trait_to_skol_substs,
- impl_to_skol_substs);
+ trait_to_skol_substs);
// Must have same number of early-bound lifetime parameters.
// Unfortunately, if the user screws up the bounds, then this
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
- let inh = Inherited::new(infcx);
+ let inh = Inherited::new(infcx, impl_c.def_id);
let infcx = &inh.infcx;
// The below is for the most part highly similar to the procedure
// Create a parameter environment that represents the implementation's
// method.
let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap();
- let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_c_node_id);
-
- // Create mapping from impl to skolemized.
- let impl_to_skol_substs = &impl_param_env.free_substs;
-
- // Create mapping from trait to skolemized.
- let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
- impl_c.container.id(),
- trait_to_impl_substs.subst(tcx,
- impl_to_skol_substs));
- debug!("compare_const_impl: trait_to_skol_substs={:?}",
- trait_to_skol_substs);
// Compute skolemized form of impl and trait const tys.
- let impl_ty = tcx.type_of(impl_c.def_id).subst(tcx, impl_to_skol_substs);
- let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_skol_substs);
+ let impl_ty = tcx.type_of(impl_c.def_id);
+ let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
// There is no "body" here, so just pass dummy id.
-> Result<(), ErrorReported>
{
let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap();
- let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap();
// check that the impl type can be made to match the trait type.
- let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
+ let impl_param_env = tcx.parameter_environment(self_type_did);
tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| {
let tcx = infcx.tcx;
let mut fulfillment_cx = traits::FulfillmentContext::new();
let named_type = tcx.type_of(self_type_did);
- let named_type = named_type.subst(tcx, &infcx.parameter_environment.free_substs);
let drop_impl_span = tcx.def_span(drop_impl_did);
let fresh_impl_substs =
fulfillment_cx.register_predicate_obligations(infcx, obligations);
}
Err(_) => {
- let item_span = tcx.hir.span(self_type_node_id);
+ let item_span = tcx.def_span(self_type_did);
struct_span_err!(tcx.sess, drop_impl_span, E0366,
"Implementations of Drop cannot be specialized")
.span_note(item_span,
rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
ty: ty::Ty<'tcx>,
span: Span,
- scope: region::CodeExtent<'tcx>)
+ scope: region::CodeExtent)
-> Result<(), ErrorReported>
{
debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
use rustc_back::slice::ref_slice;
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
use rustc::infer::type_variable::{TypeVariableOrigin};
+use rustc::middle::region::CodeExtent;
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
-use rustc::ty::{ParamTy, ParameterEnvironment};
-use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
+use rustc::ty::{ParamTy, LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, Ty, TyCtxt, Visibility};
use rustc::ty::{MethodCall, MethodCallee};
use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
// variables to get the concrete type, which can be used to
// deanonymize TyAnon, after typeck is done with all functions.
anon_types: RefCell<NodeMap<Ty<'tcx>>>,
+
+ /// Each type parameter has an implicit region bound that
+ /// indicates it must outlive at least the function body (the user
+ /// may specify stronger requirements). This field indicates the
+ /// region of the callee. If it is `None`, then the parameter
+ /// environment is for an item or something where the "callee" is
+ /// not clear.
+ implicit_region_bound: Option<ty::Region<'tcx>>,
}
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
/// Necessary because we can't write the following bound:
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>).
pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>
+ infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>,
+ def_id: DefId,
}
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
- pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId)
+ pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
-> InheritedBuilder<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty();
- let param_env = ParameterEnvironment::for_item(tcx, id);
+ let param_env = tcx.parameter_environment(def_id);
InheritedBuilder {
- infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing)
+ infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
+ def_id,
}
}
}
fn enter<F, R>(&'tcx mut self, f: F) -> R
where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
{
- self.infcx.enter(|infcx| f(Inherited::new(infcx)))
+ let def_id = self.def_id;
+ self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
}
}
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
- fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
+ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
+ let tcx = infcx.tcx;
+ let item_id = tcx.hir.as_local_node_id(def_id);
+ let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id));
+ let implicit_region_bound = body_id.map(|body| {
+ tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body)))
+ });
+
Inherited {
infcx: infcx,
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
deferred_call_resolutions: RefCell::new(DefIdMap()),
deferred_cast_checks: RefCell::new(Vec::new()),
anon_types: RefCell::new(NodeMap()),
+ implicit_region_bound,
}
}
obligations);
InferOk { value, obligations }
}
+
+ /// Replace any late-bound regions bound in `value` with
+ /// free variants attached to `all_outlive_scope`.
+ fn liberate_late_bound_regions<T>(&self,
+ all_outlive_scope: DefId,
+ value: &ty::Binder<T>)
+ -> T
+ where T: TypeFoldable<'tcx>
+ {
+ self.tcx.replace_late_bound_regions(value, |br| {
+ self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
+ scope: all_outlive_scope,
+ bound_region: br
+ }))
+ }).0
+ }
}
struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
});
let body = tcx.hir.body(body_id);
- Inherited::build(tcx, id).enter(|inh| {
+ Inherited::build(tcx, def_id).enter(|inh| {
let fcx = if let Some(decl) = fn_decl {
let fn_sig = tcx.type_of(def_id).fn_sig();
check_abi(tcx, span, fn_sig.abi());
// Compute the fty from point of view of inside fn.
- let fn_scope = inh.tcx.call_site_extent(id, body_id.node_id);
- let fn_sig =
- fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
let fn_sig =
- inh.tcx.liberate_late_bound_regions(Some(fn_scope), &fn_sig);
+ inh.liberate_late_bound_regions(def_id, &fn_sig);
let fn_sig =
inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
- fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
- Some(&self.parameter_environment.free_substs)
- }
-
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
-> ty::GenericPredicates<'tcx>
{
use middle::free_region::FreeRegionMap;
use middle::mem_categorization as mc;
use middle::mem_categorization::Categorization;
-use middle::region::{self, CodeExtent, RegionMaps};
+use middle::region::{CodeExtent, RegionMaps};
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
- pub region_maps: Rc<RegionMaps<'tcx>>,
+ pub region_maps: Rc<RegionMaps>,
free_region_map: FreeRegionMap<'tcx>,
body_id: ast::NodeId,
// call_site scope of innermost fn
- call_site_scope: Option<CodeExtent<'tcx>>,
+ call_site_scope: Option<CodeExtent>,
// id of innermost fn or loop
repeating_scope: ast::NodeId,
}
}
- fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent<'tcx>>)
- -> Option<CodeExtent<'tcx>> {
+ fn set_call_site_scope(&mut self, call_site_scope: Option<CodeExtent>)
+ -> Option<CodeExtent> {
mem::replace(&mut self.call_site_scope, call_site_scope)
}
let body_id = body.id();
- let call_site = self.tcx.intern_code_extent(
- region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
+ let call_site = CodeExtent::CallSiteScope(body_id);
let old_call_site_scope = self.set_call_site_scope(Some(call_site));
let fn_sig = {
let old_body_id = self.set_body_id(body_id.node_id);
self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span);
- self.link_fn_args(self.tcx.node_extent(body_id.node_id), &body.arguments);
+ self.link_fn_args(CodeExtent::Misc(body_id.node_id), &body.arguments);
self.visit_body(body);
self.visit_region_obligations(body_id.node_id);
for implication in implied_bounds {
debug!("implication: {:?}", implication);
match implication {
- ImpliedBound::RegionSubRegion(&ty::ReFree(free_a),
+ ImpliedBound::RegionSubRegion(r_a @ &ty::ReEarlyBound(_),
+ &ty::ReVar(vid_b)) |
+ ImpliedBound::RegionSubRegion(r_a @ &ty::ReFree(_),
&ty::ReVar(vid_b)) => {
- self.add_given(free_a, vid_b);
+ self.add_given(r_a, vid_b);
}
ImpliedBound::RegionSubParam(r_a, param_b) => {
self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
// call occurs.
//
// FIXME(#6268) to support nested method calls, should be callee_id
- let callee_scope = self.tcx.node_extent(call_expr.id);
+ let callee_scope = CodeExtent::Misc(call_expr.id);
let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
debug!("callee_region={:?}", callee_region);
debug!("constrain_index(index_expr=?, indexed_ty={}",
self.ty_to_string(indexed_ty));
- let r_index_expr = ty::ReScope(self.tcx.node_extent(index_expr.id));
+ let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.id));
if let ty::TyRef(r_ptr, mt) = indexed_ty.sty {
match mt.ty.sty {
ty::TySlice(_) | ty::TyStr => {
/// Computes the guarantors for any ref bindings in a match and
/// then ensures that the lifetime of the resulting pointer is
/// linked to the lifetime of its guarantor (if any).
- fn link_fn_args(&self, body_scope: CodeExtent<'tcx>, args: &[hir::Arg]) {
+ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
for arg in args {
/// must outlive `callee_scope`.
fn link_by_ref(&self,
expr: &hir::Expr,
- callee_scope: CodeExtent<'tcx>) {
+ callee_scope: CodeExtent) {
debug!("link_by_ref(expr={:?}, callee_scope={:?})",
expr, callee_scope);
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
}
fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
- let param_env = &self.parameter_environment;
-
debug!("param_bound(param_ty={:?})",
param_ty);
// Add in the default bound of fn body that applies to all in
// scope type parameters:
- param_bounds.extend(param_env.implicit_region_bound);
+ param_bounds.extend(self.implicit_region_bound);
VerifyBound::AnyRegion(param_bounds)
}
}
let mut regions = ty.regions();
- regions.retain(|r| !r.is_bound()); // ignore late-bound regions
+ regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
bounds.push(VerifyBound::AllRegions(regions));
// remove bounds that must hold, since they are not interesting
use constrained_type_params::{identify_constrained_type_params, Parameter};
use hir::def_id::DefId;
-use middle::region::{CodeExtent};
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
error_192(tcx, item.span);
}
}
- hir::ItemFn(.., body_id) => {
- self.check_item_fn(item, body_id);
+ hir::ItemFn(..) => {
+ self.check_item_fn(item);
}
hir::ItemStatic(..) => {
self.check_item_type(item);
sig_if_method: Option<&hir::MethodSig>) {
let code = self.code.clone();
self.for_id(item_id, span).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
- let free_id_outlive = fcx.parameter_environment.free_id_outlive;
-
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
let (mut implied_bounds, self_ty) = match item.container {
match item.kind {
ty::AssociatedKind::Const => {
let ty = fcx.tcx.type_of(item.def_id);
- let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
+ let ty = fcx.normalize_associated_types_in(span, &ty);
fcx.register_wf_obligation(ty, span, code.clone());
}
ty::AssociatedKind::Method => {
reject_shadowing_type_parameters(fcx.tcx, item.def_id);
let method_ty = fcx.tcx.type_of(item.def_id);
- let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
- let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs);
+ let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
+ let predicates = fcx.tcx.predicates_of(item.def_id)
+ .instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(span, &predicates);
let sig = method_ty.fn_sig();
this.check_fn_or_method(fcx, span, sig, &predicates,
- free_id_outlive, &mut implied_bounds);
+ item.def_id, &mut implied_bounds);
let sig_if_method = sig_if_method.expect("bad signature for method");
- this.check_method_receiver(fcx, sig_if_method, &item,
- free_id_outlive, self_ty);
+ this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
}
ty::AssociatedKind::Type => {
if item.defaultness.has_value() {
let ty = fcx.tcx.type_of(item.def_id);
- let ty = fcx.instantiate_type_scheme(span, free_substs, &ty);
+ let ty = fcx.normalize_associated_types_in(span, &ty);
fcx.register_wf_obligation(ty, span, code.clone());
}
}
fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
-> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
CheckWfFcxBuilder {
- inherited: Inherited::build(self.tcx, id),
+ inherited: Inherited::build(self.tcx, self.tcx.hir.local_def_id(id)),
code: self.code.clone(),
id: id,
span: span
}
}
- let free_substs = &fcx.parameter_environment.free_substs;
let def_id = fcx.tcx.hir.local_def_id(item.id);
- let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
this.check_where_clauses(fcx, item.span, &predicates);
vec![] // no implied bounds in a struct def'n
}
self.for_item(item).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
- let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
this.check_where_clauses(fcx, item.span, &predicates);
vec![]
});
}
- fn check_item_fn(&mut self,
- item: &hir::Item,
- body_id: hir::BodyId)
- {
+ fn check_item_fn(&mut self, item: &hir::Item) {
self.for_item(item).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
let def_id = fcx.tcx.hir.local_def_id(item.id);
let ty = fcx.tcx.type_of(def_id);
- let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty);
+ let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
let sig = item_ty.fn_sig();
- let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
let mut implied_bounds = vec![];
- let free_id_outlive = fcx.tcx.call_site_extent(item.id, body_id.node_id);
this.check_fn_or_method(fcx, item.span, sig, &predicates,
- Some(free_id_outlive), &mut implied_bounds);
+ def_id, &mut implied_bounds);
implied_bounds
})
}
self.for_item(item).with_fcx(|fcx, this| {
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
- let item_ty = fcx.instantiate_type_scheme(item.span,
- &fcx.parameter_environment
- .free_substs,
- &ty);
+ let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
debug!("check_impl: {:?}", item);
self.for_item(item).with_fcx(|fcx, this| {
- let free_substs = &fcx.parameter_environment.free_substs;
let item_def_id = fcx.tcx.hir.local_def_id(item.id);
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
let trait_ref =
- fcx.instantiate_type_scheme(
- ast_trait_ref.path.span, free_substs, &trait_ref);
+ fcx.normalize_associated_types_in(
+ ast_trait_ref.path.span, &trait_ref);
let obligations =
ty::wf::trait_obligations(fcx,
fcx.body_id,
}
None => {
let self_ty = fcx.tcx.type_of(item_def_id);
- let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty);
+ let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
}
}
- let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs);
+ let predicates = fcx.tcx.predicates_of(item_def_id).instantiate_identity(fcx.tcx);
+ let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
this.check_where_clauses(fcx, item.span, &predicates);
fcx.impl_implied_bounds(item_def_id, item.span)
span: Span,
sig: ty::PolyFnSig<'tcx>,
predicates: &ty::InstantiatedPredicates<'tcx>,
- free_id_outlive: Option<CodeExtent<'tcx>>,
+ def_id: DefId,
implied_bounds: &mut Vec<Ty<'tcx>>)
{
- let free_substs = &fcx.parameter_environment.free_substs;
- let sig = fcx.instantiate_type_scheme(span, free_substs, &sig);
- let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &sig);
+ let sig = fcx.normalize_associated_types_in(span, &sig);
+ let sig = fcx.liberate_late_bound_regions(def_id, &sig);
for input_ty in sig.inputs() {
fcx.register_wf_obligation(&input_ty, span, self.code.clone());
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
method_sig: &hir::MethodSig,
method: &ty::AssociatedItem,
- free_id_outlive: Option<CodeExtent<'tcx>>,
self_ty: ty::Ty<'tcx>)
{
// check that the type of the method's receiver matches the
let span = method_sig.decl.inputs[0].span;
- let free_substs = &fcx.parameter_environment.free_substs;
let method_ty = fcx.tcx.type_of(method.def_id);
- let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty);
- let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig());
+ let fty = fcx.normalize_associated_types_in(span, &method_ty);
+ let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
debug!("check_method_receiver: sig={:?}", sig);
}
ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
};
- let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
- let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
- &ty::Binder(rcvr_ty));
+ let rcvr_ty = fcx.normalize_associated_types_in(span, &rcvr_ty);
+ let rcvr_ty = fcx.liberate_late_bound_regions(method.def_id,
+ &ty::Binder(rcvr_ty));
debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
struct_def.fields().iter()
.map(|field| {
let field_ty = self.tcx.type_of(self.tcx.hir.local_def_id(field.id));
- let field_ty = self.instantiate_type_scheme(field.span,
- &self.parameter_environment
- .free_substs,
- &field_ty);
+ let field_ty = self.normalize_associated_types_in(field.span,
+ &field_ty);
AdtField { ty: field_ty, span: field.span }
})
.collect();
}
fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
- let free_substs = &self.parameter_environment.free_substs;
match self.tcx.impl_trait_ref(impl_def_id) {
Some(ref trait_ref) => {
// Trait impl: take implied bounds from all types that
// appear in the trait reference.
- let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref);
+ let trait_ref = self.normalize_associated_types_in(span, trait_ref);
trait_ref.substs.types().collect()
}
None => {
// Inherent impl: take implied bounds from the self type.
let self_ty = self.tcx.type_of(impl_def_id);
- let self_ty = self.instantiate_type_scheme(span, free_substs, &self_ty);
+ let self_ty = self.normalize_associated_types_in(span, &self_ty);
vec![self_ty]
}
}
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
use rustc::ty::adjustment;
use rustc::ty::fold::{TypeFolder,TypeFoldable};
-use rustc::util::nodemap::{DefIdMap, DefIdSet};
+use rustc::util::nodemap::DefIdSet;
use syntax::ast;
use syntax_pos::Span;
use std::mem;
tables: ty::TypeckTables<'gcx>,
- // Mapping from free regions of the function to the
- // early-bound versions of them, visible from the
- // outside of the function. This is needed by, and
- // only populated if there are any `impl Trait`.
- free_to_bound_regions: DefIdMap<ty::Region<'gcx>>,
-
body: &'gcx hir::Body,
}
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body)
-> WritebackCx<'cx, 'gcx, 'tcx> {
- let mut wbcx = WritebackCx {
+ WritebackCx {
fcx: fcx,
tables: ty::TypeckTables::empty(),
- free_to_bound_regions: DefIdMap(),
body: body
- };
-
- // Only build the reverse mapping if `impl Trait` is used.
- if fcx.anon_types.borrow().is_empty() {
- return wbcx;
}
-
- let gcx = fcx.tcx.global_tcx();
- let free_substs = fcx.parameter_environment.free_substs;
- for (i, k) in free_substs.iter().enumerate() {
- let r = if let Some(r) = k.as_region() {
- r
- } else {
- continue;
- };
- match *r {
- ty::ReFree(ty::FreeRegion {
- bound_region: ty::BoundRegion::BrNamed(def_id, name), ..
- }) => {
- let bound_region = gcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
- index: i as u32,
- name: name,
- }));
- wbcx.free_to_bound_regions.insert(def_id, bound_region);
- }
- _ => {
- bug!("{:?} is not a free region for an early-bound lifetime", r);
- }
- }
- }
-
- wbcx
}
fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
let inside_ty = self.resolve(&concrete_ty, &node_id);
// Convert the type from the function into a type valid outside
- // the function, by replacing free regions with early-bound ones.
+ // the function, by replacing invalid regions with 'static,
+ // after producing an error for each of them.
let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
match *r {
- // 'static is valid everywhere.
- ty::ReStatic => gcx.types.re_static,
- ty::ReEmpty => gcx.types.re_empty,
-
- // Free regions that come from early-bound regions are valid.
- ty::ReFree(ty::FreeRegion {
- bound_region: ty::BoundRegion::BrNamed(def_id, ..), ..
- }) if self.free_to_bound_regions.contains_key(&def_id) => {
- self.free_to_bound_regions[&def_id]
- }
+ // 'static and early-bound regions are valid.
+ ty::ReStatic |
+ ty::ReEarlyBound(_) |
+ ty::ReEmpty => r,
ty::ReFree(_) |
- ty::ReEarlyBound(_) |
ty::ReLateBound(..) |
ty::ReScope(_) |
ty::ReSkolemized(..) => {
use rustc::traits::{self, ObligationCause, Reveal};
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::ParameterEnvironment;
use rustc::ty::TypeFoldable;
use rustc::ty::adjustment::CoerceUnsizedInfo;
-use rustc::ty::subst::Subst;
use rustc::ty::util::CopyImplementationError;
use rustc::infer;
self_type);
let span = tcx.hir.span(impl_node_id);
- let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
- let self_type = self_type.subst(tcx, ¶m_env.free_substs);
+ let param_env = tcx.parameter_environment(impl_did);
assert!(!self_type.has_escaping_regions());
debug!("visit_implementation_of_copy: self_type={:?} (free)",
target);
let span = tcx.hir.span(impl_node_id);
- let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
- let source = source.subst(tcx, ¶m_env.free_substs);
- let target = target.subst(tcx, ¶m_env.free_substs);
+ let param_env = tcx.parameter_environment(impl_did);
assert!(!source.has_escaping_regions());
let err_info = CoerceUnsizedInfo { custom_kind: None };
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
}
- fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
- None
- }
-
fn re_infer(&self, _span: Span, _def: Option<&ty::RegionParameterDef>)
-> Option<ty::Region<'tcx>> {
None
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(param.lifetime.id),
index: index,
name: param.lifetime.name
}));
*/
#![crate_name = "rustc_typeck"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(never_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
}
}
-impl<'tcx> Clean<Option<Lifetime>> for ty::RegionKind<'tcx> {
+impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
match *self {
ty::ReStatic => Some(Lifetime::statik()),
use std::io;
use std::path::Path;
use std::str;
+use html::markdown::{Markdown, RenderType};
#[derive(Clone)]
pub struct ExternalHtml{
}
impl ExternalHtml {
- pub fn load(in_header: &[String], before_content: &[String], after_content: &[String])
+ pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
+ md_before_content: &[String], md_after_content: &[String], render: RenderType)
-> Option<ExternalHtml> {
load_external_files(in_header)
.and_then(|ih|
load_external_files(before_content)
.map(|bc| (ih, bc))
)
+ .and_then(|(ih, bc)|
+ load_external_files(md_before_content)
+ .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, render))))
+ )
.and_then(|(ih, bc)|
load_external_files(after_content)
.map(|ac| (ih, bc, ac))
)
+ .and_then(|(ih, bc, ac)|
+ load_external_files(md_after_content)
+ .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, render))))
+ )
.map(|(ih, bc, ac)|
ExternalHtml {
in_header: ih,
font-size: 17px;
margin: 30px 0 20px 0;
text-align: center;
+ word-wrap: break-word;
}
.location:empty {
overflow: auto;
padding-left: 0;
}
+#search {
+ margin-left: 230px;
+}
.content pre.line-numbers {
float: left;
border: none;
// except according to those terms.
#![crate_name = "rustdoc"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(libc)]
-#![feature(rustc_private)]
#![feature(set_stdio)]
#![feature(slice_patterns)]
-#![feature(staged_api)]
#![feature(test)]
#![feature(unicode)]
#![feature(vec_remove_item)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate arena;
extern crate getopts;
extern crate env_logger;
"files to include inline between the content and </body> of a rendered \
Markdown file or generated documentation",
"FILES")),
+ unstable(optmulti("", "markdown-before-content",
+ "files to include inline between <body> and the content of a rendered \
+ Markdown file or generated documentation",
+ "FILES")),
+ unstable(optmulti("", "markdown-after-content",
+ "files to include inline between the content and </body> of a rendered \
+ Markdown file or generated documentation",
+ "FILES")),
stable(optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL")),
stable(optflag("", "markdown-no-toc", "don't include table of contents")),
let external_html = match ExternalHtml::load(
&matches.opt_strs("html-in-header"),
&matches.opt_strs("html-before-content"),
- &matches.opt_strs("html-after-content")) {
+ &matches.opt_strs("html-after-content"),
+ &matches.opt_strs("markdown-before-content"),
+ &matches.opt_strs("markdown-after-content"),
+ render_type) {
Some(eh) => eh,
None => return 3,
};
*/
#![crate_name = "serialize"]
-#![unstable(feature = "rustc_private",
+#![cfg_attr(stage0, unstable(feature = "rustc_private",
reason = "deprecated in favor of rustc-serialize on crates.io",
- issue = "27812")]
+ issue = "27812"))]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(core_intrinsics)]
#![feature(i128_type)]
#![feature(specialization)]
-#![feature(staged_api)]
+#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]
extern crate collections;
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
-/// A `CString` is created from either a byte slice or a byte vector. After
-/// being created, a `CString` predominately inherits all of its methods from
-/// the `Deref` implementation to `[c_char]`. Note that the underlying array
-/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice
-/// can be obtained with the `as_bytes` method. Slices produced from a `CString`
-/// do *not* contain the trailing nul terminator unless otherwise specified.
+/// A `CString` is created from either a byte slice or a byte vector. A `u8`
+/// slice can be obtained with the `as_bytes` method. Slices produced from a
+/// `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
///
/// # Examples
///
/// configuration methods can be chained.
///
/// If the [`stack_size`] field is not specified, the stack size
- /// will be the `RUST_MIN_STACK` environment variable, if it is
- /// not specified either, a sensible default size will be set (2MB as
+ /// will be the `RUST_MIN_STACK` environment variable. If it is
+ /// not specified either, a sensible default will be set (2MB as
/// of the writting of this doc).
///
/// # Examples
use codemap::{CodeMap, FilePathMapping};
use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
use errors::registry::Registry;
-use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
+use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
use errors::emitter::Emitter;
-use errors::snippet::Style;
use std::rc::Rc;
use std::io::{self, Write};
fn from_diagnostic_builder(db: &DiagnosticBuilder,
je: &JsonEmitter)
-> Diagnostic {
- let sugg = db.suggestion.as_ref().map(|sugg| {
- SubDiagnostic {
- level: Level::Help,
- message: vec![(sugg.msg.clone(), Style::NoStyle)],
- span: MultiSpan::new(),
- render_span: Some(RenderSpan::Suggestion(sugg.clone())),
- }
+ let sugg = db.suggestions.iter().flat_map(|sugg| {
+ je.render(sugg).into_iter().map(move |rendered| {
+ Diagnostic {
+ message: sugg.msg.clone(),
+ code: None,
+ level: "help",
+ spans: DiagnosticSpan::from_suggestion(sugg, je),
+ children: vec![],
+ rendered: Some(rendered),
+ }
+ })
});
- let sugg = sugg.as_ref();
Diagnostic {
message: db.message(),
code: DiagnosticCode::map_opt_string(db.code.clone(), je),
level: db.level.to_str(),
spans: DiagnosticSpan::from_multispan(&db.span, je),
- children: db.children.iter().chain(sugg).map(|c| {
+ children: db.children.iter().map(|c| {
Diagnostic::from_sub_diagnostic(c, je)
- }).collect(),
+ }).chain(sugg).collect(),
rendered: None,
}
}
.map(|sp| DiagnosticSpan::from_render_span(sp, je))
.unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)),
children: vec![],
- rendered: db.render_span.as_ref()
- .and_then(|rsp| je.render(rsp)),
+ rendered: None,
}
}
}
fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
-> Vec<DiagnosticSpan> {
- assert_eq!(suggestion.msp.span_labels().len(), suggestion.substitutes.len());
- suggestion.msp.span_labels()
- .into_iter()
- .zip(&suggestion.substitutes)
- .map(|(span_label, suggestion)| {
- DiagnosticSpan::from_span_label(span_label,
- Some(suggestion),
- je)
+ suggestion.substitution_parts
+ .iter()
+ .flat_map(|substitution| {
+ substitution.substitutions.iter().map(move |suggestion| {
+ let span_label = SpanLabel {
+ span: substitution.span,
+ is_primary: true,
+ label: None,
+ };
+ DiagnosticSpan::from_span_label(span_label,
+ Some(suggestion),
+ je)
+ })
})
.collect()
}
match *rsp {
RenderSpan::FullSpan(ref msp) =>
DiagnosticSpan::from_multispan(msp, je),
- RenderSpan::Suggestion(ref suggestion) =>
- DiagnosticSpan::from_suggestion(suggestion, je),
+ // regular diagnostics don't produce this anymore
+ // FIXME(oli_obk): remove it entirely
+ RenderSpan::Suggestion(_) => unreachable!(),
}
}
}
}
impl JsonEmitter {
- fn render(&self, render_span: &RenderSpan) -> Option<String> {
- use std::borrow::Borrow;
-
- match *render_span {
- RenderSpan::FullSpan(_) => {
- None
- }
- RenderSpan::Suggestion(ref suggestion) => {
- Some(suggestion.splice_lines(self.cm.borrow()))
- }
- }
+ fn render(&self, suggestion: &CodeSuggestion) -> Vec<String> {
+ suggestion.splice_lines(&*self.cm)
}
}
//! This API is completely unstable and subject to change.
#![crate_name = "syntax"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
test(attr(deny(warnings))))]
#![deny(warnings)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(unicode)]
#![feature(rustc_diagnostic_macros)]
#![feature(i128_type)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
extern crate serialize;
#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;
// integer literal followed by field/method access or a range pattern
// (`0..2` and `12.foo()`)
if self.ch_is('.') && !self.nextch_is('.') &&
- !self.nextch()
- .unwrap_or('\0')
- .is_xid_start() {
+ !ident_start(self.nextch()) {
// might have stuff after the ., and if it does, it needs to start
// with a number
self.bump();
self.count += 1;
walk_ident(self, span, ident);
}
- fn visit_mod(&mut self, m: &Mod, _s: Span, _n: NodeId) {
+ fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) {
self.count += 1;
walk_mod(self, m)
}
fn visit_ident(&mut self, span: Span, ident: Ident) {
walk_ident(self, span, ident);
}
- fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
+ fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
+ walk_mod(self, m);
+ }
fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
}
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
- visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+ visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID);
walk_list!(visitor, visit_attribute, &krate.attrs);
}
item.id)
}
ItemKind::Mod(ref module) => {
- visitor.visit_mod(module, item.span, item.id)
+ visitor.visit_mod(module, item.span, &item.attrs, item.id)
}
ItemKind::ForeignMod(ref foreign_module) => {
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
)
}
-macro_rules! path {
- ($($x:tt)*) => (
- ::ext::deriving::generic::ty::Path::new( pathvec![ $($x)* ] )
- )
-}
-
macro_rules! path_local {
($x:ident) => (
::deriving::generic::ty::Path::new_local(stringify!($x))
//! Syntax extensions in the Rust compiler.
#![crate_name = "syntax_ext"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(warnings)]
#![feature(proc_macro_internals)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
+
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
extern crate fmt_macros;
extern crate log;
visit::walk_item(self, item);
}
- fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, id: NodeId) {
+ fn visit_mod(&mut self, m: &'a ast::Mod, _s: Span, _a: &[ast::Attribute], id: NodeId) {
let mut prev_in_root = self.in_root;
if id != ast::CRATE_NODE_ID {
prev_in_root = mem::replace(&mut self.in_root, false);
//! This API is completely unstable and subject to change.
#![crate_name = "syntax_pos"]
-#![unstable(feature = "rustc_private", issue = "27812")]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![feature(custom_attribute)]
#![feature(optin_builtin_traits)]
#![allow(unused_attributes)]
-#![feature(rustc_private)]
-#![feature(staged_api)]
#![feature(specialization)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(rustc_private))]
+#![cfg_attr(stage0, feature(staged_api))]
+
use std::cell::{Cell, RefCell};
use std::ops::{Add, Sub};
use std::rc::Rc;
//! [ti]: https://en.wikipedia.org/wiki/Terminfo
#![crate_name = "term"]
-#![unstable(feature = "rustc_private",
- reason = "use the crates.io `term` library instead",
- issue = "27812")]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![deny(missing_docs)]
#![deny(warnings)]
-#![feature(box_syntax)]
#![feature(staged_api)]
#![cfg_attr(windows, feature(libc))]
// Handle rustfmt skips
#![feature(custom_attribute)]
#![allow(unused_attributes)]
+#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
+#![cfg_attr(stage0, feature(staged_api))]
+
use std::io::prelude::*;
pub use terminfo::TerminfoTerminal;
fn main () {
let foo = 42u32;
- const FOO : u32 = foo; //~ ERROR E0435
+ let _: [u8; foo]; //~ ERROR E0435
//~| NOTE non-constant used with constant
}
pub fn test<A: Foo, B: Foo>() {
let _array = [4; <A as Foo>::Y];
- //~^ ERROR cannot use an outer type parameter in this context [E0402]
+ //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
}
fn main() {
pub fn test<A: Foo, B: Foo>() {
let _array: [u32; <A as Foo>::Y];
- //~^ ERROR cannot use an outer type parameter in this context [E0402]
+ //~^ ERROR the trait bound `A: Foo` is not satisfied [E0277]
}
fn main() {
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C target-feature=+crt-static
-// error-pattern: specifying the `crt-static` target feature is only allowed
-
-fn main() {}
fn foo<T>() {
static a: Bar<T> = Bar::What;
- //~^ ERROR cannot use an outer type parameter in this context
+//~^ ERROR can't use type parameters from outer function; try using a local type parameter instead
}
fn main() {
fn main() {
let foo = 42u32;
const FOO : u32 = foo;
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
}
pub trait Resources<'a> {}
pub trait Buffer<'a, R: Resources<'a>> {
+ //~^ NOTE the lifetime 'a as defined on the trait at 13:0...
+ //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait
+
fn select(&self) -> BufferViewHandle<R>;
//~^ ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
- //~| NOTE the lifetime 'a as defined on the method body at 14:4...
//~| NOTE ...does not necessarily outlive the anonymous lifetime #1 defined on the method body
//~| ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
- //~| NOTE the anonymous lifetime #1 defined on the method body at 14:4...
- //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body
+ //~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
}
pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
let foo = 100;
static y: isize = foo + 1;
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
println!("{}", y);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-enum Fruit {
+// these two HELPs are actually in a new line between this line and the `enum Fruit` line
+enum Fruit { //~ HELP possible candidate is found in another module, you can import it into scope
+ //~^ HELP possible candidate is found in another module, you can import it into scope
Apple(i64),
//~^ HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`?
//~| HELP there is an enum variant `Fruit::Apple`, did you mean to use `Fruit`?
Apple(5)
//~^ ERROR cannot find function `Apple` in this scope
//~| NOTE not found in this scope
- //~| HELP possible candidate is found in another module, you can import it into scope
}
fn should_return_fruit_too() -> Fruit::Apple {
Apple(5)
//~^ ERROR cannot find function `Apple` in this scope
//~| NOTE not found in this scope
- //~| HELP possible candidate is found in another module, you can import it into scope
}
fn foo() -> Ok {
fn f(x:isize) {
static child: isize = x + 1;
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
}
fn main() {}
impl PTrait for P {
fn getChildOption(&self) -> Option<Box<P>> {
static childVal: Box<P> = self.child.get();
- //~^ ERROR attempt to use a non-constant value in a constant
+ //~^ ERROR can't capture dynamic environment
panic!();
}
}
struct RepeatMut<'a, T>(T, &'a ());
impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+ //~^ NOTE ...does not necessarily outlive the lifetime 'a as defined on the impl
+
type Item = &'a mut T;
fn next(&'a mut self) -> Option<Self::Item>
//~^ ERROR method not compatible with trait
//~| lifetime mismatch
//~| NOTE expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+ //~| NOTE the anonymous lifetime #1 defined on the method body
{
- //~^ NOTE the anonymous lifetime #1 defined on the body
- //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the body
Some(&mut self.0)
}
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Dim {
+ fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+ fn dim() -> usize {
+ 3
+ }
+}
+
+fn main() {
+ let array: [usize; Dim3::dim()]
+ //~^ ERROR calls in constants are limited to constant functions
+ = [0; Dim3::dim()];
+ //~^ ERROR calls in constants are limited to constant functions
+}
pub struct Vector<T, D: Dim> {
entries: [T; D::dim()]
- //~^ ERROR cannot use an outer type parameter in this context
+ //~^ ERROR no associated item named `dim` found for type `D` in the current scope
}
-fn main() {
- let array: [usize; Dim3::dim()]
- //~^ ERROR calls in constants are limited to constant functions
- = [0; Dim3::dim()];
- //~^ ERROR calls in constants are limited to constant functions
-}
+fn main() {}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let a = 42._; //~ ERROR unexpected token: `_`
+}
A::X - B::X
}
+trait Bar: Foo {
+ const Y: i32 = Self::X;
+}
+
fn main() {
assert_eq!(11, Abc::X);
assert_eq!(97, Def::X);
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// this used to cause exponential code-size blowup during LLVM passes.
+// min-llvm-version 3.9
+
+#![feature(test)]
+
+extern crate test;
+
+struct MayUnwind;
+
+impl Drop for MayUnwind {
+ fn drop(&mut self) {
+ if test::black_box(false) {
+ panic!()
+ }
+ }
+}
+
+struct DS<U> {
+ may_unwind: MayUnwind,
+ name: String,
+ next: U,
+}
+
+fn add<U>(ds: DS<U>, name: String) -> DS<DS<U>> {
+ DS {
+ may_unwind: MayUnwind,
+ name: "?".to_owned(),
+ next: ds,
+ }
+}
+
+fn main() {
+ let deserializers = DS { may_unwind: MayUnwind, name: "?".to_owned(), next: () };
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned());
+ let deserializers = add(deserializers, "?".to_owned()); // 0.7s
+ let deserializers = add(deserializers, "?".to_owned()); // 1.3s
+ let deserializers = add(deserializers, "?".to_owned()); // 2.4s
+ let deserializers = add(deserializers, "?".to_owned()); // 6.7s
+ let deserializers = add(deserializers, "?".to_owned()); // 26.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 114.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 228.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 400.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 800.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 1600.0s
+ let deserializers = add(deserializers, "?".to_owned()); // 3200.0s
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tc {}
+impl Tc for bool {}
+
+fn main() {
+ let _: &[&Tc] = &[&true];
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tr : Sized {
+ fn _method_on_numbers(self) {}
+}
+
+impl Tr for i32 {}
+
+fn main() {
+ 42._method_on_numbers();
+}
12 | if x > y { x } else { y }
| ^
|
-note: ...the reference is valid for the lifetime 'a as defined on the body at 11:43...
- --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
+note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:0...
+ --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
-11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
- | ____________________________________________^
+11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43
- --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:0
+ --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
-11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
- | ____________________________________________^
+11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
|
= note: expected type `Ref<'a, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #2 defined on the body at 15:51...
- --> $DIR/ex2a-push-one-existing-name.rs:15:52
+note: the anonymous lifetime #2 defined on the function body at 15:0...
+ --> $DIR/ex2a-push-one-existing-name.rs:15:1
|
-15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
- | ____________________________________________________^
+15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51
- --> $DIR/ex2a-push-one-existing-name.rs:15:52
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:0
+ --> $DIR/ex2a-push-one-existing-name.rs:15:1
|
-15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
- | ____________________________________________________^
+15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
|
= note: expected type `Ref<'_, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the body at 15:43...
- --> $DIR/ex2b-push-no-existing-names.rs:15:44
+note: the anonymous lifetime #3 defined on the function body at 15:0...
+ --> $DIR/ex2b-push-no-existing-names.rs:15:1
|
-15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
- | ____________________________________________^
+15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43
- --> $DIR/ex2b-push-no-existing-names.rs:15:44
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:0
+ --> $DIR/ex2b-push-no-existing-names.rs:15:1
|
-15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
- | ____________________________________________^
+15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
16 | let z = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
- --> $DIR/ex2c-push-inference-variable.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+ --> $DIR/ex2c-push-inference-variable.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let z = Ref { data: y.data };
17 | | x.push(z);
18 | | }
|
16 | let z = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
- --> $DIR/ex2c-push-inference-variable.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+ --> $DIR/ex2c-push-inference-variable.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let z = Ref { data: y.data };
17 | | x.push(z);
18 | | }
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
- --> $DIR/ex2d-push-inference-variable-2.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+ --> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | a.push(b);
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
- --> $DIR/ex2d-push-inference-variable-2.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+ --> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | a.push(b);
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66...
- --> $DIR/ex2e-push-inference-variable-3.rs:15:67
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+ --> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | Vec::push(a, b);
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66...
- --> $DIR/ex2e-push-inference-variable-3.rs:15:67
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+ --> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
-15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
- | ___________________________________________________________________^
+15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
16 | | let a: &mut Vec<Ref<i32>> = x;
17 | | let b = Ref { data: y.data };
18 | | Vec::push(a, b);
15 | let _ = namespaced_enums::A;
| ^ not found in `namespaced_enums`
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use namespaced_enums::Foo::A;`
+help: possible candidate is found in another module, you can import it into scope
+ | use namespaced_enums::Foo::A;
error[E0425]: cannot find function `B` in module `namespaced_enums`
--> $DIR/enums-are-namespaced-xc.rs:18:31
18 | let _ = namespaced_enums::B(10);
| ^ not found in `namespaced_enums`
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use namespaced_enums::Foo::B;`
+help: possible candidate is found in another module, you can import it into scope
+ | use namespaced_enums::Foo::B;
error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
--> $DIR/enums-are-namespaced-xc.rs:21:31
21 | let _ = namespaced_enums::C { a: 10 };
| ^ not found in `namespaced_enums`
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use namespaced_enums::Foo::C;`
+help: possible candidate is found in another module, you can import it into scope
+ | use namespaced_enums::Foo::C;
error: aborting due to 3 previous errors
19 | Result {
| ^^^^^^ not a struct, variant or union type
|
- = help: possible better candidates are found in other modules, you can import them into scope:
- `use std::fmt::Result;`
- `use std::io::Result;`
- `use std::thread::Result;`
+help: possible better candidates are found in other modules, you can import them into scope
+ | use std::fmt::Result;
+ | use std::io::Result;
+ | use std::thread::Result;
error: aborting due to previous error
16 | E { name: "foobar" }; //~ ERROR unresolved struct, variant or union type `E`
| ^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use SomeEnum::E;`
+help: possible candidate is found in another module, you can import it into scope
+ | use SomeEnum::E;
error: aborting due to previous error
53 | impl Mul for Foo {
| ^^^ not found in this scope
|
- = help: possible candidates are found in other modules, you can import them into scope:
- `use mul1::Mul;`
- `use mul2::Mul;`
- `use std::ops::Mul;`
+help: possible candidates are found in other modules, you can import them into scope
+ | use mul1::Mul;
+ | use mul2::Mul;
+ | use std::ops::Mul;
error[E0412]: cannot find type `Mul` in this scope
--> $DIR/issue-21221-1.rs:72:16
72 | fn getMul() -> Mul {
| ^^^ not found in this scope
|
- = help: possible candidates are found in other modules, you can import them into scope:
- `use mul1::Mul;`
- `use mul2::Mul;`
- `use mul3::Mul;`
- `use mul4::Mul;`
- and 2 other candidates
+help: possible candidates are found in other modules, you can import them into scope
+ | use mul1::Mul;
+ | use mul2::Mul;
+ | use mul3::Mul;
+ | use mul4::Mul;
+and 2 other candidates
error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
--> $DIR/issue-21221-1.rs:83:6
88 | impl Div for Foo {
| ^^^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use std::ops::Div;`
+help: possible candidate is found in another module, you can import it into scope
+ | use std::ops::Div;
error: cannot continue compilation due to previous error
28 | impl T for Foo { }
| ^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use foo::bar::T;`
+help: possible candidate is found in another module, you can import it into scope
+ | use foo::bar::T;
error: main function not found
25 | impl OuterTrait for Foo {}
| ^^^^^^^^^^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use issue_21221_3::outer::OuterTrait;`
+help: possible candidate is found in another module, you can import it into scope
+ | use issue_21221_3::outer::OuterTrait;
error: cannot continue compilation due to previous error
20 | impl T for Foo {}
| ^ not found in this scope
|
- = help: possible candidate is found in another module, you can import it into scope:
- `use issue_21221_4::T;`
+help: possible candidate is found in another module, you can import it into scope
+ | use issue_21221_4::T;
error: cannot continue compilation due to previous error
20 | impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
| ^^^ type aliases cannot be used for traits
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use issue_3907::Foo;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use issue_3907::Foo;
error: cannot continue compilation due to previous error
| did you mean `S`?
| constructor is not visible here due to private fields
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use m::n::Z;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use m::n::Z;
error[E0423]: expected value, found struct `S`
--> $DIR/privacy-struct-ctor.rs:36:5
| did you mean `S { /* fields */ }`?
| constructor is not visible here due to private fields
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use m::S;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use m::S;
error[E0423]: expected value, found struct `xcrate::S`
--> $DIR/privacy-struct-ctor.rs:42:5
| did you mean `xcrate::S { /* fields */ }`?
| constructor is not visible here due to private fields
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use m::S;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use m::S;
error: tuple struct `Z` is private
--> $DIR/privacy-struct-ctor.rs:25:9
15 | impl<T: Clone, Add> Add for Foo<T> {
| ^^^ not a trait
|
- = help: possible better candidate is found in another module, you can import it into scope:
- `use std::ops::Add;`
+help: possible better candidate is found in another module, you can import it into scope
+ | use std::ops::Add;
error: main function not found
"Unlicense/MIT",
];
-/// These MPL licensed projects are acceptable, but only these.
+// These are exceptions to Rust's permissive licensing policy, and
+// should be considered bugs. Exceptions are only allowed in Rust
+// tooling. It is _crucial_ that no exception crates be dependencies
+// of the Rust runtime (std / test).
static EXCEPTIONS: &'static [&'static str] = &[
- "mdbook",
- "openssl",
- "pest",
- "thread-id",
+ "mdbook", // MPL2, mdbook
+ "openssl", // BSD+advertising clause, cargo, mdbook
+ "pest", // MPL2, mdbook via handlebars
+ "thread-id", // Apache-2.0, mdbook
];
pub fn check(path: &Path, bad: &mut bool) {
contents.truncate(0);
t!(t!(File::open(file), file).read_to_string(&mut contents));
+
+ if contents.is_empty() {
+ tidy_error!(bad, "{}: empty file", file.display());
+ }
+
let skip_cr = contents.contains("ignore-tidy-cr");
let skip_tab = contents.contains("ignore-tidy-tab");
let skip_length = contents.contains("ignore-tidy-linelength");