Merge branch 'master' into redox
This commit is contained in:
commit
3e15dc108c
|
@ -19,7 +19,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.0.0",
|
||||
]
|
||||
|
||||
|
@ -42,7 +42,7 @@ dependencies = [
|
|||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -63,7 +63,7 @@ name = "cmake"
|
|||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -80,7 +80,7 @@ name = "compiler_builtins"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -121,7 +121,7 @@ name = "flate"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -130,7 +130,7 @@ version = "0.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.38"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -402,7 +402,7 @@ name = "rustc_llvm"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_bitflags 0.0.0",
|
||||
]
|
||||
|
||||
|
@ -551,7 +551,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"arena 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
|
@ -587,7 +587,7 @@ dependencies = [
|
|||
"collections 0.0.0",
|
||||
"compiler_builtins 0.0.0",
|
||||
"core 0.0.0",
|
||||
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.0.0",
|
||||
"panic_abort 0.0.0",
|
||||
"panic_unwind 0.0.0",
|
||||
|
@ -677,7 +677,7 @@ dependencies = [
|
|||
"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283"
|
||||
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
|
||||
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
|
||||
"checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5"
|
||||
"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"
|
||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
|
||||
"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
|
||||
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//! `package_vers`, and otherwise indicating to the compiler what it should
|
||||
//! print out as part of its version information.
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::process::Command;
|
||||
|
||||
|
@ -69,7 +69,7 @@ pub fn collect(build: &mut Build) {
|
|||
|
||||
// If we have a git directory, add in some various SHA information of what
|
||||
// commit this compiler was compiled from.
|
||||
if fs::metadata(build.src.join(".git")).is_ok() {
|
||||
if build.src.join(".git").is_dir() {
|
||||
let ver_date = output(Command::new("git").current_dir(&build.src)
|
||||
.arg("log").arg("-1")
|
||||
.arg("--date=short")
|
||||
|
|
|
@ -299,6 +299,7 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
|
|||
build.add_rust_test_threads(&mut cmd);
|
||||
cmd.arg("--test");
|
||||
cmd.arg(markdown);
|
||||
cmd.env("RUSTC_BOOTSTRAP", "1");
|
||||
|
||||
let mut test_args = build.flags.cmd.test_args().join(" ");
|
||||
if build.config.quiet_tests {
|
||||
|
|
|
@ -48,6 +48,11 @@ pub fn tmpdir(build: &Build) -> PathBuf {
|
|||
/// Slurps up documentation from the `stage`'s `host`.
|
||||
pub fn docs(build: &Build, stage: u32, host: &str) {
|
||||
println!("Dist docs stage{} ({})", stage, host);
|
||||
if !build.config.docs {
|
||||
println!("\tskipping - docs disabled");
|
||||
return
|
||||
}
|
||||
|
||||
let name = format!("rust-docs-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-{}-image", name, name));
|
||||
let _ = fs::remove_dir_all(&image);
|
||||
|
@ -260,6 +265,14 @@ pub fn debugger_scripts(build: &Build,
|
|||
pub fn std(build: &Build, compiler: &Compiler, target: &str) {
|
||||
println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host,
|
||||
target);
|
||||
|
||||
// The only true set of target libraries came from the build triple, so
|
||||
// let's reduce redundant work by only producing archives from that host.
|
||||
if compiler.host != build.config.build {
|
||||
println!("\tskipping, not a build host");
|
||||
return
|
||||
}
|
||||
|
||||
let name = format!("rust-std-{}", package_vers(build));
|
||||
let image = tmpdir(build).join(format!("{}-{}-image", name, target));
|
||||
let _ = fs::remove_dir_all(&image);
|
||||
|
@ -294,10 +307,15 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
|
|||
println!("Dist analysis");
|
||||
|
||||
if build.config.channel != "nightly" {
|
||||
println!("Skipping dist-analysis - not on nightly channel");
|
||||
println!("\tskipping - not on nightly channel");
|
||||
return;
|
||||
}
|
||||
if compiler.host != build.config.build {
|
||||
println!("\tskipping - not a build host");
|
||||
return
|
||||
}
|
||||
if compiler.stage != 2 {
|
||||
println!("\tskipping - not stage2");
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -324,13 +342,6 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
|
|||
.arg("--legacy-manifest-dirs=rustlib,cargo");
|
||||
build.run(&mut cmd);
|
||||
t!(fs::remove_dir_all(&image));
|
||||
|
||||
// Create plain source tarball
|
||||
let mut cmd = Command::new("tar");
|
||||
cmd.arg("-czf").arg(sanitize_sh(&distdir(build).join(&format!("{}.tar.gz", name))))
|
||||
.arg("analysis")
|
||||
.current_dir(&src);
|
||||
build.run(&mut cmd);
|
||||
}
|
||||
|
||||
/// Creates the `rust-src` installer component and the plain source tarball
|
||||
|
|
|
@ -499,7 +499,7 @@ pub fn build_rules(build: &Build) -> Rules {
|
|||
.default(true)
|
||||
.dep(|s| s.name("default:doc"))
|
||||
.run(move |s| dist::docs(build, s.stage, s.target));
|
||||
rules.dist("dist-analysis", "src/libstd")
|
||||
rules.dist("dist-analysis", "analysis")
|
||||
.dep(|s| s.name("dist-std"))
|
||||
.default(true)
|
||||
.run(move |s| dist::analysis(build, &s.compiler(), s.target));
|
||||
|
|
|
@ -25,8 +25,13 @@ COPY install-ndk.sh install-sdk.sh accept-licenses.sh /android/
|
|||
RUN sh /android/install-ndk.sh
|
||||
RUN sh /android/install-sdk.sh
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
|
||||
COPY start-emulator.sh /android/
|
||||
ENTRYPOINT ["/android/start-emulator.sh"]
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/android/start-emulator.sh"]
|
||||
|
||||
ENV TARGETS=arm-linux-androideabi
|
||||
ENV TARGETS=$TARGETS,i686-linux-android
|
||||
|
|
|
@ -23,6 +23,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \
|
||||
gcc-s390x-linux-gnu libc6-dev-s390x-cross
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV TARGETS=aarch64-unknown-linux-gnu
|
||||
ENV TARGETS=$TARGETS,arm-unknown-linux-gnueabi
|
||||
ENV TARGETS=$TARGETS,arm-unknown-linux-gnueabihf
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
sudo \
|
||||
gdb
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
sudo \
|
||||
gdb
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
|
|
|
@ -18,6 +18,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
COPY build-toolchain.sh /tmp/
|
||||
RUN sh /tmp/build-toolchain.sh
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV \
|
||||
AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \
|
||||
CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-gcc
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
libssl-dev \
|
||||
sudo
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check-cargotest
|
||||
ENV NO_VENDOR 1
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
sudo \
|
||||
gdb
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--enable-debug \
|
||||
|
|
|
@ -16,6 +16,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
libedit-dev \
|
||||
zlib1g-dev
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--llvm-root=/usr/lib/llvm-3.7
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
sudo \
|
||||
gdb
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
sudo \
|
||||
gdb
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
|
|
|
@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
sudo \
|
||||
gdb
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
|
||||
ENV RUST_CHECK_TARGET check
|
||||
RUN mkdir /tmp/obj
|
||||
|
|
|
@ -18,6 +18,11 @@ WORKDIR /build/
|
|||
COPY build-musl.sh /build/
|
||||
RUN sh /build/build-musl.sh && rm -rf /build
|
||||
|
||||
RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
|
||||
dpkg -i dumb-init_*.deb && \
|
||||
rm dumb-init_*.deb
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=x86_64-unknown-linux-musl \
|
||||
--musl-root-x86_64=/musl-x86_64
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
font-family: 'Source Code Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff');
|
||||
/* Avoid using locally installed font because bad versions are in circulation:
|
||||
* see https://github.com/rust-lang/rust/issues/24355 */
|
||||
src: url("SourceCodePro-Regular.woff") format('woff');
|
||||
}
|
||||
|
||||
*:not(body) {
|
||||
|
|
|
@ -117,6 +117,8 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
|
|||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// The pointer must be aligned; use `read_unaligned` if that is not the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -137,6 +139,44 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
|||
tmp
|
||||
}
|
||||
|
||||
/// Reads the value from `src` without moving it. This leaves the
|
||||
/// memory in `src` unchanged.
|
||||
///
|
||||
/// Unlike `read`, the pointer may be unaligned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Beyond accepting a raw pointer, this is unsafe because it semantically
|
||||
/// moves the value out of `src` without preventing further usage of `src`.
|
||||
/// If `T` is not `Copy`, then care must be taken to ensure that the value at
|
||||
/// `src` is not used before the data is overwritten again (e.g. with `write`,
|
||||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_unaligned)]
|
||||
///
|
||||
/// let x = 12;
|
||||
/// let y = &x as *const i32;
|
||||
///
|
||||
/// unsafe {
|
||||
/// assert_eq!(std::ptr::read_unaligned(y), 12);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "ptr_unaligned", issue = "37955")]
|
||||
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||
let mut tmp: T = mem::uninitialized();
|
||||
copy_nonoverlapping(src as *const u8,
|
||||
&mut tmp as *mut T as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
tmp
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
/// dropping the old value.
|
||||
///
|
||||
|
@ -151,6 +191,8 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
|||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// The pointer must be aligned; use `write_unaligned` if that is not the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -171,6 +213,47 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
|||
intrinsics::move_val_init(&mut *dst, src)
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
/// dropping the old value.
|
||||
///
|
||||
/// Unlike `write`, the pointer may be unaligned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This operation is marked unsafe because it accepts a raw pointer.
|
||||
///
|
||||
/// It does not drop the contents of `dst`. This is safe, but it could leak
|
||||
/// allocations or resources, so care must be taken not to overwrite an object
|
||||
/// that should be dropped.
|
||||
///
|
||||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_unaligned)]
|
||||
///
|
||||
/// let mut x = 0;
|
||||
/// let y = &mut x as *mut i32;
|
||||
/// let z = 12;
|
||||
///
|
||||
/// unsafe {
|
||||
/// std::ptr::write_unaligned(y, z);
|
||||
/// assert_eq!(std::ptr::read_unaligned(y), 12);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_unaligned", issue = "37955")]
|
||||
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
||||
copy_nonoverlapping(&src as *const T as *const u8,
|
||||
dst as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
mem::forget(src);
|
||||
}
|
||||
|
||||
/// Performs a volatile read of the value from `src` without moving it. This
|
||||
/// leaves the memory in `src` unchanged.
|
||||
///
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#![feature(iter_min_by)]
|
||||
#![feature(ordering_chaining)]
|
||||
#![feature(result_unwrap_or_default)]
|
||||
#![feature(ptr_unaligned)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use core::ptr::*;
|
||||
use core::cell::RefCell;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
|
@ -189,3 +190,25 @@ pub fn test_variadic_fnptr() {
|
|||
let mut s = SipHasher::new();
|
||||
assert_eq!(p.hash(&mut s), q.hash(&mut s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_unaligned_drop() {
|
||||
thread_local! {
|
||||
static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
struct Dropper(u32);
|
||||
|
||||
impl Drop for Dropper {
|
||||
fn drop(&mut self) {
|
||||
DROPS.with(|d| d.borrow_mut().push(self.0));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let c = Dropper(0);
|
||||
let mut t = Dropper(1);
|
||||
unsafe { write_unaligned(&mut t, c); }
|
||||
}
|
||||
DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
use std::str;
|
||||
|
||||
pub const MAX_BASE: u64 = 64;
|
||||
pub const ALPHANUMERIC_ONLY: u64 = 62;
|
||||
|
||||
const BASE_64: &'static [u8; MAX_BASE as usize] =
|
||||
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
|
||||
|
||||
|
|
|
@ -1417,7 +1417,8 @@ extern "C" {
|
|||
Ty: DIType,
|
||||
isLocalToUnit: bool,
|
||||
Val: ValueRef,
|
||||
Decl: DIDescriptor)
|
||||
Decl: DIDescriptor,
|
||||
AlignInBits: u64)
|
||||
-> DIGlobalVariable;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef,
|
||||
|
@ -1429,7 +1430,8 @@ extern "C" {
|
|||
Ty: DIType,
|
||||
AlwaysPreserve: bool,
|
||||
Flags: DIFlags,
|
||||
ArgNo: c_uint)
|
||||
ArgNo: c_uint,
|
||||
AlignInBits: u64)
|
||||
-> DIVariable;
|
||||
|
||||
pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef,
|
||||
|
|
|
@ -44,7 +44,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
|||
use syntax::attr;
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::codemap;
|
||||
use syntax_pos::{self, Span, BytePos, Pos};
|
||||
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
|
||||
|
||||
pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||
opaque: opaque::Decoder<'a>,
|
||||
|
@ -515,7 +515,12 @@ impl<'tcx> EntryKind<'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> CrateMetadata {
|
||||
fn is_proc_macro(&self, id: DefIndex) -> bool {
|
||||
self.proc_macros.is_some() && id != CRATE_DEF_INDEX
|
||||
}
|
||||
|
||||
fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
|
||||
assert!(!self.is_proc_macro(item_id));
|
||||
self.root.index.lookup(self.blob.raw_bytes(), item_id)
|
||||
}
|
||||
|
||||
|
@ -548,18 +553,17 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
}
|
||||
|
||||
pub fn get_def(&self, index: DefIndex) -> Option<Def> {
|
||||
if self.proc_macros.is_some() {
|
||||
Some(match index {
|
||||
CRATE_DEF_INDEX => Def::Mod(self.local_def_id(index)),
|
||||
_ => Def::Macro(self.local_def_id(index)),
|
||||
})
|
||||
} else {
|
||||
self.entry(index).kind.to_def(self.local_def_id(index))
|
||||
match self.is_proc_macro(index) {
|
||||
true => Some(Def::Macro(self.local_def_id(index))),
|
||||
false => self.entry(index).kind.to_def(self.local_def_id(index)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
|
||||
self.entry(index).span.decode((self, sess))
|
||||
match self.is_proc_macro(index) {
|
||||
true => DUMMY_SP,
|
||||
false => self.entry(index).span.decode((self, sess)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trait_def(&self,
|
||||
|
@ -670,23 +674,23 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
}
|
||||
|
||||
pub fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
|
||||
match self.proc_macros {
|
||||
Some(_) if id != CRATE_DEF_INDEX => None,
|
||||
_ => self.entry(id).stability.map(|stab| stab.decode(self)),
|
||||
match self.is_proc_macro(id) {
|
||||
true => None,
|
||||
false => self.entry(id).stability.map(|stab| stab.decode(self)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
|
||||
match self.proc_macros {
|
||||
Some(_) if id != CRATE_DEF_INDEX => None,
|
||||
_ => self.entry(id).deprecation.map(|depr| depr.decode(self)),
|
||||
match self.is_proc_macro(id) {
|
||||
true => None,
|
||||
false => self.entry(id).deprecation.map(|depr| depr.decode(self)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
|
||||
match self.proc_macros {
|
||||
Some(_) => ty::Visibility::Public,
|
||||
_ => self.entry(id).visibility,
|
||||
match self.is_proc_macro(id) {
|
||||
true => ty::Visibility::Public,
|
||||
false => self.entry(id).visibility,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -832,6 +836,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
id: DefIndex)
|
||||
-> Option<&'tcx InlinedItem> {
|
||||
debug!("Looking up item: {:?}", id);
|
||||
if self.is_proc_macro(id) { return None; }
|
||||
let item_doc = self.entry(id);
|
||||
let item_did = self.local_def_id(id);
|
||||
let parent_def_id = self.local_def_id(self.def_key(id).parent.unwrap());
|
||||
|
@ -844,6 +849,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
}
|
||||
|
||||
pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
|
||||
!self.is_proc_macro(id) &&
|
||||
self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
|
||||
}
|
||||
|
||||
|
@ -874,7 +880,10 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
id: DefIndex)
|
||||
-> Option<Mir<'tcx>> {
|
||||
self.entry(id).mir.map(|mir| mir.decode((self, tcx)))
|
||||
match self.is_proc_macro(id) {
|
||||
true => None,
|
||||
false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
|
||||
|
@ -950,7 +959,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
}
|
||||
|
||||
pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec<ast::Attribute> {
|
||||
if self.proc_macros.is_some() && node_id != CRATE_DEF_INDEX {
|
||||
if self.is_proc_macro(node_id) {
|
||||
return Vec::new();
|
||||
}
|
||||
// The attributes for a tuple struct are attached to the definition, not the ctor;
|
||||
|
@ -1131,7 +1140,18 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
|
||||
pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey {
|
||||
debug!("def_key: id={:?}", id);
|
||||
self.entry(id).def_key.decode(self)
|
||||
if self.is_proc_macro(id) {
|
||||
let name = self.proc_macros.as_ref().unwrap()[id.as_usize() - 1].0;
|
||||
hir_map::DefKey {
|
||||
parent: Some(CRATE_DEF_INDEX),
|
||||
disambiguated_data: hir_map::DisambiguatedDefPathData {
|
||||
data: hir_map::DefPathData::MacroDef(name.as_str()),
|
||||
disambiguator: 0,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
self.entry(id).def_key.decode(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the path leading to the thing with this `id`. Note that
|
||||
|
@ -1139,7 +1159,7 @@ impl<'a, 'tcx> CrateMetadata {
|
|||
// returns `None`
|
||||
pub fn def_path(&self, id: DefIndex) -> Option<hir_map::DefPath> {
|
||||
debug!("def_path(id={:?})", id);
|
||||
if self.maybe_entry(id).is_some() {
|
||||
if self.is_proc_macro(id) || self.maybe_entry(id).is_some() {
|
||||
Some(hir_map::DefPath::make(self.cnum, id, |parent| self.def_key(parent)))
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -26,7 +26,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
|
|||
extent: cx.tcx.region_maps.node_extent(self.id),
|
||||
span: self.span,
|
||||
stmts: stmts,
|
||||
expr: self.expr.to_ref()
|
||||
expr: self.expr.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,39 +34,44 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
|
|||
fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
block_id: ast::NodeId,
|
||||
stmts: &'tcx [hir::Stmt])
|
||||
-> Vec<StmtRef<'tcx>>
|
||||
{
|
||||
-> Vec<StmtRef<'tcx>> {
|
||||
let mut result = vec![];
|
||||
for (index, stmt) in stmts.iter().enumerate() {
|
||||
match stmt.node {
|
||||
hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) =>
|
||||
hir::StmtExpr(ref expr, id) |
|
||||
hir::StmtSemi(ref expr, id) => {
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
span: stmt.span,
|
||||
kind: StmtKind::Expr {
|
||||
scope: cx.tcx.region_maps.node_extent(id),
|
||||
expr: expr.to_ref()
|
||||
expr: expr.to_ref(),
|
||||
},
|
||||
})))
|
||||
}
|
||||
hir::StmtDecl(ref decl, id) => {
|
||||
match decl.node {
|
||||
hir::DeclItem(..) => {
|
||||
// ignore for purposes of the MIR
|
||||
}
|
||||
}))),
|
||||
hir::StmtDecl(ref decl, id) => match decl.node {
|
||||
hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
|
||||
hir::DeclLocal(ref local) => {
|
||||
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
|
||||
block: block_id,
|
||||
first_statement_index: index as u32,
|
||||
});
|
||||
let remainder_extent =
|
||||
cx.tcx.region_maps.lookup_code_extent(remainder_extent);
|
||||
hir::DeclLocal(ref local) => {
|
||||
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
|
||||
block: block_id,
|
||||
first_statement_index: index as u32,
|
||||
});
|
||||
let remainder_extent =
|
||||
cx.tcx.region_maps.lookup_code_extent(remainder_extent);
|
||||
|
||||
let pattern = Pattern::from_hir(cx.tcx, &local.pat);
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
span: stmt.span,
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_extent,
|
||||
init_scope: cx.tcx.region_maps.node_extent(id),
|
||||
pattern: pattern,
|
||||
initializer: local.init.to_ref(),
|
||||
},
|
||||
})));
|
||||
let pattern = Pattern::from_hir(cx.tcx, &local.pat);
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
span: stmt.span,
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_extent,
|
||||
init_scope: cx.tcx.region_maps.node_extent(id),
|
||||
pattern: pattern,
|
||||
initializer: local.init.to_ref(),
|
||||
},
|
||||
})));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
|||
let adj = cx.tcx.tables().adjustments.get(&self.id).cloned();
|
||||
|
||||
debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}",
|
||||
expr, adj);
|
||||
expr,
|
||||
adj);
|
||||
|
||||
// Now apply adjustments, if any.
|
||||
match adj.map(|adj| (adj.kind, adj.target)) {
|
||||
|
@ -78,41 +79,44 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
|||
for i in 0..autoderefs {
|
||||
let i = i as u32;
|
||||
let adjusted_ty =
|
||||
expr.ty.adjust_for_autoderef(
|
||||
cx.tcx,
|
||||
self.id,
|
||||
self.span,
|
||||
i,
|
||||
|mc| cx.tcx.tables().method_map.get(&mc).map(|m| m.ty));
|
||||
debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty);
|
||||
expr.ty.adjust_for_autoderef(cx.tcx, self.id, self.span, i, |mc| {
|
||||
cx.tcx.tables().method_map.get(&mc).map(|m| m.ty)
|
||||
});
|
||||
debug!("make_mirror: autoderef #{}, adjusted_ty={:?}",
|
||||
i,
|
||||
adjusted_ty);
|
||||
let method_key = ty::MethodCall::autoderef(self.id, i);
|
||||
let meth_ty =
|
||||
cx.tcx.tables().method_map.get(&method_key).map(|m| m.ty);
|
||||
let meth_ty = cx.tcx.tables().method_map.get(&method_key).map(|m| m.ty);
|
||||
let kind = if let Some(meth_ty) = meth_ty {
|
||||
debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty);
|
||||
|
||||
let ref_ty = cx.tcx.no_late_bound_regions(&meth_ty.fn_ret());
|
||||
let (region, mutbl) = match ref_ty {
|
||||
Some(&ty::TyS {
|
||||
sty: ty::TyRef(region, mt), ..
|
||||
}) => (region, mt.mutbl),
|
||||
_ => span_bug!(expr.span, "autoderef returned bad type")
|
||||
Some(&ty::TyS { sty: ty::TyRef(region, mt), .. }) => (region, mt.mutbl),
|
||||
_ => span_bug!(expr.span, "autoderef returned bad type"),
|
||||
};
|
||||
|
||||
expr = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: cx.tcx.mk_ref(
|
||||
region, ty::TypeAndMut { ty: expr.ty, mutbl: mutbl }),
|
||||
ty: cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: expr.ty,
|
||||
mutbl: mutbl,
|
||||
}),
|
||||
span: expr.span,
|
||||
kind: ExprKind::Borrow {
|
||||
region: region,
|
||||
borrow_kind: to_borrow_kind(mutbl),
|
||||
arg: expr.to_ref()
|
||||
}
|
||||
arg: expr.to_ref(),
|
||||
},
|
||||
};
|
||||
|
||||
overloaded_lvalue(cx, self, method_key,
|
||||
PassArgs::ByRef, expr.to_ref(), vec![])
|
||||
overloaded_lvalue(cx,
|
||||
self,
|
||||
method_key,
|
||||
PassArgs::ByRef,
|
||||
expr.to_ref(),
|
||||
vec![])
|
||||
} else {
|
||||
debug!("make_mirror: built-in autoderef");
|
||||
ExprKind::Deref { arg: expr.to_ref() }
|
||||
|
@ -148,7 +152,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
|||
let region = cx.tcx.mk_region(region);
|
||||
expr = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: cx.tcx.mk_ref(region, ty::TypeAndMut { ty: expr.ty, mutbl: m }),
|
||||
ty: cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: expr.ty,
|
||||
mutbl: m,
|
||||
}),
|
||||
span: self.span,
|
||||
kind: ExprKind::Borrow {
|
||||
region: region,
|
||||
|
@ -240,12 +248,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
let sig = match method.ty.sty {
|
||||
ty::TyFnDef(.., fn_ty) => &fn_ty.sig,
|
||||
_ => span_bug!(expr.span, "type of method is not an fn")
|
||||
_ => span_bug!(expr.span, "type of method is not an fn"),
|
||||
};
|
||||
|
||||
let sig = cx.tcx.no_late_bound_regions(sig).unwrap_or_else(|| {
|
||||
span_bug!(expr.span, "method call has late-bound regions")
|
||||
});
|
||||
let sig = cx.tcx
|
||||
.no_late_bound_regions(sig)
|
||||
.unwrap_or_else(|| span_bug!(expr.span, "method call has late-bound regions"));
|
||||
|
||||
assert_eq!(sig.inputs().len(), 2);
|
||||
|
||||
|
@ -253,44 +261,49 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
ty: sig.inputs()[1],
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Tuple {
|
||||
fields: args.iter().map(ToRef::to_ref).collect()
|
||||
}
|
||||
kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() },
|
||||
};
|
||||
|
||||
ExprKind::Call {
|
||||
ty: method.ty,
|
||||
fun: method.to_ref(),
|
||||
args: vec![fun.to_ref(), tupled_args.to_ref()]
|
||||
args: vec![fun.to_ref(), tupled_args.to_ref()],
|
||||
}
|
||||
} else {
|
||||
let adt_data = if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = fun.node {
|
||||
// Tuple-like ADTs are represented as ExprCall. We convert them here.
|
||||
expr_ty.ty_adt_def().and_then(|adt_def|{
|
||||
expr_ty.ty_adt_def().and_then(|adt_def| {
|
||||
match path.def {
|
||||
Def::VariantCtor(variant_id, CtorKind::Fn) => {
|
||||
Some((adt_def, adt_def.variant_index_with_id(variant_id)))
|
||||
},
|
||||
Def::StructCtor(_, CtorKind::Fn) => {
|
||||
Some((adt_def, 0))
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
Def::StructCtor(_, CtorKind::Fn) => Some((adt_def, 0)),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
} else { None };
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some((adt_def, index)) = adt_data {
|
||||
let substs = cx.tcx.tables().node_id_item_substs(fun.id)
|
||||
let substs = cx.tcx
|
||||
.tables()
|
||||
.node_id_item_substs(fun.id)
|
||||
.unwrap_or_else(|| cx.tcx.intern_substs(&[]));
|
||||
let field_refs = args.iter().enumerate().map(|(idx, e)| FieldExprRef {
|
||||
name: Field::new(idx),
|
||||
expr: e.to_ref()
|
||||
}).collect();
|
||||
let field_refs = args.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, e)| {
|
||||
FieldExprRef {
|
||||
name: Field::new(idx),
|
||||
expr: e.to_ref(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
ExprKind::Adt {
|
||||
adt_def: adt_def,
|
||||
substs: substs,
|
||||
variant_index: index,
|
||||
fields: field_refs,
|
||||
base: None
|
||||
base: None,
|
||||
}
|
||||
} else {
|
||||
ExprKind::Call {
|
||||
|
@ -314,9 +327,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
hir::ExprBlock(ref blk) => {
|
||||
ExprKind::Block { body: &blk }
|
||||
}
|
||||
hir::ExprBlock(ref blk) => ExprKind::Block { body: &blk },
|
||||
|
||||
hir::ExprAssign(ref lhs, ref rhs) => {
|
||||
ExprKind::Assign {
|
||||
|
@ -332,8 +343,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
} else {
|
||||
PassArgs::ByRef
|
||||
};
|
||||
overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
|
||||
pass_args, lhs.to_ref(), vec![rhs])
|
||||
overloaded_operator(cx,
|
||||
expr,
|
||||
ty::MethodCall::expr(expr.id),
|
||||
pass_args,
|
||||
lhs.to_ref(),
|
||||
vec![rhs])
|
||||
} else {
|
||||
ExprKind::AssignOp {
|
||||
op: bin_op(op.node),
|
||||
|
@ -343,9 +358,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
hir::ExprLit(..) => ExprKind::Literal {
|
||||
literal: cx.const_eval_literal(expr)
|
||||
},
|
||||
hir::ExprLit(..) => ExprKind::Literal { literal: cx.const_eval_literal(expr) },
|
||||
|
||||
hir::ExprBinary(op, ref lhs, ref rhs) => {
|
||||
if cx.tcx.tables().is_method_call(expr.id) {
|
||||
|
@ -354,8 +367,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
} else {
|
||||
PassArgs::ByRef
|
||||
};
|
||||
overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
|
||||
pass_args, lhs.to_ref(), vec![rhs])
|
||||
overloaded_operator(cx,
|
||||
expr,
|
||||
ty::MethodCall::expr(expr.id),
|
||||
pass_args,
|
||||
lhs.to_ref(),
|
||||
vec![rhs])
|
||||
} else {
|
||||
// FIXME overflow
|
||||
match (op.node, cx.constness) {
|
||||
|
@ -405,8 +422,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
hir::ExprIndex(ref lhs, ref index) => {
|
||||
if cx.tcx.tables().is_method_call(expr.id) {
|
||||
overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue, lhs.to_ref(), vec![index])
|
||||
overloaded_lvalue(cx,
|
||||
expr,
|
||||
ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue,
|
||||
lhs.to_ref(),
|
||||
vec![index])
|
||||
} else {
|
||||
ExprKind::Index {
|
||||
lhs: lhs.to_ref(),
|
||||
|
@ -417,8 +438,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
|
||||
if cx.tcx.tables().is_method_call(expr.id) {
|
||||
overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue, arg.to_ref(), vec![])
|
||||
overloaded_lvalue(cx,
|
||||
expr,
|
||||
ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue,
|
||||
arg.to_ref(),
|
||||
vec![])
|
||||
} else {
|
||||
ExprKind::Deref { arg: arg.to_ref() }
|
||||
}
|
||||
|
@ -426,8 +451,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
hir::ExprUnary(hir::UnOp::UnNot, ref arg) => {
|
||||
if cx.tcx.tables().is_method_call(expr.id) {
|
||||
overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue, arg.to_ref(), vec![])
|
||||
overloaded_operator(cx,
|
||||
expr,
|
||||
ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue,
|
||||
arg.to_ref(),
|
||||
vec![])
|
||||
} else {
|
||||
ExprKind::Unary {
|
||||
op: UnOp::Not,
|
||||
|
@ -438,14 +467,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
|
||||
if cx.tcx.tables().is_method_call(expr.id) {
|
||||
overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue, arg.to_ref(), vec![])
|
||||
overloaded_operator(cx,
|
||||
expr,
|
||||
ty::MethodCall::expr(expr.id),
|
||||
PassArgs::ByValue,
|
||||
arg.to_ref(),
|
||||
vec![])
|
||||
} else {
|
||||
// FIXME runtime-overflow
|
||||
if let hir::ExprLit(_) = arg.node {
|
||||
ExprKind::Literal {
|
||||
literal: cx.const_eval_literal(expr),
|
||||
}
|
||||
ExprKind::Literal { literal: cx.const_eval_literal(expr) }
|
||||
} else {
|
||||
ExprKind::Unary {
|
||||
op: UnOp::Neg,
|
||||
|
@ -457,56 +488,54 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
hir::ExprStruct(ref qpath, ref fields, ref base) => {
|
||||
match expr_ty.sty {
|
||||
ty::TyAdt(adt, substs) => match adt.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
let field_refs = field_refs(&adt.variants[0], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: base.as_ref().map(|base| {
|
||||
FruInfo {
|
||||
base: base.to_ref(),
|
||||
field_types:
|
||||
cx.tcx.tables().fru_field_types[&expr.id].clone()
|
||||
}
|
||||
})
|
||||
ty::TyAdt(adt, substs) => {
|
||||
match adt.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
let field_refs = field_refs(&adt.variants[0], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: base.as_ref().map(|base| {
|
||||
FruInfo {
|
||||
base: base.to_ref(),
|
||||
field_types: cx.tcx.tables().fru_field_types[&expr.id]
|
||||
.clone(),
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
let def = match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.def,
|
||||
hir::QPath::TypeRelative(..) => Def::Err
|
||||
};
|
||||
match def {
|
||||
Def::Variant(variant_id) => {
|
||||
assert!(base.is_none());
|
||||
AdtKind::Enum => {
|
||||
let def = match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.def,
|
||||
hir::QPath::TypeRelative(..) => Def::Err,
|
||||
};
|
||||
match def {
|
||||
Def::Variant(variant_id) => {
|
||||
assert!(base.is_none());
|
||||
|
||||
let index = adt.variant_index_with_id(variant_id);
|
||||
let field_refs = field_refs(&adt.variants[index], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: index,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: None
|
||||
let index = adt.variant_index_with_id(variant_id);
|
||||
let field_refs = field_refs(&adt.variants[index], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: index,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: None,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_bug!(expr.span, "unexpected def: {:?}", def);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"unexpected def: {:?}",
|
||||
def);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"unexpected type for struct literal: {:?}",
|
||||
expr_ty);
|
||||
span_bug!(expr.span,
|
||||
"unexpected type for struct literal: {:?}",
|
||||
expr_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -516,9 +545,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
let (def_id, substs) = match closure_ty.sty {
|
||||
ty::TyClosure(def_id, substs) => (def_id, substs),
|
||||
_ => {
|
||||
span_bug!(expr.span,
|
||||
"closure expr w/o closure type: {:?}",
|
||||
closure_ty);
|
||||
span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
|
||||
}
|
||||
};
|
||||
let upvars = cx.tcx.with_freevars(expr.id, |freevars| {
|
||||
|
@ -543,69 +570,81 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
ExprKind::InlineAsm {
|
||||
asm: asm,
|
||||
outputs: outputs.to_ref(),
|
||||
inputs: inputs.to_ref()
|
||||
inputs: inputs.to_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
// Now comes the rote stuff:
|
||||
|
||||
hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat {
|
||||
value: v.to_ref(),
|
||||
count: TypedConstVal {
|
||||
ty: cx.tcx.tables().expr_ty(c),
|
||||
span: c.span,
|
||||
value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) {
|
||||
ConstVal::Integral(ConstInt::Usize(u)) => u,
|
||||
other => bug!("constant evaluation of repeat count yielded {:?}", other),
|
||||
hir::ExprRepeat(ref v, ref c) => {
|
||||
ExprKind::Repeat {
|
||||
value: v.to_ref(),
|
||||
count: TypedConstVal {
|
||||
ty: cx.tcx.tables().expr_ty(c),
|
||||
span: c.span,
|
||||
value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) {
|
||||
ConstVal::Integral(ConstInt::Usize(u)) => u,
|
||||
other => bug!("constant evaluation of repeat count yielded {:?}", other),
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
hir::ExprRet(ref v) =>
|
||||
ExprKind::Return { value: v.to_ref() },
|
||||
hir::ExprBreak(label, ref value) =>
|
||||
}
|
||||
hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
|
||||
hir::ExprBreak(label, ref value) => {
|
||||
ExprKind::Break {
|
||||
label: label.map(|label| {
|
||||
cx.tcx.region_maps.node_extent(label.loop_id)
|
||||
}),
|
||||
value: value.to_ref()
|
||||
},
|
||||
hir::ExprAgain(label) =>
|
||||
label: label.map(|label| cx.tcx.region_maps.node_extent(label.loop_id)),
|
||||
value: value.to_ref(),
|
||||
}
|
||||
}
|
||||
hir::ExprAgain(label) => {
|
||||
ExprKind::Continue {
|
||||
label: label.map(|label| {
|
||||
cx.tcx.region_maps.node_extent(label.loop_id)
|
||||
})
|
||||
},
|
||||
hir::ExprMatch(ref discr, ref arms, _) =>
|
||||
ExprKind::Match { discriminant: discr.to_ref(),
|
||||
arms: arms.iter().map(|a| convert_arm(cx, a)).collect() },
|
||||
hir::ExprIf(ref cond, ref then, ref otherwise) =>
|
||||
ExprKind::If { condition: cond.to_ref(),
|
||||
then: block::to_expr_ref(cx, then),
|
||||
otherwise: otherwise.to_ref() },
|
||||
hir::ExprWhile(ref cond, ref body, _) =>
|
||||
ExprKind::Loop { condition: Some(cond.to_ref()),
|
||||
body: block::to_expr_ref(cx, body) },
|
||||
hir::ExprLoop(ref body, _, _) =>
|
||||
ExprKind::Loop { condition: None,
|
||||
body: block::to_expr_ref(cx, body) },
|
||||
label: label.map(|label| cx.tcx.region_maps.node_extent(label.loop_id)),
|
||||
}
|
||||
}
|
||||
hir::ExprMatch(ref discr, ref arms, _) => {
|
||||
ExprKind::Match {
|
||||
discriminant: discr.to_ref(),
|
||||
arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),
|
||||
}
|
||||
}
|
||||
hir::ExprIf(ref cond, ref then, ref otherwise) => {
|
||||
ExprKind::If {
|
||||
condition: cond.to_ref(),
|
||||
then: block::to_expr_ref(cx, then),
|
||||
otherwise: otherwise.to_ref(),
|
||||
}
|
||||
}
|
||||
hir::ExprWhile(ref cond, ref body, _) => {
|
||||
ExprKind::Loop {
|
||||
condition: Some(cond.to_ref()),
|
||||
body: block::to_expr_ref(cx, body),
|
||||
}
|
||||
}
|
||||
hir::ExprLoop(ref body, _, _) => {
|
||||
ExprKind::Loop {
|
||||
condition: None,
|
||||
body: block::to_expr_ref(cx, body),
|
||||
}
|
||||
}
|
||||
hir::ExprField(ref source, name) => {
|
||||
let index = match cx.tcx.tables().expr_ty_adjusted(source).sty {
|
||||
ty::TyAdt(adt_def, _) =>
|
||||
adt_def.variants[0].index_of_field_named(name.node),
|
||||
ref ty =>
|
||||
span_bug!(expr.span, "field of non-ADT: {:?}", ty),
|
||||
ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node),
|
||||
ref ty => span_bug!(expr.span, "field of non-ADT: {:?}", ty),
|
||||
};
|
||||
let index = index.unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"no index found for field `{}`",
|
||||
name.node)
|
||||
});
|
||||
ExprKind::Field { lhs: source.to_ref(), name: Field::new(index) }
|
||||
let index =
|
||||
index.unwrap_or_else(|| {
|
||||
span_bug!(expr.span, "no index found for field `{}`", name.node)
|
||||
});
|
||||
ExprKind::Field {
|
||||
lhs: source.to_ref(),
|
||||
name: Field::new(index),
|
||||
}
|
||||
}
|
||||
hir::ExprTupField(ref source, index) => {
|
||||
ExprKind::Field {
|
||||
lhs: source.to_ref(),
|
||||
name: Field::new(index.node as usize),
|
||||
}
|
||||
}
|
||||
hir::ExprTupField(ref source, index) =>
|
||||
ExprKind::Field { lhs: source.to_ref(),
|
||||
name: Field::new(index.node as usize) },
|
||||
hir::ExprCast(ref source, _) => {
|
||||
// Check to see if this cast is a "coercion cast", where the cast is actually done
|
||||
// using a coercion (or is a no-op).
|
||||
|
@ -616,17 +655,15 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
ExprKind::Cast { source: source.to_ref() }
|
||||
}
|
||||
}
|
||||
hir::ExprType(ref source, _) =>
|
||||
return source.make_mirror(cx),
|
||||
hir::ExprBox(ref value) =>
|
||||
hir::ExprType(ref source, _) => return source.make_mirror(cx),
|
||||
hir::ExprBox(ref value) => {
|
||||
ExprKind::Box {
|
||||
value: value.to_ref(),
|
||||
value_extents: cx.tcx.region_maps.node_extent(value.id)
|
||||
},
|
||||
hir::ExprArray(ref fields) =>
|
||||
ExprKind::Vec { fields: fields.to_ref() },
|
||||
hir::ExprTup(ref fields) =>
|
||||
ExprKind::Tuple { fields: fields.to_ref() },
|
||||
value_extents: cx.tcx.region_maps.node_extent(value.id),
|
||||
}
|
||||
}
|
||||
hir::ExprArray(ref fields) => ExprKind::Vec { fields: fields.to_ref() },
|
||||
hir::ExprTup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() },
|
||||
};
|
||||
|
||||
Expr {
|
||||
|
@ -663,8 +700,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
|||
}
|
||||
}
|
||||
|
||||
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
Arm {
|
||||
patterns: arm.pats.iter().map(|p| Pattern::from_hir(cx.tcx, p)).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
|
@ -676,41 +712,48 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
expr: &'tcx hir::Expr,
|
||||
def: Def)
|
||||
-> ExprKind<'tcx> {
|
||||
let substs = cx.tcx.tables().node_id_item_substs(expr.id)
|
||||
let substs = cx.tcx
|
||||
.tables()
|
||||
.node_id_item_substs(expr.id)
|
||||
.unwrap_or_else(|| cx.tcx.intern_substs(&[]));
|
||||
let def_id = match def {
|
||||
// A regular function, constructor function or a constant.
|
||||
Def::Fn(def_id) | Def::Method(def_id) |
|
||||
Def::Fn(def_id) |
|
||||
Def::Method(def_id) |
|
||||
Def::StructCtor(def_id, CtorKind::Fn) |
|
||||
Def::VariantCtor(def_id, CtorKind::Fn) |
|
||||
Def::Const(def_id) | Def::AssociatedConst(def_id) => def_id,
|
||||
Def::Const(def_id) |
|
||||
Def::AssociatedConst(def_id) => def_id,
|
||||
|
||||
Def::StructCtor(def_id, CtorKind::Const) |
|
||||
Def::VariantCtor(def_id, CtorKind::Const) => {
|
||||
match cx.tcx.tables().node_id_to_type(expr.id).sty {
|
||||
// A unit struct/variant which is used as a value.
|
||||
// We return a completely different ExprKind here to account for this special case.
|
||||
ty::TyAdt(adt_def, substs) => return ExprKind::Adt {
|
||||
adt_def: adt_def,
|
||||
variant_index: adt_def.variant_index_with_id(def_id),
|
||||
substs: substs,
|
||||
fields: vec![],
|
||||
base: None,
|
||||
},
|
||||
ref sty => bug!("unexpected sty: {:?}", sty)
|
||||
ty::TyAdt(adt_def, substs) => {
|
||||
return ExprKind::Adt {
|
||||
adt_def: adt_def,
|
||||
variant_index: adt_def.variant_index_with_id(def_id),
|
||||
substs: substs,
|
||||
fields: vec![],
|
||||
base: None,
|
||||
}
|
||||
}
|
||||
ref sty => bug!("unexpected sty: {:?}", sty),
|
||||
}
|
||||
}
|
||||
|
||||
Def::Static(node_id, _) => return ExprKind::StaticRef {
|
||||
id: node_id,
|
||||
},
|
||||
Def::Static(node_id, _) => return ExprKind::StaticRef { id: node_id },
|
||||
|
||||
Def::Local(..) | Def::Upvar(..) => return convert_var(cx, expr, def),
|
||||
|
||||
_ => span_bug!(expr.span, "def `{:?}` not yet implemented", def),
|
||||
};
|
||||
ExprKind::Literal {
|
||||
literal: Literal::Item { def_id: def_id, substs: substs }
|
||||
literal: Literal::Item {
|
||||
def_id: def_id,
|
||||
substs: substs,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,14 +766,15 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
match def {
|
||||
Def::Local(def_id) => {
|
||||
let node_id = cx.tcx.map.as_local_node_id(def_id).unwrap();
|
||||
ExprKind::VarRef {
|
||||
id: node_id,
|
||||
}
|
||||
ExprKind::VarRef { id: node_id }
|
||||
}
|
||||
|
||||
Def::Upvar(def_id, index, closure_expr_id) => {
|
||||
let id_var = cx.tcx.map.as_local_node_id(def_id).unwrap();
|
||||
debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id);
|
||||
debug!("convert_var(upvar({:?}, {:?}, {:?}))",
|
||||
id_var,
|
||||
index,
|
||||
closure_expr_id);
|
||||
let var_ty = cx.tcx.tables().node_id_to_type(id_var);
|
||||
|
||||
let body_id = match cx.tcx.map.find(closure_expr_id) {
|
||||
|
@ -761,41 +805,45 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
|
||||
let self_expr = match cx.tcx.closure_kind(cx.tcx.map.local_def_id(closure_expr_id)) {
|
||||
ty::ClosureKind::Fn => {
|
||||
let ref_closure_ty =
|
||||
cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
mutbl: hir::MutImmutable });
|
||||
let ref_closure_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: closure_ty,
|
||||
mutbl: hir::MutImmutable,
|
||||
});
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Deref {
|
||||
arg: Expr {
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef
|
||||
}.to_ref()
|
||||
}
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
.to_ref(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ty::ClosureKind::FnMut => {
|
||||
let ref_closure_ty =
|
||||
cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
mutbl: hir::MutMutable });
|
||||
let ref_closure_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: closure_ty,
|
||||
mutbl: hir::MutMutable,
|
||||
});
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Deref {
|
||||
arg: Expr {
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef
|
||||
}.to_ref()
|
||||
}
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
.to_ref(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ty::ClosureKind::FnOnce => {
|
||||
|
@ -823,10 +871,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
let upvar_capture = match cx.tcx.tables().upvar_capture(upvar_id) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"no upvar_capture for {:?}",
|
||||
upvar_id);
|
||||
span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id);
|
||||
}
|
||||
};
|
||||
match upvar_capture {
|
||||
|
@ -834,15 +879,16 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
ty::UpvarCapture::ByRef(borrow) => {
|
||||
ExprKind::Deref {
|
||||
arg: Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: cx.tcx.mk_ref(borrow.region,
|
||||
ty::TypeAndMut {
|
||||
ty: var_ty,
|
||||
mutbl: borrow.kind.to_mutbl_lossy()
|
||||
}),
|
||||
span: expr.span,
|
||||
kind: field_kind,
|
||||
}.to_ref()
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: cx.tcx.mk_ref(borrow.region,
|
||||
ty::TypeAndMut {
|
||||
ty: var_ty,
|
||||
mutbl: borrow.kind.to_mutbl_lossy(),
|
||||
}),
|
||||
span: expr.span,
|
||||
kind: field_kind,
|
||||
}
|
||||
.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -894,30 +940,31 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
// the arguments, unfortunately, do not, so if this is a ByRef
|
||||
// operator, we have to gin up the autorefs (but by value is easy)
|
||||
match pass_args {
|
||||
PassArgs::ByValue => {
|
||||
argrefs.extend(args.iter().map(|arg| arg.to_ref()))
|
||||
}
|
||||
PassArgs::ByValue => argrefs.extend(args.iter().map(|arg| arg.to_ref())),
|
||||
|
||||
PassArgs::ByRef => {
|
||||
let region = cx.tcx.node_scope_region(expr.id);
|
||||
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
|
||||
argrefs.extend(
|
||||
args.iter()
|
||||
.map(|arg| {
|
||||
let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg);
|
||||
let adjusted_ty =
|
||||
cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: arg_ty,
|
||||
mutbl: hir::MutImmutable });
|
||||
Expr {
|
||||
argrefs.extend(args.iter()
|
||||
.map(|arg| {
|
||||
let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg);
|
||||
let adjusted_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: arg_ty,
|
||||
mutbl: hir::MutImmutable,
|
||||
});
|
||||
Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: adjusted_ty,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Borrow { region: region,
|
||||
borrow_kind: BorrowKind::Shared,
|
||||
arg: arg.to_ref() }
|
||||
}.to_ref()
|
||||
}))
|
||||
kind: ExprKind::Borrow {
|
||||
region: region,
|
||||
borrow_kind: BorrowKind::Shared,
|
||||
arg: arg.to_ref(),
|
||||
},
|
||||
}
|
||||
.to_ref()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -981,9 +1028,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
kind: convert_var(cx, closure_expr, freevar.def),
|
||||
};
|
||||
match upvar_capture {
|
||||
ty::UpvarCapture::ByValue => {
|
||||
captured_var.to_ref()
|
||||
}
|
||||
ty::UpvarCapture::ByValue => captured_var.to_ref(),
|
||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||
let borrow_kind = match upvar_borrow.kind {
|
||||
ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
|
||||
|
@ -991,13 +1036,16 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
ty::BorrowKind::MutBorrow => BorrowKind::Mut,
|
||||
};
|
||||
Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: freevar_ty,
|
||||
span: closure_expr.span,
|
||||
kind: ExprKind::Borrow { region: upvar_borrow.region,
|
||||
borrow_kind: borrow_kind,
|
||||
arg: captured_var.to_ref() }
|
||||
}.to_ref()
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: freevar_ty,
|
||||
span: closure_expr.span,
|
||||
kind: ExprKind::Borrow {
|
||||
region: upvar_borrow.region,
|
||||
borrow_kind: borrow_kind,
|
||||
arg: captured_var.to_ref(),
|
||||
},
|
||||
}
|
||||
.to_ref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1005,12 +1053,13 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
/// Converts a list of named fields (i.e. for struct-like struct/enum ADTs) into FieldExprRef.
|
||||
fn field_refs<'tcx>(variant: &'tcx VariantDef,
|
||||
fields: &'tcx [hir::Field])
|
||||
-> Vec<FieldExprRef<'tcx>>
|
||||
{
|
||||
-> Vec<FieldExprRef<'tcx>> {
|
||||
fields.iter()
|
||||
.map(|field| FieldExprRef {
|
||||
name: Field::new(variant.index_of_field_named(field.name.node).unwrap()),
|
||||
expr: field.expr.to_ref(),
|
||||
})
|
||||
.collect()
|
||||
.map(|field| {
|
||||
FieldExprRef {
|
||||
name: Field::new(variant.index_of_field_named(field.name.node).unwrap()),
|
||||
expr: field.expr.to_ref(),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
* This module contains the code to convert from the wacky tcx data
|
||||
* structures into the hair. The `builder` is generally ignorant of
|
||||
* the tcx etc, and instead goes through the `Cx` for most of its
|
||||
* work.
|
||||
*/
|
||||
//! This module contains the code to convert from the wacky tcx data
|
||||
//! structures into the hair. The `builder` is generally ignorant of
|
||||
//! the tcx etc, and instead goes through the `Cx` for most of its
|
||||
//! work.
|
||||
//!
|
||||
|
||||
use hair::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
|
@ -32,19 +31,17 @@ use rustc::hir;
|
|||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cx<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
constness: hir::Constness,
|
||||
|
||||
/// True if this constant/function needs overflow checks.
|
||||
check_overflow: bool
|
||||
check_overflow: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
src: MirSource)
|
||||
-> Cx<'a, 'gcx, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx, 'tcx> {
|
||||
let constness = match src {
|
||||
MirSource::Const(_) |
|
||||
MirSource::Static(..) => hir::Constness::Const,
|
||||
|
@ -52,7 +49,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id));
|
||||
fn_like.map_or(hir::Constness::NotConst, |f| f.constness())
|
||||
}
|
||||
MirSource::Promoted(..) => bug!()
|
||||
MirSource::Promoted(..) => bug!(),
|
||||
};
|
||||
|
||||
let src_node_id = src.item_id();
|
||||
|
@ -70,13 +67,16 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
// Some functions always have overflow checks enabled,
|
||||
// however, they may not get codegen'd, depending on
|
||||
// the settings for the crate they are translated in.
|
||||
let mut check_overflow = attrs.iter().any(|item| {
|
||||
item.check_name("rustc_inherit_overflow_checks")
|
||||
});
|
||||
let mut check_overflow = attrs.iter()
|
||||
.any(|item| item.check_name("rustc_inherit_overflow_checks"));
|
||||
|
||||
// Respect -Z force-overflow-checks=on and -C debug-assertions.
|
||||
check_overflow |= infcx.tcx.sess.opts.debugging_opts.force_overflow_checks
|
||||
.unwrap_or(infcx.tcx.sess.opts.debug_assertions);
|
||||
check_overflow |= infcx.tcx
|
||||
.sess
|
||||
.opts
|
||||
.debugging_opts
|
||||
.force_overflow_checks
|
||||
.unwrap_or(infcx.tcx.sess.opts.debug_assertions);
|
||||
|
||||
// Constants and const fn's always need overflow checks.
|
||||
check_overflow |= constness == hir::Constness::Const;
|
||||
|
@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
tcx: infcx.tcx,
|
||||
infcx: infcx,
|
||||
constness: constness,
|
||||
check_overflow: check_overflow
|
||||
check_overflow: check_overflow,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
|
||||
pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
|
||||
match ConstUsize::new(value, self.tcx.sess.target.uint_type) {
|
||||
Ok(val) => Literal::Value { value: ConstVal::Integral(ConstInt::Usize(val))},
|
||||
Ok(val) => Literal::Value { value: ConstVal::Integral(ConstInt::Usize(val)) },
|
||||
Err(_) => bug!("usize literal out of range for target"),
|
||||
}
|
||||
}
|
||||
|
@ -128,9 +128,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
|
||||
Literal::Value {
|
||||
value: const_eval::eval_const_expr(self.tcx.global_tcx(), e)
|
||||
}
|
||||
Literal::Value { value: const_eval::eval_const_expr(self.tcx.global_tcx(), e) }
|
||||
}
|
||||
|
||||
pub fn trait_method(&mut self,
|
||||
|
@ -145,10 +143,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
if item.kind == ty::AssociatedKind::Method && item.name == method_name {
|
||||
let method_ty = self.tcx.item_type(item.def_id);
|
||||
let method_ty = method_ty.subst(self.tcx, substs);
|
||||
return (method_ty, Literal::Item {
|
||||
def_id: item.def_id,
|
||||
substs: substs,
|
||||
});
|
||||
return (method_ty,
|
||||
Literal::Item {
|
||||
def_id: item.def_id,
|
||||
substs: substs,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +167,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
|||
pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
let ty = self.tcx.lift_to_global(&ty).unwrap_or_else(|| {
|
||||
bug!("MIR: Cx::needs_drop({}) got \
|
||||
type with inference types/regions", ty);
|
||||
type with inference types/regions",
|
||||
ty);
|
||||
});
|
||||
self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub trait ToRef {
|
|||
fn to_ref(self) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> ToRef for &'tcx hir::Expr {
|
||||
impl<'a, 'tcx: 'a> ToRef for &'tcx hir::Expr {
|
||||
type Output = ExprRef<'tcx>;
|
||||
|
||||
fn to_ref(self) -> ExprRef<'tcx> {
|
||||
|
@ -26,7 +26,7 @@ impl<'a,'tcx:'a> ToRef for &'tcx hir::Expr {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> ToRef for &'tcx P<hir::Expr> {
|
||||
impl<'a, 'tcx: 'a> ToRef for &'tcx P<hir::Expr> {
|
||||
type Output = ExprRef<'tcx>;
|
||||
|
||||
fn to_ref(self) -> ExprRef<'tcx> {
|
||||
|
@ -34,7 +34,7 @@ impl<'a,'tcx:'a> ToRef for &'tcx P<hir::Expr> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> ToRef for Expr<'tcx> {
|
||||
impl<'a, 'tcx: 'a> ToRef for Expr<'tcx> {
|
||||
type Output = ExprRef<'tcx>;
|
||||
|
||||
fn to_ref(self) -> ExprRef<'tcx> {
|
||||
|
@ -42,8 +42,8 @@ impl<'a,'tcx:'a> ToRef for Expr<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option<T>
|
||||
where &'tcx T: ToRef<Output=U>
|
||||
impl<'a, 'tcx: 'a, T, U> ToRef for &'tcx Option<T>
|
||||
where &'tcx T: ToRef<Output = U>
|
||||
{
|
||||
type Output = Option<U>;
|
||||
|
||||
|
@ -52,8 +52,8 @@ impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option<T>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a,T,U> ToRef for &'tcx Vec<T>
|
||||
where &'tcx T: ToRef<Output=U>
|
||||
impl<'a, 'tcx: 'a, T, U> ToRef for &'tcx Vec<T>
|
||||
where &'tcx T: ToRef<Output = U>
|
||||
{
|
||||
type Output = Vec<U>;
|
||||
|
||||
|
@ -62,8 +62,8 @@ impl<'a,'tcx:'a,T,U> ToRef for &'tcx Vec<T>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a,T,U> ToRef for &'tcx P<[T]>
|
||||
where &'tcx T: ToRef<Output=U>
|
||||
impl<'a, 'tcx: 'a, T, U> ToRef for &'tcx P<[T]>
|
||||
where &'tcx T: ToRef<Output = U>
|
||||
{
|
||||
type Output = Vec<U>;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
//! future.
|
||||
|
||||
use def_use::DefUseAnalysis;
|
||||
use rustc::mir::{Constant, Local, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
|
||||
use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
|
||||
use rustc::mir::transform::{MirPass, MirSource, Pass};
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::ty::TyCtxt;
|
||||
|
@ -122,7 +122,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
|
|||
local == dest_local => {
|
||||
let maybe_action = match *operand {
|
||||
Operand::Consume(ref src_lvalue) => {
|
||||
Action::local_copy(&def_use_analysis, src_lvalue)
|
||||
Action::local_copy(&mir, &def_use_analysis, src_lvalue)
|
||||
}
|
||||
Operand::Constant(ref src_constant) => {
|
||||
Action::constant(src_constant)
|
||||
|
@ -159,7 +159,7 @@ enum Action<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Action<'tcx> {
|
||||
fn local_copy(def_use_analysis: &DefUseAnalysis, src_lvalue: &Lvalue<'tcx>)
|
||||
fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_lvalue: &Lvalue<'tcx>)
|
||||
-> Option<Action<'tcx>> {
|
||||
// The source must be a local.
|
||||
let src_local = if let Lvalue::Local(local) = *src_lvalue {
|
||||
|
@ -195,7 +195,9 @@ impl<'tcx> Action<'tcx> {
|
|||
// SRC = X;
|
||||
// USE(SRC);
|
||||
let src_def_count = src_use_info.def_count_not_including_drop();
|
||||
if src_def_count != 1 {
|
||||
// allow function arguments to be propagated
|
||||
if src_def_count > 1 ||
|
||||
(src_def_count == 0 && mir.local_kind(src_local) != LocalKind::Arg) {
|
||||
debug!(" Can't copy-propagate local: {} defs of src",
|
||||
src_use_info.def_count_not_including_drop());
|
||||
return None
|
||||
|
|
|
@ -48,7 +48,7 @@ use rustc::session::config::CrateType::CrateTypeExecutable;
|
|||
use rustc::ty::{self, TyCtxt};
|
||||
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
|
||||
|
@ -832,7 +832,7 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
|
|||
},
|
||||
};
|
||||
|
||||
if let Err(e) = fs::create_dir_all(&root_path) {
|
||||
if let Err(e) = rustc::util::fs::create_dir_racy(&root_path) {
|
||||
tcx.sess.err(&format!("Could not create directory {}: {}",
|
||||
root_path.display(),
|
||||
e));
|
||||
|
|
|
@ -971,7 +971,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
|||
let mut name = String::with_capacity(prefix.len() + 6);
|
||||
name.push_str(prefix);
|
||||
name.push_str(".");
|
||||
base_n::push_str(idx as u64, base_n::MAX_BASE, &mut name);
|
||||
base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name);
|
||||
name
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1763,6 +1763,10 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
|||
|
||||
let var_name = CString::new(var_name).unwrap();
|
||||
let linkage_name = CString::new(linkage_name).unwrap();
|
||||
|
||||
let ty = cx.tcx().item_type(node_def_id);
|
||||
let global_align = type_of::align_of(cx, ty);
|
||||
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
|
||||
var_scope,
|
||||
|
@ -1773,7 +1777,9 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
|||
type_metadata,
|
||||
is_local_to_unit,
|
||||
global,
|
||||
ptr::null_mut());
|
||||
ptr::null_mut(),
|
||||
global_align as u64,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -462,6 +462,7 @@ pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
LocalVariable |
|
||||
CapturedVariable => (0, DW_TAG_auto_variable)
|
||||
};
|
||||
let align = ::type_of::align_of(cx, variable_type);
|
||||
|
||||
let name = CString::new(variable_name.as_str().as_bytes()).unwrap();
|
||||
match (variable_access, &[][..]) {
|
||||
|
@ -478,7 +479,9 @@ pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
type_metadata,
|
||||
cx.sess().opts.optimize != config::OptLevel::No,
|
||||
DIFlags::FlagZero,
|
||||
argument_index)
|
||||
argument_index,
|
||||
align as u64,
|
||||
)
|
||||
};
|
||||
source_loc::set_debug_location(cx, None,
|
||||
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
|
||||
|
|
|
@ -1468,6 +1468,13 @@ impl<'a> Item<'a> {
|
|||
return None;
|
||||
}
|
||||
} else {
|
||||
// Macros from other libraries get special filenames which we can
|
||||
// safely ignore.
|
||||
if self.item.source.filename.starts_with("<") &&
|
||||
self.item.source.filename.ends_with("macros>") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (krate, src_root) = match cache.extern_locations.get(&self.item.def_id.krate) {
|
||||
Some(&(ref name, ref src, Local)) => (name, src),
|
||||
Some(&(ref name, ref src, Remote(ref s))) => {
|
||||
|
|
|
@ -52,13 +52,15 @@
|
|||
font-family: 'Source Code Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff');
|
||||
/* Avoid using locally installed font because bad versions are in circulation:
|
||||
* see https://github.com/rust-lang/rust/issues/24355 */
|
||||
src: url("SourceCodePro-Regular.woff") format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Code Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Code Pro Semibold'), url("SourceCodePro-Semibold.woff") format('woff');
|
||||
src: url("SourceCodePro-Semibold.woff") format('woff');
|
||||
}
|
||||
|
||||
* {
|
||||
|
|
|
@ -54,6 +54,9 @@ extern crate serialize as rustc_serialize; // used by deriving
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::default::Default;
|
||||
use std::env;
|
||||
use std::fmt::Display;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::sync::mpsc::channel;
|
||||
|
@ -183,7 +186,7 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
let matches = match getopts::getopts(&args[1..], &all_groups) {
|
||||
Ok(m) => m,
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
print_error(err);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
@ -211,11 +214,11 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
}
|
||||
|
||||
if matches.free.is_empty() {
|
||||
println!("expected an input file to act on");
|
||||
print_error("missing file operand");
|
||||
return 1;
|
||||
}
|
||||
if matches.free.len() > 1 {
|
||||
println!("only one input file may be specified");
|
||||
print_error("too many file operands");
|
||||
return 1;
|
||||
}
|
||||
let input = &matches.free[0];
|
||||
|
@ -227,7 +230,7 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
let externs = match parse_externs(&matches) {
|
||||
Ok(ex) => ex,
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
print_error(err);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
@ -247,14 +250,16 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
|
||||
if let Some(ref p) = css_file_extension {
|
||||
if !p.is_file() {
|
||||
println!("{}", "--extend-css option must take a css file as input");
|
||||
writeln!(
|
||||
&mut io::stderr(),
|
||||
"rustdoc: option --extend-css argument must be a file."
|
||||
).unwrap();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
let external_html = match ExternalHtml::load(
|
||||
&matches.opt_strs("html-in-header"),
|
||||
&matches.opt_strs("html-before-content"),
|
||||
&matches.opt_strs("html-in-header"), &matches.opt_strs("html-before-content"),
|
||||
&matches.opt_strs("html-after-content")) {
|
||||
Some(eh) => eh,
|
||||
None => return 3
|
||||
|
@ -291,17 +296,26 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
0
|
||||
}
|
||||
Some(s) => {
|
||||
println!("unknown output format: {}", s);
|
||||
print_error(format!("unknown output format: {}", s));
|
||||
1
|
||||
}
|
||||
}
|
||||
});
|
||||
res.unwrap_or_else(|s| {
|
||||
println!("input error: {}", s);
|
||||
print_error(format!("input error: {}", s));
|
||||
1
|
||||
})
|
||||
}
|
||||
|
||||
/// Prints an uniformised error message on the standard error output
|
||||
fn print_error<T>(error_message: T) where T: Display {
|
||||
writeln!(
|
||||
&mut io::stderr(),
|
||||
"rustdoc: {}\nTry 'rustdoc --help' for more information.",
|
||||
error_message
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
/// Looks inside the command line arguments to extract the relevant input format
|
||||
/// and files and then generates the necessary rustdoc output for formatting.
|
||||
fn acquire_input<R, F>(input: &str,
|
||||
|
|
|
@ -71,7 +71,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
|
|||
let mut out = match File::create(&output) {
|
||||
Err(e) => {
|
||||
let _ = writeln!(&mut io::stderr(),
|
||||
"error opening `{}` for writing: {}",
|
||||
"rustdoc: {}: {}",
|
||||
output.display(), e);
|
||||
return 4;
|
||||
}
|
||||
|
@ -80,8 +80,10 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
|
|||
|
||||
let (metadata, text) = extract_leading_metadata(&input_str);
|
||||
if metadata.is_empty() {
|
||||
let _ = writeln!(&mut io::stderr(),
|
||||
"invalid markdown file: expecting initial line with `% ...TITLE...`");
|
||||
let _ = writeln!(
|
||||
&mut io::stderr(),
|
||||
"rustdoc: invalid markdown file: expecting initial line with `% ...TITLE...`"
|
||||
);
|
||||
return 5;
|
||||
}
|
||||
let title = metadata[0];
|
||||
|
@ -132,7 +134,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
|
|||
match err {
|
||||
Err(e) => {
|
||||
let _ = writeln!(&mut io::stderr(),
|
||||
"error writing to `{}`: {}",
|
||||
"rustdoc: cannot write to `{}`: {}",
|
||||
output.display(), e);
|
||||
6
|
||||
}
|
||||
|
|
|
@ -499,6 +499,19 @@ impl UdpSocket {
|
|||
/// This will retrieve the stored error in the underlying socket, clearing
|
||||
/// the field in the process. This can be useful for checking errors between
|
||||
/// calls.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// match socket.take_error() {
|
||||
/// Ok(Some(error)) => println!("UdpSocket error: {:?}", error),
|
||||
/// Ok(None) => println!("No error"),
|
||||
/// Err(error) => println!("UdpSocket.take_error failed: {:?}", error),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0.take_error()
|
||||
|
@ -507,6 +520,15 @@ impl UdpSocket {
|
|||
/// Connects this UDP socket to a remote address, allowing the `send` and
|
||||
/// `recv` syscalls to be used to send data and also applies filters to only
|
||||
/// receive data from the specified address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// ```
|
||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||
super::each_addr(addr, |addr| self.0.connect(addr))
|
||||
|
@ -514,8 +536,20 @@ impl UdpSocket {
|
|||
|
||||
/// Sends data on the socket to the remote address to which it is connected.
|
||||
///
|
||||
/// The `connect` method will connect this socket to a remote address. This
|
||||
/// The [`connect()`] method will connect this socket to a remote address. This
|
||||
/// method will fail if the socket is not connected.
|
||||
///
|
||||
/// [`connect()`]: #method.connect
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// socket.send(&[0, 1, 2]).expect("couldn't send message");
|
||||
/// ```
|
||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.send(buf)
|
||||
|
@ -526,6 +560,20 @@ impl UdpSocket {
|
|||
///
|
||||
/// The `connect` method will connect this socket to a remote address. This
|
||||
/// method will fail if the socket is not connected.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// let mut buf = [0; 10];
|
||||
/// match socket.recv(&mut buf) {
|
||||
/// Ok(received) => println!("received {} bytes", received),
|
||||
/// Err(e) => println!("recv function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.recv(buf)
|
||||
|
@ -535,6 +583,15 @@ impl UdpSocket {
|
|||
///
|
||||
/// On Unix this corresponds to calling fcntl, and on Windows this
|
||||
/// corresponds to calling ioctlsocket.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.set_nonblocking(true).expect("set_nonblocking call failed");
|
||||
/// ```
|
||||
#[stable(feature = "net2_mutators", since = "1.9.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
|
|
|
@ -454,10 +454,16 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
|
|||
}
|
||||
|
||||
/// Creates a new asynchronous channel, returning the sender/receiver halves.
|
||||
///
|
||||
/// All data sent on the sender will become available on the receiver, and no
|
||||
/// send will block the calling thread (this channel has an "infinite buffer").
|
||||
///
|
||||
/// If the [`Receiver`] is disconnected while trying to [`send()`] with the
|
||||
/// [`Sender`], the [`send()`] method will return an error.
|
||||
///
|
||||
/// [`send()`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
|
||||
/// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
|
||||
/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -487,18 +493,23 @@ pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
|
|||
|
||||
/// Creates a new synchronous, bounded channel.
|
||||
///
|
||||
/// Like asynchronous channels, the `Receiver` will block until a message
|
||||
/// Like asynchronous channels, the [`Receiver`] will block until a message
|
||||
/// becomes available. These channels differ greatly in the semantics of the
|
||||
/// sender from asynchronous channels, however.
|
||||
///
|
||||
/// This channel has an internal buffer on which messages will be queued. `bound`
|
||||
/// specifies the buffer size. When the internal buffer becomes full, future sends
|
||||
/// will *block* waiting for the buffer to open up. Note that a buffer size of 0
|
||||
/// is valid, in which case this becomes "rendezvous channel" where each send will
|
||||
/// not return until a recv is paired with it.
|
||||
/// This channel has an internal buffer on which messages will be queued.
|
||||
/// `bound` specifies the buffer size. When the internal buffer becomes full,
|
||||
/// future sends will *block* waiting for the buffer to open up. Note that a
|
||||
/// buffer size of 0 is valid, in which case this becomes "rendezvous channel"
|
||||
/// where each [`send()`] will not return until a recv is paired with it.
|
||||
///
|
||||
/// As with asynchronous channels, all senders will panic in `send` if the
|
||||
/// `Receiver` has been destroyed.
|
||||
/// Like asynchronous channels, if the [`Receiver`] is disconnected while
|
||||
/// trying to [`send()`] with the [`SyncSender`], the [`send()`] method will
|
||||
/// return an error.
|
||||
///
|
||||
/// [`send()`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
|
||||
/// [`SyncSender`]: ../../../std/sync/mpsc/struct.SyncSender.html
|
||||
/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
@ -301,6 +301,7 @@ pub enum ColorConfig {
|
|||
|
||||
pub struct TestOpts {
|
||||
pub filter: Option<String>,
|
||||
pub filter_exact: bool,
|
||||
pub run_ignored: bool,
|
||||
pub run_tests: bool,
|
||||
pub bench_benchmarks: bool,
|
||||
|
@ -317,6 +318,7 @@ impl TestOpts {
|
|||
fn new() -> TestOpts {
|
||||
TestOpts {
|
||||
filter: None,
|
||||
filter_exact: false,
|
||||
run_ignored: false,
|
||||
run_tests: false,
|
||||
bench_benchmarks: false,
|
||||
|
@ -348,6 +350,7 @@ fn optgroups() -> Vec<getopts::OptGroup> {
|
|||
getopts::optmulti("", "skip", "Skip tests whose names contain FILTER (this flag can \
|
||||
be used multiple times)","FILTER"),
|
||||
getopts::optflag("q", "quiet", "Display one character per test instead of one line"),
|
||||
getopts::optflag("", "exact", "Exactly match filters rather than by substring"),
|
||||
getopts::optopt("", "color", "Configure coloring of output:
|
||||
auto = colorize if stdout is a tty and tests are run on serially (default);
|
||||
always = always colorize output;
|
||||
|
@ -407,6 +410,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
|
|||
|
||||
let run_ignored = matches.opt_present("ignored");
|
||||
let quiet = matches.opt_present("quiet");
|
||||
let exact = matches.opt_present("exact");
|
||||
|
||||
let logfile = matches.opt_str("logfile");
|
||||
let logfile = logfile.map(|s| PathBuf::from(&s));
|
||||
|
@ -448,6 +452,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
|
|||
|
||||
let test_opts = TestOpts {
|
||||
filter: filter,
|
||||
filter_exact: exact,
|
||||
run_ignored: run_ignored,
|
||||
run_tests: run_tests,
|
||||
bench_benchmarks: bench_benchmarks,
|
||||
|
@ -1118,14 +1123,26 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
|
|||
None => filtered,
|
||||
Some(ref filter) => {
|
||||
filtered.into_iter()
|
||||
.filter(|test| test.desc.name.as_slice().contains(&filter[..]))
|
||||
.filter(|test| {
|
||||
if opts.filter_exact {
|
||||
test.desc.name.as_slice() == &filter[..]
|
||||
} else {
|
||||
test.desc.name.as_slice().contains(&filter[..])
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
|
||||
// Skip tests that match any of the skip filters
|
||||
filtered = filtered.into_iter()
|
||||
.filter(|t| !opts.skip.iter().any(|sf| t.desc.name.as_slice().contains(&sf[..])))
|
||||
.filter(|t| !opts.skip.iter().any(|sf| {
|
||||
if opts.filter_exact {
|
||||
t.desc.name.as_slice() == &sf[..]
|
||||
} else {
|
||||
t.desc.name.as_slice().contains(&sf[..])
|
||||
}
|
||||
}))
|
||||
.collect();
|
||||
|
||||
// Maybe pull out the ignored test and unignore them
|
||||
|
@ -1654,6 +1671,77 @@ mod tests {
|
|||
assert!(!filtered[0].desc.ignore);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn exact_filter_match() {
|
||||
fn tests() -> Vec<TestDescAndFn> {
|
||||
vec!["base",
|
||||
"base::test",
|
||||
"base::test1",
|
||||
"base::test2",
|
||||
].into_iter()
|
||||
.map(|name| TestDescAndFn {
|
||||
desc: TestDesc {
|
||||
name: StaticTestName(name),
|
||||
ignore: false,
|
||||
should_panic: ShouldPanic::No,
|
||||
},
|
||||
testfn: DynTestFn(Box::new(move |()| {}))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
let substr = filter_tests(&TestOpts {
|
||||
filter: Some("base".into()),
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(substr.len(), 4);
|
||||
|
||||
let substr = filter_tests(&TestOpts {
|
||||
filter: Some("bas".into()),
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(substr.len(), 4);
|
||||
|
||||
let substr = filter_tests(&TestOpts {
|
||||
filter: Some("::test".into()),
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(substr.len(), 3);
|
||||
|
||||
let substr = filter_tests(&TestOpts {
|
||||
filter: Some("base::test".into()),
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(substr.len(), 3);
|
||||
|
||||
let exact = filter_tests(&TestOpts {
|
||||
filter: Some("base".into()),
|
||||
filter_exact: true, ..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(exact.len(), 1);
|
||||
|
||||
let exact = filter_tests(&TestOpts {
|
||||
filter: Some("bas".into()),
|
||||
filter_exact: true,
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(exact.len(), 0);
|
||||
|
||||
let exact = filter_tests(&TestOpts {
|
||||
filter: Some("::test".into()),
|
||||
filter_exact: true,
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(exact.len(), 0);
|
||||
|
||||
let exact = filter_tests(&TestOpts {
|
||||
filter: Some("base::test".into()),
|
||||
filter_exact: true,
|
||||
..TestOpts::new()
|
||||
}, tests());
|
||||
assert_eq!(exact.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn sort_tests() {
|
||||
let mut opts = TestOpts::new();
|
||||
|
|
|
@ -552,8 +552,13 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateBasicType(
|
|||
uint64_t AlignInBits,
|
||||
unsigned Encoding) {
|
||||
return wrap(Builder->createBasicType(
|
||||
Name, SizeInBits,
|
||||
AlignInBits, Encoding));
|
||||
Name,
|
||||
SizeInBits,
|
||||
#if LLVM_VERSION_LE(3, 9)
|
||||
AlignInBits,
|
||||
#endif
|
||||
Encoding
|
||||
));
|
||||
}
|
||||
|
||||
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
|
||||
|
@ -645,8 +650,11 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
|||
LLVMRustMetadataRef Ty,
|
||||
bool isLocalToUnit,
|
||||
LLVMValueRef Val,
|
||||
LLVMRustMetadataRef Decl = NULL) {
|
||||
return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
|
||||
LLVMRustMetadataRef Decl = NULL,
|
||||
uint64_t AlignInBits = 0)
|
||||
{
|
||||
return wrap(Builder->createGlobalVariable(
|
||||
unwrapDI<DIDescriptor>(Context),
|
||||
Name,
|
||||
LinkageName,
|
||||
unwrapDI<DIFile>(File),
|
||||
|
@ -654,7 +662,11 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
|||
unwrapDI<DIType>(Ty),
|
||||
isLocalToUnit,
|
||||
cast<Constant>(unwrap(Val)),
|
||||
unwrapDIptr<MDNode>(Decl)));
|
||||
unwrapDIptr<MDNode>(Decl)
|
||||
#if LLVM_VERSION_GE(4, 0)
|
||||
, AlignInBits
|
||||
#endif
|
||||
));
|
||||
}
|
||||
|
||||
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
|
||||
|
@ -667,14 +679,23 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
|
|||
LLVMRustMetadataRef Ty,
|
||||
bool AlwaysPreserve,
|
||||
LLVMRustDIFlags Flags,
|
||||
unsigned ArgNo) {
|
||||
unsigned ArgNo,
|
||||
uint64_t AlignInBits)
|
||||
{
|
||||
#if LLVM_VERSION_GE(3, 8)
|
||||
if (Tag == 0x100) { // DW_TAG_auto_variable
|
||||
return wrap(Builder->createAutoVariable(
|
||||
unwrapDI<DIDescriptor>(Scope), Name,
|
||||
unwrapDI<DIDescriptor>(Scope),
|
||||
Name,
|
||||
unwrapDI<DIFile>(File),
|
||||
LineNo,
|
||||
unwrapDI<DIType>(Ty), AlwaysPreserve, from_rust(Flags)));
|
||||
unwrapDI<DIType>(Ty),
|
||||
AlwaysPreserve,
|
||||
from_rust(Flags)
|
||||
#if LLVM_VERSION_GE(4,0)
|
||||
, AlignInBits
|
||||
#endif
|
||||
));
|
||||
} else {
|
||||
return wrap(Builder->createParameterVariable(
|
||||
unwrapDI<DIDescriptor>(Scope), Name, ArgNo,
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
// 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.
|
||||
|
||||
|
||||
// This test case tests the incremental compilation hash (ICH) implementation
|
||||
// for closure expression.
|
||||
|
||||
// The general pattern followed here is: Change one thing between rev1 and rev2
|
||||
// and make sure that the hash has changed, then change nothing between rev2 and
|
||||
// rev3 and make sure that the hash has not changed.
|
||||
|
||||
// must-compile-successfully
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
|
||||
// Change closure body ---------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_closure_body() {
|
||||
let _ = || 1u32;
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_closure_body() {
|
||||
let _ = || 3u32;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add parameter ---------------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn add_parameter() {
|
||||
let x = 0u32;
|
||||
let _ = || x + 1;
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn add_parameter() {
|
||||
let x = 0u32;
|
||||
let _ = |x: u32| x + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change parameter pattern ----------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_parameter_pattern() {
|
||||
let _ = |x: &u32| x;
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_parameter_pattern() {
|
||||
let _ = |&x: &u32| x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add `move` to closure -------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn add_move() {
|
||||
let _ = || 1;
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn add_move() {
|
||||
let _ = move || 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add type ascription to parameter --------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn add_type_ascription_to_parameter() {
|
||||
let closure = |x| x + 1u32;
|
||||
let _: u32 = closure(1);
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn add_type_ascription_to_parameter() {
|
||||
let closure = |x: u32| x + 1u32;
|
||||
let _: u32 = closure(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change parameter type -------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_parameter_type() {
|
||||
let closure = |x: u32| (x as u64) + 1;
|
||||
let _ = closure(1);
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_parameter_type() {
|
||||
let closure = |x: u16| (x as u64) + 1;
|
||||
let _ = closure(1);
|
||||
}
|
|
@ -0,0 +1,387 @@
|
|||
// 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.
|
||||
|
||||
|
||||
// This test case tests the incremental compilation hash (ICH) implementation
|
||||
// for struct constructor expressions.
|
||||
|
||||
// The general pattern followed here is: Change one thing between rev1 and rev2
|
||||
// and make sure that the hash has changed, then change nothing between rev2 and
|
||||
// rev3 and make sure that the hash has not changed.
|
||||
|
||||
// must-compile-successfully
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
|
||||
enum Enum {
|
||||
Struct {
|
||||
x: i32,
|
||||
y: i64,
|
||||
z: i16,
|
||||
},
|
||||
Tuple(i32, i64, i16)
|
||||
}
|
||||
|
||||
// Change field value (struct-like) -----------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_field_value_struct_like() -> Enum {
|
||||
Enum::Struct {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_field_value_struct_like() -> Enum {
|
||||
Enum::Struct {
|
||||
x: 0,
|
||||
y: 2,
|
||||
z: 2,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change field order (struct-like) -----------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_field_order_struct_like() -> Enum {
|
||||
Enum::Struct {
|
||||
x: 3,
|
||||
y: 4,
|
||||
z: 5,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_field_order_struct_like() -> Enum {
|
||||
Enum::Struct {
|
||||
y: 4,
|
||||
x: 3,
|
||||
z: 5,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum Enum2 {
|
||||
Struct {
|
||||
x: i8,
|
||||
y: i8,
|
||||
z: i8,
|
||||
},
|
||||
Struct2 {
|
||||
x: i8,
|
||||
y: i8,
|
||||
z: i8,
|
||||
},
|
||||
Tuple(u16, u16, u16),
|
||||
Tuple2(u64, u64, u64),
|
||||
}
|
||||
|
||||
// Change constructor path (struct-like) ------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_constructor_path_struct_like() {
|
||||
let _ = Enum::Struct {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_constructor_path_struct_like() {
|
||||
let _ = Enum2::Struct {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change variant (regular struct) ------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_constructor_variant_struct_like() {
|
||||
let _ = Enum2::Struct {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_constructor_variant_struct_like() {
|
||||
let _ = Enum2::Struct2 {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Change constructor path indirectly (struct-like) -------------------------
|
||||
mod change_constructor_path_indirectly_struct_like {
|
||||
#[cfg(cfail1)]
|
||||
use super::Enum as TheEnum;
|
||||
#[cfg(not(cfail1))]
|
||||
use super::Enum2 as TheEnum;
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> TheEnum {
|
||||
TheEnum::Struct {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Change constructor variant indirectly (struct-like) ---------------------------
|
||||
mod change_constructor_variant_indirectly_struct_like {
|
||||
use super::Enum2;
|
||||
#[cfg(cfail1)]
|
||||
use super::Enum2::Struct as Variant;
|
||||
#[cfg(not(cfail1))]
|
||||
use super::Enum2::Struct2 as Variant;
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> Enum2 {
|
||||
Variant {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Change field value (tuple-like) -------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_field_value_tuple_like() -> Enum {
|
||||
Enum::Tuple(0, 1, 2)
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_field_value_tuple_like() -> Enum {
|
||||
Enum::Tuple(0, 1, 3)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change constructor path (tuple-like) --------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_constructor_path_tuple_like() {
|
||||
let _ = Enum::Tuple(0, 1, 2);
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_constructor_path_tuple_like() {
|
||||
let _ = Enum2::Tuple(0, 1, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change constructor variant (tuple-like) --------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_constructor_variant_tuple_like() {
|
||||
let _ = Enum2::Tuple(0, 1, 2);
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_constructor_variant_tuple_like() {
|
||||
let _ = Enum2::Tuple2(0, 1, 2);
|
||||
}
|
||||
|
||||
|
||||
// Change constructor path indirectly (tuple-like) ---------------------------
|
||||
mod change_constructor_path_indirectly_tuple_like {
|
||||
#[cfg(cfail1)]
|
||||
use super::Enum as TheEnum;
|
||||
#[cfg(not(cfail1))]
|
||||
use super::Enum2 as TheEnum;
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> TheEnum {
|
||||
TheEnum::Tuple(0, 1, 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change constructor variant indirectly (tuple-like) ---------------------------
|
||||
mod change_constructor_variant_indirectly_tuple_like {
|
||||
use super::Enum2;
|
||||
#[cfg(cfail1)]
|
||||
use super::Enum2::Tuple as Variant;
|
||||
#[cfg(not(cfail1))]
|
||||
use super::Enum2::Tuple2 as Variant;
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> Enum2 {
|
||||
Variant(0, 1, 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum Clike {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
}
|
||||
|
||||
enum Clike2 {
|
||||
B,
|
||||
C,
|
||||
D
|
||||
}
|
||||
|
||||
// Change constructor path (C-like) --------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_constructor_path_c_like() {
|
||||
let _ = Clike::B;
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_constructor_path_c_like() {
|
||||
let _ = Clike2::B;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change constructor variant (C-like) --------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_constructor_variant_c_like() {
|
||||
let _ = Clike::A;
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_constructor_variant_c_like() {
|
||||
let _ = Clike::C;
|
||||
}
|
||||
|
||||
|
||||
// Change constructor path indirectly (C-like) ---------------------------
|
||||
mod change_constructor_path_indirectly_c_like {
|
||||
#[cfg(cfail1)]
|
||||
use super::Clike as TheEnum;
|
||||
#[cfg(not(cfail1))]
|
||||
use super::Clike2 as TheEnum;
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> TheEnum {
|
||||
TheEnum::B
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change constructor variant indirectly (C-like) ---------------------------
|
||||
mod change_constructor_variant_indirectly_c_like {
|
||||
use super::Clike;
|
||||
#[cfg(cfail1)]
|
||||
use super::Clike::A as Variant;
|
||||
#[cfg(not(cfail1))]
|
||||
use super::Clike::B as Variant;
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> Clike {
|
||||
Variant
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
// Case 1: The function body is not exported to metadata. If the body changes,
|
||||
// the hash of the HirBody node should change, but not the hash of
|
||||
// either the Hir or the Metadata node.
|
||||
|
||||
#[cfg(cfail1)]
|
||||
pub fn body_not_exported_to_metadata() -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
pub fn body_not_exported_to_metadata() -> u32 {
|
||||
2
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Case 2: The function body *is* exported to metadata because the function is
|
||||
// marked as #[inline]. Only the hash of the Hir depnode should be
|
||||
// unaffected by a change to the body.
|
||||
|
||||
#[cfg(cfail1)]
|
||||
#[inline]
|
||||
pub fn body_exported_to_metadata_because_of_inline() -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
#[inline]
|
||||
pub fn body_exported_to_metadata_because_of_inline() -> u32 {
|
||||
2
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Case 2: The function body *is* exported to metadata because the function is
|
||||
// generic. Only the hash of the Hir depnode should be
|
||||
// unaffected by a change to the body.
|
||||
|
||||
#[cfg(cfail1)]
|
||||
#[inline]
|
||||
pub fn body_exported_to_metadata_because_of_generic() -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
#[inline]
|
||||
pub fn body_exported_to_metadata_because_of_generic() -> u32 {
|
||||
2
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// 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.
|
||||
|
||||
|
||||
// This test case tests the incremental compilation hash (ICH) implementation
|
||||
// for closure expression.
|
||||
|
||||
// The general pattern followed here is: Change one thing between rev1 and rev2
|
||||
// and make sure that the hash has changed, then change nothing between rev2 and
|
||||
// rev3 and make sure that the hash has not changed.
|
||||
|
||||
// must-compile-successfully
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph
|
||||
|
||||
#![allow(warnings)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type="rlib"]
|
||||
#![feature(inclusive_range_syntax)]
|
||||
|
||||
// Change simple index ---------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_simple_index(slice: &[u32]) -> u32 {
|
||||
slice[3]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_simple_index(slice: &[u32]) -> u32 {
|
||||
slice[4]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change lower bound ----------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_lower_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..5]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_lower_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[2..5]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change upper bound ----------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_upper_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..5]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_upper_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..7]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add lower bound -------------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn add_lower_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[..4]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn add_lower_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..4]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add upper bound -------------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn add_upper_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn add_upper_bound(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..7]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Change mutability -----------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn change_mutability(slice: &mut [u32]) -> u32 {
|
||||
(&mut slice[3..5])[0]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn change_mutability(slice: &mut [u32]) -> u32 {
|
||||
(&slice[3..5])[0]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Exclusive to inclusive range ------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
|
||||
&slice[3..7]
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
|
||||
&slice[3...7]
|
||||
}
|
|
@ -202,6 +202,12 @@ mod change_constructor_path_indirectly_regular_struct {
|
|||
#[cfg(not(cfail1))]
|
||||
use super::RegularStruct2 as Struct;
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> Struct {
|
||||
Struct {
|
||||
x: 0,
|
||||
|
@ -262,6 +268,12 @@ mod change_constructor_path_indirectly_tuple_struct {
|
|||
#[cfg(not(cfail1))]
|
||||
use super::TupleStruct2 as Struct;
|
||||
|
||||
#[rustc_dirty(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_dirty(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
fn function() -> Struct {
|
||||
Struct(0, 1, 2)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <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 test(x: u32) -> u32 {
|
||||
let y = x;
|
||||
y
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
||||
// END RUST SOURCE
|
||||
// START rustc.node4.CopyPropagation.before.mir
|
||||
// bb0: {
|
||||
// _2 = _1;
|
||||
// _4 = _2;
|
||||
// _3 = _4;
|
||||
// _5 = _3;
|
||||
// _0 = _5;
|
||||
// return;
|
||||
// }
|
||||
// END rustc.node4.CopyPropagation.before.mir
|
||||
// START rustc.node4.CopyPropagation.after.mir
|
||||
// bb0: {
|
||||
// _0 = _1;
|
||||
// return;
|
||||
// }
|
||||
// END rustc.node4.CopyPropagation.after.mir
|
|
@ -127,6 +127,9 @@ pub struct Config {
|
|||
// Only run tests that match this filter
|
||||
pub filter: Option<String>,
|
||||
|
||||
// Exactly match the filter, rather than a substring
|
||||
pub filter_exact: bool,
|
||||
|
||||
// Write out a parseable log of tests that were run
|
||||
pub logfile: Option<PathBuf>,
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
|
|||
"(compile-fail|parse-fail|run-fail|run-pass|\
|
||||
run-pass-valgrind|pretty|debug-info|incremental|mir-opt)"),
|
||||
optflag("", "ignored", "run tests marked as ignored"),
|
||||
optflag("", "exact", "filters match exactly"),
|
||||
optopt("", "runtool", "supervisor program to run tests under \
|
||||
(eg. emulator, valgrind)", "PROGRAM"),
|
||||
optopt("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS"),
|
||||
|
@ -167,6 +168,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
|
|||
mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"),
|
||||
run_ignored: matches.opt_present("ignored"),
|
||||
filter: matches.free.first().cloned(),
|
||||
filter_exact: matches.opt_present("exact"),
|
||||
logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
|
||||
runtool: matches.opt_str("runtool"),
|
||||
host_rustcflags: matches.opt_str("host-rustcflags"),
|
||||
|
@ -216,6 +218,7 @@ pub fn log_config(config: &Config) {
|
|||
opt_str(&config.filter
|
||||
.as_ref()
|
||||
.map(|re| re.to_owned()))));
|
||||
logv(c, format!("filter_exact: {}", config.filter_exact));
|
||||
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
|
||||
logv(c, format!("host-rustcflags: {}",
|
||||
opt_str(&config.host_rustcflags)));
|
||||
|
@ -309,6 +312,7 @@ pub fn run_tests(config: &Config) {
|
|||
pub fn test_opts(config: &Config) -> test::TestOpts {
|
||||
test::TestOpts {
|
||||
filter: config.filter.clone(),
|
||||
filter_exact: config.filter_exact,
|
||||
run_ignored: config.run_ignored,
|
||||
quiet: config.quiet,
|
||||
logfile: config.logfile.clone(),
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"5cee7774cf6d876246a0ae0f8362cceeecec5924b751049c945faac9342565ff","Cargo.toml":"2634dedd87889b33a794e31b41a8d8d4713ef40382be3d464229707679bd83da","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ecb2d93f4c81edbd48d8742ff7887dc0a4530a5890967839090bbc972d49bebe","appveyor.yml":"46c77d913eaa45871296942c2cd96ef092c9dcaf19201cb5c500a5107faeb06f","src/bin/gcc-shim.rs":"11edfe1fc6f932bd42ffffda5145833302bc163e0b87dc0d54f4bd0997ad4708","src/lib.rs":"5eb0e311367226ed0420f5e2dac10cc35fc0a3be639a612b6e8ea6d24f646634","src/registry.rs":"3e2a42581ebb82e325dd5600c6571cef937b35003b2927dc618967f5238a2058","src/windows_registry.rs":"906653c020ffe9d572e435f3fc3a8892d9e0a13240ba297db01ce0a288e08cdb","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"d11ed0db4dda5ecf5fb970c9b0c56428cd47421a2742f07032e2cc6b0a0f07e2","tests/test.rs":"164220f11be2eebc20315826513999970660a82feff8cc4b15b4e9d73d98324e"},"package":"553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"675ffe583db77282d010306f29e6d81e5070ab081deddd0300137dfbd2cb83de","Cargo.toml":"19bb617b74de761515ef5d087fd0e30912fda1d7c22fd04fa211236dab99a509","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ecb2d93f4c81edbd48d8742ff7887dc0a4530a5890967839090bbc972d49bebe","appveyor.yml":"46c77d913eaa45871296942c2cd96ef092c9dcaf19201cb5c500a5107faeb06f","src/bin/gcc-shim.rs":"11edfe1fc6f932bd42ffffda5145833302bc163e0b87dc0d54f4bd0997ad4708","src/lib.rs":"7e7c60beccfdd145e876da81bb07dd09c5248dab0b26d93190bab4242799d51a","src/registry.rs":"3e2a42581ebb82e325dd5600c6571cef937b35003b2927dc618967f5238a2058","src/windows_registry.rs":"1f4211caec5a192b5f05c8a47efb27aa6a0ab976c659b9318a0cf603a28d6746","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"f4dad5a8133c3dd6678d9a3de057b82e624ef547b9b3e4ac9508a48962fc387b","tests/test.rs":"164220f11be2eebc20315826513999970660a82feff8cc4b15b4e9d73d98324e"},"package":"872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950"}
|
|
@ -19,12 +19,14 @@ script:
|
|||
- cargo test --manifest-path gcc-test/Cargo.toml --target $TARGET --features parallel
|
||||
- cargo test --manifest-path gcc-test/Cargo.toml --target $TARGET --release
|
||||
- cargo doc
|
||||
- cargo clean && cargo build
|
||||
- rustdoc --test README.md -L target/debug -L target/debug/deps
|
||||
after_success:
|
||||
- travis-cargo --only nightly doc-upload
|
||||
env:
|
||||
global:
|
||||
secure: ilbcq9zX+UaiBcwqkBGldeanbEQus9npLsi0/nF1PUxKbQsoWSVtVOehAD8Hy92D3hX2npIRyNL8GxBn85XEcBYc1h7DiWUhLcXfZie79v8Ly/qboHCfZLXlB1ofbypbyQfouEdOE9zHf0ZILYVpAgUkliv6KuVShsrKNlbn4QE=
|
||||
secure: "CBtqrudgE0PS8x3kTr44jKbC2D4nfnmdYVecooNm0qnER4B4TSvZpZSQoCgKK6k4BYQuOSyFTOwYx6M79w39ZMOgyCP9ytB+tyMWL0/+ZuUQL04yVg4M5vd3oJMkOaXbvG56ncgPyFrseY+FPDg+mXAzvJk/nily37YXjkQj2D0="
|
||||
|
||||
matrix:
|
||||
- ARCH=x86_64
|
||||
- ARCH=i686
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
|
||||
name = "gcc"
|
||||
version = "0.3.38"
|
||||
version = "0.3.40"
|
||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/alexcrichton/gcc-rs"
|
||||
|
|
|
@ -353,6 +353,23 @@ impl Config {
|
|||
self.compile_objects(&src_dst);
|
||||
self.assemble(lib_name, &dst.join(output), &objects);
|
||||
|
||||
if self.get_target().contains("msvc") {
|
||||
let compiler = self.get_base_compiler();
|
||||
let atlmfc_lib = compiler.env().iter().find(|&&(ref var, _)| {
|
||||
var == OsStr::new("LIB")
|
||||
}).and_then(|&(_, ref lib_paths)| {
|
||||
env::split_paths(lib_paths).find(|path| {
|
||||
let sub = Path::new("atlmfc/lib");
|
||||
path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub))
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(atlmfc_lib) = atlmfc_lib {
|
||||
self.print(&format!("cargo:rustc-link-search=native={}",
|
||||
atlmfc_lib.display()));
|
||||
}
|
||||
}
|
||||
|
||||
self.print(&format!("cargo:rustc-link-lib=static={}",
|
||||
&output[3..output.len() - 2]));
|
||||
self.print(&format!("cargo:rustc-link-search=native={}", dst.display()));
|
||||
|
@ -446,17 +463,20 @@ impl Config {
|
|||
|
||||
if msvc {
|
||||
cmd.args.push("/nologo".into());
|
||||
cmd.args.push("/MD".into()); // link against msvcrt.dll for now
|
||||
let features = env::var("CARGO_CFG_TARGET_FEATURE")
|
||||
.unwrap_or(String::new());
|
||||
if features.contains("crt-static") {
|
||||
cmd.args.push("/MT".into());
|
||||
} else {
|
||||
cmd.args.push("/MD".into());
|
||||
}
|
||||
match &opt_level[..] {
|
||||
"z" | "s" => cmd.args.push("/Os".into()),
|
||||
"2" => cmd.args.push("/O2".into()),
|
||||
"1" => cmd.args.push("/O1".into()),
|
||||
_ => {}
|
||||
}
|
||||
if target.contains("i686") {
|
||||
cmd.args.push("/SAFESEH".into());
|
||||
} else if target.contains("i586") {
|
||||
cmd.args.push("/SAFESEH".into());
|
||||
if target.contains("i586") {
|
||||
cmd.args.push("/ARCH:IA32".into());
|
||||
}
|
||||
} else if nvcc {
|
||||
|
@ -489,27 +509,48 @@ impl Config {
|
|||
cmd.args.push("-Xcompiler".into());
|
||||
cmd.args.push("\'-fPIC\'".into());
|
||||
}
|
||||
|
||||
if target.contains("musl") {
|
||||
cmd.args.push("-static".into());
|
||||
}
|
||||
|
||||
// armv7 targets get to use armv7 instructions
|
||||
if target.starts_with("armv7-unknown-linux-") {
|
||||
cmd.args.push("-march=armv7-a".into());
|
||||
}
|
||||
|
||||
// On android we can guarantee some extra float instructions
|
||||
// (specified in the android spec online)
|
||||
if target.starts_with("armv7-linux-androideabi") {
|
||||
cmd.args.push("-march=armv7-a".into());
|
||||
cmd.args.push("-mfpu=vfpv3-d16".into());
|
||||
}
|
||||
|
||||
// For us arm == armv6 by default
|
||||
if target.starts_with("arm-unknown-linux-") {
|
||||
cmd.args.push("-march=armv6".into());
|
||||
cmd.args.push("-marm".into());
|
||||
}
|
||||
|
||||
// Turn codegen down on i586 to avoid some instructions.
|
||||
if target.starts_with("i586-unknown-linux-") {
|
||||
cmd.args.push("-march=pentium".into());
|
||||
}
|
||||
|
||||
// Set codegen level for i686 correctly
|
||||
if target.starts_with("i686-unknown-linux-") {
|
||||
cmd.args.push("-march=i686".into());
|
||||
}
|
||||
|
||||
// Looks like `musl-gcc` makes is hard for `-m32` to make its way
|
||||
// all the way to the linker, so we need to actually instruct the
|
||||
// linker that we're generating 32-bit executables as well. This'll
|
||||
// typically only be used for build scripts which transitively use
|
||||
// these flags that try to compile executables.
|
||||
if target == "i686-unknown-linux-musl" {
|
||||
cmd.args.push("-Wl,-melf_i386".into());
|
||||
}
|
||||
|
||||
if target.starts_with("thumb") {
|
||||
cmd.args.push("-mthumb".into());
|
||||
|
||||
|
@ -518,10 +559,14 @@ impl Config {
|
|||
}
|
||||
}
|
||||
if target.starts_with("thumbv6m") {
|
||||
cmd.args.push("-march=armv6-m".into());
|
||||
cmd.args.push("-march=armv6s-m".into());
|
||||
}
|
||||
if target.starts_with("thumbv7em") {
|
||||
cmd.args.push("-march=armv7e-m".into());
|
||||
|
||||
if target.ends_with("eabihf") {
|
||||
cmd.args.push("-mfpu=fpv4-sp-d16".into())
|
||||
}
|
||||
}
|
||||
if target.starts_with("thumbv7m") {
|
||||
cmd.args.push("-march=armv7-m".into());
|
||||
|
@ -739,6 +784,7 @@ impl Config {
|
|||
"powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
|
||||
"powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"),
|
||||
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
|
||||
"sparc64-unknown-netbsd" => Some("sparc64--netbsd"),
|
||||
"thumbv6m-none-eabi" => Some("arm-none-eabi"),
|
||||
"thumbv7em-none-eabi" => Some("arm-none-eabi"),
|
||||
"thumbv7em-none-eabihf" => Some("arm-none-eabi"),
|
||||
|
@ -805,6 +851,8 @@ impl Config {
|
|||
None
|
||||
} else if target.contains("darwin") {
|
||||
Some("c++".to_string())
|
||||
} else if target.contains("freebsd") {
|
||||
Some("c++".to_string())
|
||||
} else {
|
||||
Some("stdc++".to_string())
|
||||
}
|
||||
|
|
|
@ -211,6 +211,11 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
|
|||
let sub = otry!(vc_lib_subdir(target));
|
||||
tool.libs.push(path.join("lib").join(sub));
|
||||
tool.include.push(path.join("include"));
|
||||
let atlmfc_path = path.join("atlmfc");
|
||||
if atlmfc_path.exists() {
|
||||
tool.libs.push(atlmfc_path.join("lib").join(sub));
|
||||
tool.include.push(atlmfc_path.join("include"));
|
||||
}
|
||||
Some(tool)
|
||||
}).next()
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ impl Test {
|
|||
pub fn new() -> Test {
|
||||
let mut gcc = PathBuf::from(env::current_exe().unwrap());
|
||||
gcc.pop();
|
||||
if gcc.ends_with("deps") {
|
||||
gcc.pop();
|
||||
}
|
||||
gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX));
|
||||
Test {
|
||||
td: TempDir::new("gcc-test").unwrap(),
|
||||
|
|
Loading…
Reference in New Issue