Auto merge of #73550 - RalfJung:rollup-5huj1k1, r=RalfJung
Rollup of 9 pull requests Successful merges: - #72600 (Properly encode AnonConst into crate metadata) - #73055 (remove leftover mentions of `skol` and `int` from the compiler) - #73058 (Support sanitizers on aarch64-unknown-linux-gnu) - #73171 (RISC-V Emulated Testing) - #73404 (Update CFGuard syntax) - #73444 (ci: disable alt build during try builds) - #73471 (Prevent attacker from manipulating FPU tag word used in SGX enclave) - #73539 (Deprecate `Vec::remove_item`) - #73543 (Clean up E0695 explanation) Failed merges: r? @ghost
This commit is contained in:
commit
f455e46eae
57 changed files with 545 additions and 299 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
|
@ -152,10 +152,6 @@ jobs:
|
||||||
- name: dist-x86_64-linux
|
- name: dist-x86_64-linux
|
||||||
os: ubuntu-latest-xl
|
os: ubuntu-latest-xl
|
||||||
env: {}
|
env: {}
|
||||||
- name: dist-x86_64-linux-alt
|
|
||||||
env:
|
|
||||||
IMAGE: dist-x86_64-linux
|
|
||||||
os: ubuntu-latest-xl
|
|
||||||
timeout-minutes: 600
|
timeout-minutes: 600
|
||||||
runs-on: "${{ matrix.os }}"
|
runs-on: "${{ matrix.os }}"
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
|
|
@ -1206,7 +1206,7 @@ impl<'a> Builder<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc
|
// If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc
|
||||||
// when compiling the standard library, since this might be linked into the final outputs
|
// when compiling the standard library, since this might be linked into the final outputs
|
||||||
// produced by rustc. Since this mitigation is only available on Windows, only enable it
|
// produced by rustc. Since this mitigation is only available on Windows, only enable it
|
||||||
// for the standard library in case the compiler is run on a non-Windows platform.
|
// for the standard library in case the compiler is run on a non-Windows platform.
|
||||||
|
|
@ -1217,7 +1217,7 @@ impl<'a> Builder<'a> {
|
||||||
&& self.config.control_flow_guard
|
&& self.config.control_flow_guard
|
||||||
&& compiler.stage >= 1
|
&& compiler.stage >= 1
|
||||||
{
|
{
|
||||||
rustflags.arg("-Zcontrol_flow_guard=checks");
|
rustflags.arg("-Zcontrol-flow-guard");
|
||||||
}
|
}
|
||||||
|
|
||||||
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
|
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,8 @@ v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
|
||||||
"rootfs in qemu testing, you probably don't want to use this")
|
"rootfs in qemu testing, you probably don't want to use this")
|
||||||
v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
|
v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
|
||||||
"rootfs in qemu testing, you probably don't want to use this")
|
"rootfs in qemu testing, you probably don't want to use this")
|
||||||
|
v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs",
|
||||||
|
"rootfs in qemu testing, you probably don't want to use this")
|
||||||
v("experimental-targets", "llvm.experimental-targets",
|
v("experimental-targets", "llvm.experimental-targets",
|
||||||
"experimental LLVM targets to build")
|
"experimental LLVM targets to build")
|
||||||
v("release-channel", "rust.channel", "the name of the release channel to build")
|
v("release-channel", "rust.channel", "the name of the release channel to build")
|
||||||
|
|
|
||||||
|
|
@ -689,48 +689,41 @@ fn supported_sanitizers(
|
||||||
target: Interned<String>,
|
target: Interned<String>,
|
||||||
channel: &str,
|
channel: &str,
|
||||||
) -> Vec<SanitizerRuntime> {
|
) -> Vec<SanitizerRuntime> {
|
||||||
let mut result = Vec::new();
|
let darwin_libs = |os: &str, components: &[&str]| -> Vec<SanitizerRuntime> {
|
||||||
|
components
|
||||||
|
.into_iter()
|
||||||
|
.map(move |c| SanitizerRuntime {
|
||||||
|
cmake_target: format!("clang_rt.{}_{}_dynamic", c, os),
|
||||||
|
path: out_dir
|
||||||
|
.join(&format!("build/lib/darwin/libclang_rt.{}_{}_dynamic.dylib", c, os)),
|
||||||
|
name: format!("librustc-{}_rt.{}.dylib", channel, c),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
let common_libs = |os: &str, arch: &str, components: &[&str]| -> Vec<SanitizerRuntime> {
|
||||||
|
components
|
||||||
|
.into_iter()
|
||||||
|
.map(move |c| SanitizerRuntime {
|
||||||
|
cmake_target: format!("clang_rt.{}-{}", c, arch),
|
||||||
|
path: out_dir.join(&format!("build/lib/{}/libclang_rt.{}-{}.a", os, c, arch)),
|
||||||
|
name: format!("librustc-{}_rt.{}.a", channel, c),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
match &*target {
|
match &*target {
|
||||||
"x86_64-apple-darwin" => {
|
"aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
|
||||||
for s in &["asan", "lsan", "tsan"] {
|
"aarch64-unknown-linux-gnu" => {
|
||||||
result.push(SanitizerRuntime {
|
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"])
|
||||||
cmake_target: format!("clang_rt.{}_osx_dynamic", s),
|
|
||||||
path: out_dir
|
|
||||||
.join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)),
|
|
||||||
name: format!("librustc-{}_rt.{}.dylib", channel, s),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
|
||||||
|
"x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
|
||||||
"x86_64-unknown-linux-gnu" => {
|
"x86_64-unknown-linux-gnu" => {
|
||||||
for s in &["asan", "lsan", "msan", "tsan"] {
|
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
|
||||||
result.push(SanitizerRuntime {
|
|
||||||
cmake_target: format!("clang_rt.{}-x86_64", s),
|
|
||||||
path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)),
|
|
||||||
name: format!("librustc-{}_rt.{}.a", channel, s),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"x86_64-fuchsia" => {
|
_ => Vec::new(),
|
||||||
for s in &["asan"] {
|
|
||||||
result.push(SanitizerRuntime {
|
|
||||||
cmake_target: format!("clang_rt.{}-x86_64", s),
|
|
||||||
path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-x86_64.a", s)),
|
|
||||||
name: format!("librustc-{}_rt.{}.a", channel, s),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"aarch64-fuchsia" => {
|
|
||||||
for s in &["asan"] {
|
|
||||||
result.push(SanitizerRuntime {
|
|
||||||
cmake_target: format!("clang_rt.{}-aarch64", s),
|
|
||||||
path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-aarch64.a", s)),
|
|
||||||
name: format!("librustc-{}_rt.{}.a", channel, s),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HashStamp {
|
struct HashStamp {
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
dist-x86_64-linux: {}
|
dist-x86_64-linux: {}
|
||||||
dist-x86_64-linux-alt:
|
|
||||||
IMAGE: dist-x86_64-linux
|
|
||||||
|
|
||||||
# The macOS and Windows builds here are currently disabled due to them not being
|
# The macOS and Windows builds here are currently disabled due to them not being
|
||||||
# overly necessary on `try` builds. We also don't actually have anything that
|
# overly necessary on `try` builds. We also don't actually have anything that
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
From c820da85c65c7f3aa9e9cb3ed71ada69bf9b783e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alistair Francis <alistair.francis@wdc.com>
|
||||||
|
Date: Tue, 19 Nov 2019 13:06:40 +0100
|
||||||
|
Subject: [PATCH] Remove stime() function calls
|
||||||
|
|
||||||
|
stime() has been deprecated in glibc 2.31 and replaced with
|
||||||
|
clock_settime(). Let's replace the stime() function calls with
|
||||||
|
clock_settime() in preperation.
|
||||||
|
|
||||||
|
function old new delta
|
||||||
|
rdate_main 197 224 +27
|
||||||
|
clock_settime - 27 +27
|
||||||
|
date_main 926 941 +15
|
||||||
|
stime 37 - -37
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
(add/remove: 2/2 grow/shrink: 2/0 up/down: 69/-37) Total: 32 bytes
|
||||||
|
|
||||||
|
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
|
||||||
|
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
|
||||||
|
|
||||||
|
[Tom Eccles: adjust patch context to apply on top of 1.31.1-stable]
|
||||||
|
Signed-off-by: Tom Eccles <tom.eccles@codethink.co.uk>
|
||||||
|
---
|
||||||
|
coreutils/date.c | 6 +++++-
|
||||||
|
libbb/missing_syscalls.c | 8 --------
|
||||||
|
util-linux/rdate.c | 8 ++++++--
|
||||||
|
3 files changed, 11 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/coreutils/date.c b/coreutils/date.c
|
||||||
|
index 3414d38ae..4ade6abb4 100644
|
||||||
|
--- a/coreutils/date.c
|
||||||
|
+++ b/coreutils/date.c
|
||||||
|
@@ -279,6 +279,9 @@ int date_main(int argc UNUSED_PARAM, char **argv)
|
||||||
|
time(&ts.tv_sec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
+#if !ENABLE_FEATURE_DATE_NANO
|
||||||
|
+ ts.tv_nsec = 0;
|
||||||
|
+#endif
|
||||||
|
localtime_r(&ts.tv_sec, &tm_time);
|
||||||
|
|
||||||
|
/* If date string is given, update tm_time, and maybe set date */
|
||||||
|
@@ -301,9 +304,10 @@ int date_main(int argc UNUSED_PARAM, char **argv)
|
||||||
|
if (date_str[0] != '@')
|
||||||
|
tm_time.tm_isdst = -1;
|
||||||
|
ts.tv_sec = validate_tm_time(date_str, &tm_time);
|
||||||
|
+ ts.tv_nsec = 0;
|
||||||
|
|
||||||
|
/* if setting time, set it */
|
||||||
|
- if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
|
||||||
|
+ if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) {
|
||||||
|
bb_perror_msg("can't set date");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c
|
||||||
|
index 87cf59b3d..dc40d9155 100644
|
||||||
|
--- a/libbb/missing_syscalls.c
|
||||||
|
+++ b/libbb/missing_syscalls.c
|
||||||
|
@@ -15,14 +15,6 @@ pid_t getsid(pid_t pid)
|
||||||
|
return syscall(__NR_getsid, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
-int stime(const time_t *t)
|
||||||
|
-{
|
||||||
|
- struct timeval tv;
|
||||||
|
- tv.tv_sec = *t;
|
||||||
|
- tv.tv_usec = 0;
|
||||||
|
- return settimeofday(&tv, NULL);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int sethostname(const char *name, size_t len)
|
||||||
|
{
|
||||||
|
return syscall(__NR_sethostname, name, len);
|
||||||
|
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
|
||||||
|
index 70f829e7f..878375d78 100644
|
||||||
|
--- a/util-linux/rdate.c
|
||||||
|
+++ b/util-linux/rdate.c
|
||||||
|
@@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
|
||||||
|
if (!(flags & 2)) { /* no -p (-s may be present) */
|
||||||
|
if (time(NULL) == remote_time)
|
||||||
|
bb_error_msg("current time matches remote time");
|
||||||
|
- else
|
||||||
|
- if (stime(&remote_time) < 0)
|
||||||
|
+ else {
|
||||||
|
+ struct timespec ts;
|
||||||
|
+ ts.tv_sec = remote_time;
|
||||||
|
+ ts.tv_nsec = 0;
|
||||||
|
+ if (clock_settime(CLOCK_REALTIME, &ts) < 0)
|
||||||
|
bb_perror_msg_and_die("can't set time of day");
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags != 1) /* not lone -s */
|
||||||
|
--
|
||||||
|
2.25.1
|
||||||
|
|
||||||
102
src/ci/docker/disabled/riscv64gc-linux/Dockerfile
Normal file
102
src/ci/docker/disabled/riscv64gc-linux/Dockerfile
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
# based on armhf-gnu/Dockerfile
|
||||||
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
|
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||||
|
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
||||||
|
bc \
|
||||||
|
bison \
|
||||||
|
ca-certificates \
|
||||||
|
cmake \
|
||||||
|
cpio \
|
||||||
|
curl \
|
||||||
|
debian-ports-archive-keyring \
|
||||||
|
debootstrap \
|
||||||
|
flex \
|
||||||
|
gcc \
|
||||||
|
gcc-riscv64-linux-gnu \
|
||||||
|
git \
|
||||||
|
g++-riscv64-linux-gnu \
|
||||||
|
g++ \
|
||||||
|
libc6-dev \
|
||||||
|
libc6-dev-riscv64-cross \
|
||||||
|
make \
|
||||||
|
patch \
|
||||||
|
python3 \
|
||||||
|
qemu-system-misc \
|
||||||
|
xz-utils
|
||||||
|
|
||||||
|
ENV ARCH=riscv
|
||||||
|
ENV CROSS_COMPILE=riscv64-linux-gnu-
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# From https://github.com/michaeljclark/busybear-linux/blob/master/conf/linux.config
|
||||||
|
COPY riscv64gc-linux/linux.config /build
|
||||||
|
|
||||||
|
# Compile the kernel that we're going to be emulating with. This is
|
||||||
|
# basically just done to be compatible with the QEMU target that we're going
|
||||||
|
# to be using when running tests.
|
||||||
|
RUN curl https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.6.16.tar.xz | tar xJf - && \
|
||||||
|
cp linux.config linux-5.6.16/.config && \
|
||||||
|
cd /build/linux-5.6.16 && \
|
||||||
|
make olddefconfig && \
|
||||||
|
make -j$(nproc) vmlinux
|
||||||
|
RUN cp linux-5.6.16/vmlinux /tmp
|
||||||
|
RUN rm -rf linux-5.6.16
|
||||||
|
|
||||||
|
# Compile an instance of busybox as this provides a lightweight system and init
|
||||||
|
# binary which we will boot into. Only trick here is configuring busybox to
|
||||||
|
# build static binaries.
|
||||||
|
RUN curl https://busybox.net/downloads/busybox-1.31.1.tar.bz2 | tar xjf -
|
||||||
|
COPY riscv64gc-linux/0001-Remove-stime-function-calls.patch /build/busybox-1.31.1/
|
||||||
|
RUN cd /build/busybox-1.31.1 && \
|
||||||
|
patch -p1 -i 0001-Remove-stime-function-calls.patch && \
|
||||||
|
make defconfig && \
|
||||||
|
sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
|
||||||
|
make -j$(nproc) && \
|
||||||
|
make install && \
|
||||||
|
mv _install /tmp/rootfs && \
|
||||||
|
cd /build && \
|
||||||
|
rm -rf busybox-1.31.1
|
||||||
|
|
||||||
|
# Download the ubuntu rootfs, which we'll use as a chroot for all our tests
|
||||||
|
# This is only needed to provide /lib/* and /usr/lib/*
|
||||||
|
WORKDIR /tmp
|
||||||
|
RUN debootstrap --variant=minbase --arch=riscv64 --foreign focal /tmp/rootfs/ubuntu
|
||||||
|
RUN cd rootfs && mkdir proc sys dev etc etc/init.d
|
||||||
|
# rootfs/ubuntu/proc is in a weird state (access fails with ELOOP) until
|
||||||
|
# rootfs/ubuntu/debootstrap/debootstrap --second-stage is run (under emulation),
|
||||||
|
# but this takes ages. Instead hack it into a good enough state.
|
||||||
|
# /proc is used by std::env::current_exe() (which is roughly
|
||||||
|
# `readlink /proc/self/exe`)
|
||||||
|
RUN cd rootfs/ubuntu && rm -rf proc && mkdir proc
|
||||||
|
|
||||||
|
# Copy over our init script, which starts up our test server and also a few other
|
||||||
|
# misc tasks
|
||||||
|
COPY scripts/qemu-bare-bones-rcS rootfs/etc/init.d/rcS
|
||||||
|
RUN chmod +x rootfs/etc/init.d/rcS
|
||||||
|
|
||||||
|
# Helper to quickly fill the entropy pool in the kernel
|
||||||
|
COPY scripts/qemu-bare-bones-addentropy.c /tmp/addentropy.c
|
||||||
|
RUN riscv64-linux-gnu-gcc addentropy.c -o rootfs/addentropy -static
|
||||||
|
|
||||||
|
# download and build the riscv bootloader
|
||||||
|
RUN git clone https://github.com/riscv/riscv-pk
|
||||||
|
WORKDIR /tmp/riscv-pk
|
||||||
|
# nothing special about this revision: it is just master at the time of writing
|
||||||
|
# v1.0.0 doesn't build
|
||||||
|
RUN git checkout 5d9ed238e1cabfbca3c47f50d32894ce94bfc304
|
||||||
|
RUN mkdir build && cd build && \
|
||||||
|
../configure --with-payload=/tmp/vmlinux --host=riscv64-linux-gnu && \
|
||||||
|
make -j$(nproc) && \
|
||||||
|
cp bbl /tmp
|
||||||
|
WORKDIR /tmp
|
||||||
|
RUN rm -rf /tmp/riscv-pk
|
||||||
|
|
||||||
|
COPY scripts/sccache.sh /scripts/
|
||||||
|
RUN sh /scripts/sccache.sh
|
||||||
|
|
||||||
|
ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
|
||||||
|
ENV SCRIPT python3 ../x.py test --target riscv64gc-unknown-linux-gnu
|
||||||
|
|
||||||
|
ENV NO_CHANGE_USER=1
|
||||||
51
src/ci/docker/disabled/riscv64gc-linux/linux.config
Normal file
51
src/ci/docker/disabled/riscv64gc-linux/linux.config
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
CONFIG_DEFAULT_HOSTNAME="busybear"
|
||||||
|
CONFIG_SYSVIPC=y
|
||||||
|
CONFIG_POSIX_MQUEUE=y
|
||||||
|
CONFIG_IKCONFIG=y
|
||||||
|
CONFIG_IKCONFIG_PROC=y
|
||||||
|
CONFIG_CGROUPS=y
|
||||||
|
CONFIG_CGROUP_SCHED=y
|
||||||
|
CONFIG_CFS_BANDWIDTH=y
|
||||||
|
CONFIG_CGROUP_BPF=y
|
||||||
|
CONFIG_NAMESPACES=y
|
||||||
|
CONFIG_USER_NS=y
|
||||||
|
CONFIG_CHECKPOINT_RESTORE=y
|
||||||
|
CONFIG_BLK_DEV_INITRD=y
|
||||||
|
CONFIG_EXPERT=y
|
||||||
|
CONFIG_BPF_SYSCALL=y
|
||||||
|
CONFIG_SMP=y
|
||||||
|
CONFIG_MODULES=y
|
||||||
|
CONFIG_NET=y
|
||||||
|
CONFIG_PACKET=y
|
||||||
|
CONFIG_PACKET_DIAG=y
|
||||||
|
CONFIG_UNIX=y
|
||||||
|
CONFIG_INET=y
|
||||||
|
CONFIG_NETLINK_DIAG=y
|
||||||
|
# CONFIG_WIRELESS is not set
|
||||||
|
CONFIG_PCI=y
|
||||||
|
CONFIG_DEVTMPFS=y
|
||||||
|
CONFIG_BLK_DEV_LOOP=y
|
||||||
|
CONFIG_VIRTIO_BLK=y
|
||||||
|
CONFIG_NETDEVICES=y
|
||||||
|
CONFIG_VIRTIO_NET=y
|
||||||
|
# CONFIG_ETHERNET is not set
|
||||||
|
# CONFIG_WLAN is not set
|
||||||
|
CONFIG_SERIAL_8250=y
|
||||||
|
CONFIG_SERIAL_8250_CONSOLE=y
|
||||||
|
CONFIG_SERIAL_OF_PLATFORM=y
|
||||||
|
CONFIG_HVC_RISCV_SBI=y
|
||||||
|
# CONFIG_HW_RANDOM is not set
|
||||||
|
# CONFIG_USB_SUPPORT is not set
|
||||||
|
CONFIG_VIRTIO_MMIO=y
|
||||||
|
CONFIG_SIFIVE_PLIC=y
|
||||||
|
CONFIG_RAS=y
|
||||||
|
CONFIG_EXT2_FS=y
|
||||||
|
CONFIG_EXT3_FS=y
|
||||||
|
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||||
|
CONFIG_AUTOFS4_FS=y
|
||||||
|
CONFIG_MSDOS_FS=y
|
||||||
|
CONFIG_VFAT_FS=y
|
||||||
|
CONFIG_TMPFS=y
|
||||||
|
# CONFIG_CRYPTO_ECHAINIV is not set
|
||||||
|
# CONFIG_CRYPTO_HW is not set
|
||||||
|
CONFIG_PRINTK_TIME=y
|
||||||
|
|
@ -35,5 +35,6 @@ ENV HOSTS=aarch64-unknown-linux-gnu
|
||||||
ENV RUST_CONFIGURE_ARGS \
|
ENV RUST_CONFIGURE_ARGS \
|
||||||
--enable-full-tools \
|
--enable-full-tools \
|
||||||
--enable-profiler \
|
--enable-profiler \
|
||||||
|
--enable-sanitizers \
|
||||||
--disable-docs
|
--disable-docs
|
||||||
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
|
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
|
||||||
|
|
|
||||||
|
|
@ -281,11 +281,6 @@ jobs:
|
||||||
- name: dist-x86_64-linux
|
- name: dist-x86_64-linux
|
||||||
<<: *job-linux-xl
|
<<: *job-linux-xl
|
||||||
|
|
||||||
- name: dist-x86_64-linux-alt
|
|
||||||
env:
|
|
||||||
IMAGE: dist-x86_64-linux
|
|
||||||
<<: *job-linux-xl
|
|
||||||
|
|
||||||
auto:
|
auto:
|
||||||
<<: *base-ci-job
|
<<: *base-ci-job
|
||||||
name: auto
|
name: auto
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
# `control_flow_guard`
|
# `control-flow-guard`
|
||||||
|
|
||||||
The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793).
|
The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793).
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
The rustc flag `-Z control_flow_guard=checks` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature.
|
The rustc flag `-Z control-flow-guard` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature.
|
||||||
|
|
||||||
CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported Windows platforms (Windows 8.1 onwards). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete.
|
CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported Windows platforms (Windows 8.1 onwards). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete.
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ The CFG checks and metadata can potentially increase binary size and runtime ove
|
||||||
|
|
||||||
## Testing Control Flow Guard
|
## Testing Control Flow Guard
|
||||||
|
|
||||||
The rustc flag `-Z control_flow_guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement.
|
The rustc flag `-Z control-flow-guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement.
|
||||||
|
|
||||||
|
|
||||||
## Control Flow Guard in libraries
|
## Control Flow Guard in libraries
|
||||||
|
|
@ -44,14 +44,14 @@ For example:
|
||||||
```cmd
|
```cmd
|
||||||
rustup toolchain install --force nightly
|
rustup toolchain install --force nightly
|
||||||
rustup component add rust-src
|
rustup component add rust-src
|
||||||
SET RUSTFLAGS=-Z control_flow_guard=checks
|
SET RUSTFLAGS=-Z control-flow-guard
|
||||||
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
|
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
|
||||||
```
|
```
|
||||||
|
|
||||||
```PowerShell
|
```PowerShell
|
||||||
rustup toolchain install --force nightly
|
rustup toolchain install --force nightly
|
||||||
rustup component add rust-src
|
rustup component add rust-src
|
||||||
$Env:RUSTFLAGS = "-Z control_flow_guard=checks"
|
$Env:RUSTFLAGS = "-Z control-flow-guard"
|
||||||
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
|
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(binary_heap_into_iter_sorted)]
|
#![feature(binary_heap_into_iter_sorted)]
|
||||||
#![feature(binary_heap_drain_sorted)]
|
#![feature(binary_heap_drain_sorted)]
|
||||||
#![feature(vec_remove_item)]
|
|
||||||
#![feature(split_inclusive)]
|
#![feature(split_inclusive)]
|
||||||
#![feature(binary_heap_retain)]
|
#![feature(binary_heap_retain)]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,21 +131,6 @@ fn test_extend_ref() {
|
||||||
assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
|
assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_item() {
|
|
||||||
let mut v = vec![1, 2, 3];
|
|
||||||
v.remove_item(&1);
|
|
||||||
|
|
||||||
assert_eq!(v.len(), 2);
|
|
||||||
assert_eq!(v, [2, 3]);
|
|
||||||
|
|
||||||
let mut w = vec![1, 2, 3];
|
|
||||||
w.remove_item(&4);
|
|
||||||
|
|
||||||
assert_eq!(w.len(), 3);
|
|
||||||
w.remove_item(&4);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_from_mut() {
|
fn test_slice_from_mut() {
|
||||||
let mut values = vec![1, 2, 3, 4, 5];
|
let mut values = vec![1, 2, 3, 4, 5];
|
||||||
|
|
|
||||||
|
|
@ -1760,17 +1760,15 @@ impl<T: PartialEq> Vec<T> {
|
||||||
impl<T> Vec<T> {
|
impl<T> Vec<T> {
|
||||||
/// Removes the first instance of `item` from the vector if the item exists.
|
/// Removes the first instance of `item` from the vector if the item exists.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// This method will be removed soon.
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # #![feature(vec_remove_item)]
|
|
||||||
/// let mut vec = vec![1, 2, 3, 1];
|
|
||||||
///
|
|
||||||
/// vec.remove_item(&1);
|
|
||||||
///
|
|
||||||
/// assert_eq!(vec, vec![2, 3, 1]);
|
|
||||||
/// ```
|
|
||||||
#[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")]
|
#[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")]
|
||||||
|
#[rustc_deprecated(
|
||||||
|
reason = "Removing the first item equal to a needle is already easily possible \
|
||||||
|
with iterators and the current Vec methods. Furthermore, having a method for \
|
||||||
|
one particular case of removal (linear search, only the first item, no swap remove) \
|
||||||
|
but not for others is inconsistent. This method will be removed soon.",
|
||||||
|
since = "1.46.0"
|
||||||
|
)]
|
||||||
pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
|
pub fn remove_item<V>(&mut self, item: &V) -> Option<T>
|
||||||
where
|
where
|
||||||
T: PartialEq<V>,
|
T: PartialEq<V>,
|
||||||
|
|
|
||||||
|
|
@ -804,7 +804,10 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
|
||||||
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
||||||
linker.link_dylib(Symbol::intern(&libname));
|
linker.link_dylib(Symbol::intern(&libname));
|
||||||
}
|
}
|
||||||
"x86_64-unknown-linux-gnu" | "x86_64-fuchsia" | "aarch64-fuchsia" => {
|
"aarch64-fuchsia"
|
||||||
|
| "aarch64-unknown-linux-gnu"
|
||||||
|
| "x86_64-fuchsia"
|
||||||
|
| "x86_64-unknown-linux-gnu" => {
|
||||||
let filename = format!("librustc{}_rt.{}.a", channel, name);
|
let filename = format!("librustc{}_rt.{}.a", channel, name);
|
||||||
let path = default_tlib.join(&filename);
|
let path = default_tlib.join(&filename);
|
||||||
linker.link_whole_rlib(&path);
|
linker.link_whole_rlib(&path);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
A `break` statement without a label appeared inside a labeled block.
|
A `break` statement without a label appeared inside a labeled block.
|
||||||
|
|
||||||
Example of erroneous code:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0695
|
```compile_fail,E0695
|
||||||
# #![feature(label_break_value)]
|
# #![feature(label_break_value)]
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
/// placeholder region. This is the first step of checking subtyping
|
/// placeholder region. This is the first step of checking subtyping
|
||||||
/// when higher-ranked things are involved.
|
/// when higher-ranked things are involved.
|
||||||
///
|
///
|
||||||
/// **Important:** you must call this function from within a snapshot.
|
/// **Important:** You have to be careful to not leak these placeholders,
|
||||||
/// Moreover, before committing the snapshot, you must eventually call
|
/// for more information about how placeholders and HRTBs work, see
|
||||||
/// either `plug_leaks` or `pop_placeholders` to remove the placeholder
|
|
||||||
/// regions. If you rollback the snapshot (or are using a probe), then
|
|
||||||
/// the pop occurs as part of the rollback, so an explicit call is not
|
|
||||||
/// needed (but is also permitted).
|
|
||||||
///
|
|
||||||
/// For more information about how placeholders and HRTBs work, see
|
|
||||||
/// the [rustc dev guide].
|
/// the [rustc dev guide].
|
||||||
///
|
///
|
||||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ impl<'tcx> TaintSet<'tcx> {
|
||||||
verifys[i].origin.span(),
|
verifys[i].origin.span(),
|
||||||
"we never add verifications while doing higher-ranked things",
|
"we never add verifications while doing higher-ranked things",
|
||||||
),
|
),
|
||||||
&Purged | &AddCombination(..) | &AddVar(..) => {}
|
&AddCombination(..) | &AddVar(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -289,14 +289,6 @@ pub(crate) enum UndoLog<'tcx> {
|
||||||
|
|
||||||
/// We added a GLB/LUB "combination variable".
|
/// We added a GLB/LUB "combination variable".
|
||||||
AddCombination(CombineMapType, TwoRegions<'tcx>),
|
AddCombination(CombineMapType, TwoRegions<'tcx>),
|
||||||
|
|
||||||
/// During skolemization, we sometimes purge entries from the undo
|
|
||||||
/// log in a kind of minisnapshot (unlike other snapshots, this
|
|
||||||
/// purging actually takes place *on success*). In that case, we
|
|
||||||
/// replace the corresponding entry with `Noop` so as to avoid the
|
|
||||||
/// need to do a bunch of swapping. (We can't use `swap_remove` as
|
|
||||||
/// the order of the vector is important.)
|
|
||||||
Purged,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
|
@ -357,9 +349,6 @@ impl<'tcx> RegionConstraintStorage<'tcx> {
|
||||||
|
|
||||||
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
|
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
|
||||||
match undo_entry {
|
match undo_entry {
|
||||||
Purged => {
|
|
||||||
// nothing to do here
|
|
||||||
}
|
|
||||||
AddVar(vid) => {
|
AddVar(vid) => {
|
||||||
self.var_infos.pop().unwrap();
|
self.var_infos.pop().unwrap();
|
||||||
assert_eq!(self.var_infos.len(), vid.index() as usize);
|
assert_eq!(self.var_infos.len(), vid.index() as usize);
|
||||||
|
|
@ -488,62 +477,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||||
self.var_infos[vid].origin
|
self.var_infos[vid].origin
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all the edges to/from the placeholder regions that are
|
|
||||||
/// in `skols`. This is used after a higher-ranked operation
|
|
||||||
/// completes to remove all trace of the placeholder regions
|
|
||||||
/// created in that time.
|
|
||||||
pub fn pop_placeholders(&mut self, placeholders: &FxHashSet<ty::Region<'tcx>>) {
|
|
||||||
debug!("pop_placeholders(placeholders={:?})", placeholders);
|
|
||||||
|
|
||||||
assert!(UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
|
||||||
|
|
||||||
let constraints_to_kill: Vec<usize> = self
|
|
||||||
.undo_log
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.rev()
|
|
||||||
.filter(|&(_, undo_entry)| match undo_entry {
|
|
||||||
super::UndoLog::RegionConstraintCollector(undo_entry) => {
|
|
||||||
kill_constraint(placeholders, undo_entry)
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.map(|(index, _)| index)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for index in constraints_to_kill {
|
|
||||||
let undo_entry = match &mut self.undo_log[index] {
|
|
||||||
super::UndoLog::RegionConstraintCollector(undo_entry) => {
|
|
||||||
mem::replace(undo_entry, Purged)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
self.rollback_undo_entry(undo_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
fn kill_constraint<'tcx>(
|
|
||||||
placeholders: &FxHashSet<ty::Region<'tcx>>,
|
|
||||||
undo_entry: &UndoLog<'tcx>,
|
|
||||||
) -> bool {
|
|
||||||
match undo_entry {
|
|
||||||
&AddConstraint(Constraint::VarSubVar(..)) => false,
|
|
||||||
&AddConstraint(Constraint::RegSubVar(a, _)) => placeholders.contains(&a),
|
|
||||||
&AddConstraint(Constraint::VarSubReg(_, b)) => placeholders.contains(&b),
|
|
||||||
&AddConstraint(Constraint::RegSubReg(a, b)) => {
|
|
||||||
placeholders.contains(&a) || placeholders.contains(&b)
|
|
||||||
}
|
|
||||||
&AddGiven(..) => false,
|
|
||||||
&AddVerify(_) => false,
|
|
||||||
&AddCombination(_, ref two_regions) => {
|
|
||||||
placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b)
|
|
||||||
}
|
|
||||||
&AddVar(..) | &Purged => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
|
fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
|
||||||
// cannot add constraints once regions are resolved
|
// cannot add constraints once regions are resolved
|
||||||
debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
|
debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
|
||||||
|
|
|
||||||
|
|
@ -198,10 +198,6 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
|
||||||
assert!(self.logs.len() >= snapshot.undo_len);
|
assert!(self.logs.len() >= snapshot.undo_len);
|
||||||
assert!(self.num_open_snapshots > 0);
|
assert!(self.num_open_snapshots > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn iter(&self) -> std::slice::Iter<'_, UndoLog<'tcx>> {
|
|
||||||
self.logs.iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> std::ops::Index<usize> for InferCtxtUndoLogs<'tcx> {
|
impl<'tcx> std::ops::Index<usize> for InferCtxtUndoLogs<'tcx> {
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ crate use self::util::elaborate_predicates;
|
||||||
|
|
||||||
pub use rustc_middle::traits::*;
|
pub use rustc_middle::traits::*;
|
||||||
|
|
||||||
/// An `Obligation` represents some trait reference (e.g., `int: Eq`) for
|
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
|
||||||
/// which the "impl_source" must be found. The process of finding a "impl_source" is
|
/// which the "impl_source" must be found. The process of finding a "impl_source" is
|
||||||
/// called "resolving" the `Obligation`. This process consists of
|
/// called "resolving" the `Obligation`. This process consists of
|
||||||
/// either identifying an `impl` (e.g., `impl Eq for int`) that
|
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
|
||||||
/// satisfies the obligation, or else finding a bound that is in
|
/// satisfies the obligation, or else finding a bound that is in
|
||||||
/// scope. The eventual result is usually a `Selection` (defined below).
|
/// scope. The eventual result is usually a `Selection` (defined below).
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,11 @@ impl PredicateSet<'tcx> {
|
||||||
fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
|
fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
|
||||||
// We have to be careful here because we want
|
// We have to be careful here because we want
|
||||||
//
|
//
|
||||||
// for<'a> Foo<&'a int>
|
// for<'a> Foo<&'a i32>
|
||||||
//
|
//
|
||||||
// and
|
// and
|
||||||
//
|
//
|
||||||
// for<'b> Foo<&'b int>
|
// for<'b> Foo<&'b i32>
|
||||||
//
|
//
|
||||||
// to be considered equivalent. So normalize all late-bound
|
// to be considered equivalent. So normalize all late-bound
|
||||||
// regions before we throw things into the underlying set.
|
// regions before we throw things into the underlying set.
|
||||||
|
|
|
||||||
|
|
@ -465,7 +465,6 @@ fn test_debugging_options_tracking_hash() {
|
||||||
untracked!(ast_json_noexpand, true);
|
untracked!(ast_json_noexpand, true);
|
||||||
untracked!(borrowck, String::from("other"));
|
untracked!(borrowck, String::from("other"));
|
||||||
untracked!(borrowck_stats, true);
|
untracked!(borrowck_stats, true);
|
||||||
untracked!(control_flow_guard, CFGuard::Checks);
|
|
||||||
untracked!(deduplicate_diagnostics, true);
|
untracked!(deduplicate_diagnostics, true);
|
||||||
untracked!(dep_tasks, true);
|
untracked!(dep_tasks, true);
|
||||||
untracked!(dont_buffer_diagnostics, true);
|
untracked!(dont_buffer_diagnostics, true);
|
||||||
|
|
@ -539,6 +538,7 @@ fn test_debugging_options_tracking_hash() {
|
||||||
tracked!(binary_dep_depinfo, true);
|
tracked!(binary_dep_depinfo, true);
|
||||||
tracked!(chalk, true);
|
tracked!(chalk, true);
|
||||||
tracked!(codegen_backend, Some("abc".to_string()));
|
tracked!(codegen_backend, Some("abc".to_string()));
|
||||||
|
tracked!(control_flow_guard, CFGuard::Checks);
|
||||||
tracked!(crate_attr, vec!["abc".to_string()]);
|
tracked!(crate_attr, vec!["abc".to_string()]);
|
||||||
tracked!(debug_macros, true);
|
tracked!(debug_macros, true);
|
||||||
tracked!(dep_info_omit_d_target, true);
|
tracked!(dep_info_omit_d_target, true);
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,7 @@ impl MetadataBlob {
|
||||||
impl EntryKind {
|
impl EntryKind {
|
||||||
fn def_kind(&self) -> DefKind {
|
fn def_kind(&self) -> DefKind {
|
||||||
match *self {
|
match *self {
|
||||||
|
EntryKind::AnonConst(..) => DefKind::AnonConst,
|
||||||
EntryKind::Const(..) => DefKind::Const,
|
EntryKind::Const(..) => DefKind::Const,
|
||||||
EntryKind::AssocConst(..) => DefKind::AssocConst,
|
EntryKind::AssocConst(..) => DefKind::AssocConst,
|
||||||
EntryKind::ImmStatic
|
EntryKind::ImmStatic
|
||||||
|
|
@ -1121,7 +1122,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
|
|
||||||
fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs {
|
fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs {
|
||||||
match self.kind(id) {
|
match self.kind(id) {
|
||||||
EntryKind::Const(qualif, _)
|
EntryKind::AnonConst(qualif, _)
|
||||||
|
| EntryKind::Const(qualif, _)
|
||||||
| EntryKind::AssocConst(
|
| EntryKind::AssocConst(
|
||||||
AssocContainer::ImplDefault
|
AssocContainer::ImplDefault
|
||||||
| AssocContainer::ImplFinal
|
| AssocContainer::ImplFinal
|
||||||
|
|
@ -1340,7 +1342,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
|
|
||||||
fn get_rendered_const(&self, id: DefIndex) -> String {
|
fn get_rendered_const(&self, id: DefIndex) -> String {
|
||||||
match self.kind(id) {
|
match self.kind(id) {
|
||||||
EntryKind::Const(_, data) | EntryKind::AssocConst(_, _, data) => data.decode(self).0,
|
EntryKind::AnonConst(_, data)
|
||||||
|
| EntryKind::Const(_, data)
|
||||||
|
| EntryKind::AssocConst(_, _, data) => data.decode(self).0,
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1358,7 +1358,7 @@ impl EncodeContext<'tcx> {
|
||||||
let const_data = self.encode_rendered_const_for_body(body_id);
|
let const_data = self.encode_rendered_const_for_body(body_id);
|
||||||
let qualifs = self.tcx.mir_const_qualif(def_id);
|
let qualifs = self.tcx.mir_const_qualif(def_id);
|
||||||
|
|
||||||
record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Const(qualifs, const_data));
|
record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst(qualifs, const_data));
|
||||||
record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
|
record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
|
||||||
record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
|
record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
|
||||||
self.encode_item_type(def_id.to_def_id());
|
self.encode_item_type(def_id.to_def_id());
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,7 @@ define_tables! {
|
||||||
|
|
||||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||||
enum EntryKind {
|
enum EntryKind {
|
||||||
|
AnonConst(mir::ConstQualifs, Lazy<RenderedConst>),
|
||||||
Const(mir::ConstQualifs, Lazy<RenderedConst>),
|
Const(mir::ConstQualifs, Lazy<RenderedConst>),
|
||||||
ImmStatic,
|
ImmStatic,
|
||||||
MutStatic,
|
MutStatic,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(track_caller)]
|
#![feature(track_caller)]
|
||||||
#![feature(trusted_len)]
|
#![feature(trusted_len)]
|
||||||
#![feature(vec_remove_item)]
|
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
|
|
|
||||||
|
|
@ -393,23 +393,25 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
|
||||||
/// ```
|
/// ```
|
||||||
/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
|
/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
|
||||||
/// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
|
/// impl<T:Clone> Clone<T> for Box<T> { ... } // Impl_2
|
||||||
/// impl Clone for int { ... } // Impl_3
|
/// impl Clone for i32 { ... } // Impl_3
|
||||||
///
|
///
|
||||||
/// fn foo<T:Clone>(concrete: Option<Box<int>>,
|
/// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
|
||||||
/// param: T,
|
/// // Case A: Vtable points at a specific impl. Only possible when
|
||||||
/// mixed: Option<T>) {
|
/// // type is concretely known. If the impl itself has bounded
|
||||||
|
/// // type parameters, Vtable will carry resolutions for those as well:
|
||||||
|
/// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
|
||||||
///
|
///
|
||||||
/// // Case A: ImplSource points at a specific impl. Only possible when
|
/// // Case A: ImplSource points at a specific impl. Only possible when
|
||||||
/// // type is concretely known. If the impl itself has bounded
|
/// // type is concretely known. If the impl itself has bounded
|
||||||
/// // type parameters, ImplSource will carry resolutions for those as well:
|
/// // type parameters, ImplSource will carry resolutions for those as well:
|
||||||
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
|
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
|
||||||
///
|
///
|
||||||
/// // Case B: ImplSource must be provided by caller. This applies when
|
/// // Case B: ImplSource must be provided by caller. This applies when
|
||||||
/// // type is a type parameter.
|
/// // type is a type parameter.
|
||||||
/// param.clone(); // ImplSourceParam
|
/// param.clone(); // ImplSourceParam
|
||||||
///
|
///
|
||||||
/// // Case C: A mix of cases A and B.
|
/// // Case C: A mix of cases A and B.
|
||||||
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
|
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -599,12 +599,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// type Func<A> = fn(A);
|
/// type Func<A> = fn(A);
|
||||||
/// type MetaFunc = for<'a> fn(Func<&'a int>)
|
/// type MetaFunc = for<'a> fn(Func<&'a i32>)
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The type `MetaFunc`, when fully expanded, will be
|
/// The type `MetaFunc`, when fully expanded, will be
|
||||||
///
|
///
|
||||||
/// for<'a> fn(fn(&'a int))
|
/// for<'a> fn(fn(&'a i32))
|
||||||
/// ^~ ^~ ^~~
|
/// ^~ ^~ ^~~
|
||||||
/// | | |
|
/// | | |
|
||||||
/// | | DebruijnIndex of 2
|
/// | | DebruijnIndex of 2
|
||||||
|
|
@ -613,7 +613,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
||||||
/// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
|
/// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
|
||||||
/// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
|
/// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
|
||||||
/// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
|
/// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
|
||||||
/// definition of `MetaFunc`, the binder is not visible, so the type `&'a int` will have a
|
/// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a
|
||||||
/// De Bruijn index of 1. It's only during the substitution that we can see we must increase the
|
/// De Bruijn index of 1. It's only during the substitution that we can see we must increase the
|
||||||
/// depth by 1 to account for the binder that we passed through.
|
/// depth by 1 to account for the binder that we passed through.
|
||||||
///
|
///
|
||||||
|
|
@ -621,18 +621,18 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// type FuncTuple<A> = (A,fn(A));
|
/// type FuncTuple<A> = (A,fn(A));
|
||||||
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>)
|
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>)
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Here the final type will be:
|
/// Here the final type will be:
|
||||||
///
|
///
|
||||||
/// for<'a> fn((&'a int, fn(&'a int)))
|
/// for<'a> fn((&'a i32, fn(&'a i32)))
|
||||||
/// ^~~ ^~~
|
/// ^~~ ^~~
|
||||||
/// | |
|
/// | |
|
||||||
/// DebruijnIndex of 1 |
|
/// DebruijnIndex of 1 |
|
||||||
/// DebruijnIndex of 2
|
/// DebruijnIndex of 2
|
||||||
///
|
///
|
||||||
/// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
|
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
|
||||||
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
|
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
|
||||||
/// is that only in the second case have we passed through a fn binder.
|
/// is that only in the second case have we passed through a fn binder.
|
||||||
fn shift_vars_through_binders<T: TypeFoldable<'tcx>>(&self, val: T) -> T {
|
fn shift_vars_through_binders<T: TypeFoldable<'tcx>>(&self, val: T) -> T {
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@ impl<'tcx> TypeWalker<'tcx> {
|
||||||
/// Skips the subtree corresponding to the last type
|
/// Skips the subtree corresponding to the last type
|
||||||
/// returned by `next()`.
|
/// returned by `next()`.
|
||||||
///
|
///
|
||||||
/// Example: Imagine you are walking `Foo<Bar<int>, usize>`.
|
/// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut iter: TypeWalker = ...;
|
/// let mut iter: TypeWalker = ...;
|
||||||
/// iter.next(); // yields Foo
|
/// iter.next(); // yields Foo
|
||||||
/// iter.next(); // yields Bar<int>
|
/// iter.next(); // yields Bar<i32>
|
||||||
/// iter.skip_current_subtree(); // skips int
|
/// iter.skip_current_subtree(); // skips i32
|
||||||
/// iter.next(); // yields usize
|
/// iter.next(); // yields usize
|
||||||
/// ```
|
/// ```
|
||||||
pub fn skip_current_subtree(&mut self) {
|
pub fn skip_current_subtree(&mut self) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#![feature(hash_raw_entry)]
|
#![feature(hash_raw_entry)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
#![feature(vec_remove_item)]
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
|
||||||
|
|
@ -452,7 +452,9 @@ fn remove_cycle<CTX: QueryContext>(
|
||||||
|
|
||||||
// Remove the queries in our cycle from the list of jobs to look at
|
// Remove the queries in our cycle from the list of jobs to look at
|
||||||
for r in &stack {
|
for r in &stack {
|
||||||
jobs.remove_item(&r.1);
|
if let Some(pos) = jobs.iter().position(|j| j == &r.1) {
|
||||||
|
jobs.remove(pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the queries in the cycle which are
|
// Find the queries in the cycle which are
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ pub enum Strip {
|
||||||
Symbols,
|
Symbols,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The different settings that the `-Z control_flow_guard` flag can have.
|
/// The different settings that the `-Z control-flow-guard` flag can have.
|
||||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||||
pub enum CFGuard {
|
pub enum CFGuard {
|
||||||
/// Do not emit Control Flow Guard metadata or checks.
|
/// Do not emit Control Flow Guard metadata or checks.
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,8 @@ macro_rules! options {
|
||||||
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
|
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
|
||||||
pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `leak`, `memory` or `thread`";
|
pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `leak`, `memory` or `thread`";
|
||||||
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
|
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
|
||||||
pub const parse_cfguard: &str = "either `disabled`, `nochecks`, or `checks`";
|
pub const parse_cfguard: &str =
|
||||||
|
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
|
||||||
pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
|
pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
|
||||||
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
|
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
|
||||||
pub const parse_optimization_fuel: &str = "crate=integer";
|
pub const parse_optimization_fuel: &str = "crate=integer";
|
||||||
|
|
@ -495,12 +496,24 @@ macro_rules! options {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_cfguard(slot: &mut CFGuard, v: Option<&str>) -> bool {
|
fn parse_cfguard(slot: &mut CFGuard, v: Option<&str>) -> bool {
|
||||||
match v {
|
if v.is_some() {
|
||||||
Some("disabled") => *slot = CFGuard::Disabled,
|
let mut bool_arg = None;
|
||||||
Some("nochecks") => *slot = CFGuard::NoChecks,
|
if parse_opt_bool(&mut bool_arg, v) {
|
||||||
Some("checks") => *slot = CFGuard::Checks,
|
*slot = if bool_arg.unwrap() {
|
||||||
_ => return false,
|
CFGuard::Checks
|
||||||
|
} else {
|
||||||
|
CFGuard::Disabled
|
||||||
|
};
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*slot = match v {
|
||||||
|
None => CFGuard::Checks,
|
||||||
|
Some("checks") => CFGuard::Checks,
|
||||||
|
Some("nochecks") => CFGuard::NoChecks,
|
||||||
|
Some(_) => return false,
|
||||||
|
};
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -796,8 +809,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"enable the experimental Chalk-based trait solving engine"),
|
"enable the experimental Chalk-based trait solving engine"),
|
||||||
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
|
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||||
"the backend to use"),
|
"the backend to use"),
|
||||||
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [UNTRACKED],
|
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
|
||||||
"use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"),
|
"use Windows Control Flow Guard (default: no)"),
|
||||||
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
|
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
|
||||||
"inject the given attribute in the crate"),
|
"inject the given attribute in the crate"),
|
||||||
debug_macros: bool = (false, parse_bool, [TRACKED],
|
debug_macros: bool = (false, parse_bool, [TRACKED],
|
||||||
|
|
|
||||||
|
|
@ -1349,11 +1349,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ASAN_SUPPORTED_TARGETS: &[&str] =
|
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
|
||||||
&["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"];
|
"aarch64-fuchsia",
|
||||||
const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
"aarch64-unknown-linux-gnu",
|
||||||
const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
|
"x86_64-apple-darwin",
|
||||||
const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
"x86_64-fuchsia",
|
||||||
|
"x86_64-unknown-linux-gnu",
|
||||||
|
];
|
||||||
|
const LSAN_SUPPORTED_TARGETS: &[&str] =
|
||||||
|
&["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
||||||
|
const MSAN_SUPPORTED_TARGETS: &[&str] =
|
||||||
|
&["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"];
|
||||||
|
const TSAN_SUPPORTED_TARGETS: &[&str] =
|
||||||
|
&["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
||||||
|
|
||||||
// Sanitizers can only be used on some tested platforms.
|
// Sanitizers can only be used on some tested platforms.
|
||||||
for s in sess.opts.debugging_opts.sanitizer {
|
for s in sess.opts.debugging_opts.sanitizer {
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
||||||
// handle normalization within binders because
|
// handle normalization within binders because
|
||||||
// otherwise we wind up a need to normalize when doing
|
// otherwise we wind up a need to normalize when doing
|
||||||
// trait matching (since you can have a trait
|
// trait matching (since you can have a trait
|
||||||
// obligation like `for<'a> T::B : Fn(&'a int)`), but
|
// obligation like `for<'a> T::B: Fn(&'a i32)`), but
|
||||||
// we can't normalize with bound regions in scope. So
|
// we can't normalize with bound regions in scope. So
|
||||||
// far now we just ignore binders but only normalize
|
// far now we just ignore binders but only normalize
|
||||||
// if all bound regions are gone (and then we still
|
// if all bound regions are gone (and then we still
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
// handle normalization within binders because
|
// handle normalization within binders because
|
||||||
// otherwise we wind up a need to normalize when doing
|
// otherwise we wind up a need to normalize when doing
|
||||||
// trait matching (since you can have a trait
|
// trait matching (since you can have a trait
|
||||||
// obligation like `for<'a> T::B : Fn(&'a int)`), but
|
// obligation like `for<'a> T::B: Fn(&'a i32)`), but
|
||||||
// we can't normalize with bound regions in scope. So
|
// we can't normalize with bound regions in scope. So
|
||||||
// far now we just ignore binders but only normalize
|
// far now we just ignore binders but only normalize
|
||||||
// if all bound regions are gone (and then we still
|
// if all bound regions are gone (and then we still
|
||||||
|
|
|
||||||
|
|
@ -553,14 +553,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
///
|
///
|
||||||
/// Here is an example. Imagine we have a closure expression
|
/// Here is an example. Imagine we have a closure expression
|
||||||
/// and we desugared it so that the type of the expression is
|
/// and we desugared it so that the type of the expression is
|
||||||
/// `Closure`, and `Closure` expects an int as argument. Then it
|
/// `Closure`, and `Closure` expects `i32` as argument. Then it
|
||||||
/// is "as if" the compiler generated this impl:
|
/// is "as if" the compiler generated this impl:
|
||||||
///
|
///
|
||||||
/// impl Fn(int) for Closure { ... }
|
/// impl Fn(i32) for Closure { ... }
|
||||||
///
|
///
|
||||||
/// Now imagine our obligation is `Fn(usize) for Closure`. So far
|
/// Now imagine our obligation is `Closure: Fn(usize)`. So far
|
||||||
/// we have matched the self type `Closure`. At this point we'll
|
/// we have matched the self type `Closure`. At this point we'll
|
||||||
/// compare the `int` to `usize` and generate an error.
|
/// compare the `i32` to `usize` and generate an error.
|
||||||
///
|
///
|
||||||
/// Note that this checking occurs *after* the impl has selected,
|
/// Note that this checking occurs *after* the impl has selected,
|
||||||
/// because these output type parameters should not affect the
|
/// because these output type parameters should not affect the
|
||||||
|
|
|
||||||
|
|
@ -1754,27 +1754,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
) -> Vec<PredicateObligation<'tcx>> {
|
) -> Vec<PredicateObligation<'tcx>> {
|
||||||
// Because the types were potentially derived from
|
// Because the types were potentially derived from
|
||||||
// higher-ranked obligations they may reference late-bound
|
// higher-ranked obligations they may reference late-bound
|
||||||
// regions. For example, `for<'a> Foo<&'a int> : Copy` would
|
// regions. For example, `for<'a> Foo<&'a i32> : Copy` would
|
||||||
// yield a type like `for<'a> &'a int`. In general, we
|
// yield a type like `for<'a> &'a i32`. In general, we
|
||||||
// maintain the invariant that we never manipulate bound
|
// maintain the invariant that we never manipulate bound
|
||||||
// regions, so we have to process these bound regions somehow.
|
// regions, so we have to process these bound regions somehow.
|
||||||
//
|
//
|
||||||
// The strategy is to:
|
// The strategy is to:
|
||||||
//
|
//
|
||||||
// 1. Instantiate those regions to placeholder regions (e.g.,
|
// 1. Instantiate those regions to placeholder regions (e.g.,
|
||||||
// `for<'a> &'a int` becomes `&0 int`.
|
// `for<'a> &'a i32` becomes `&0 i32`.
|
||||||
// 2. Produce something like `&'0 int : Copy`
|
// 2. Produce something like `&'0 i32 : Copy`
|
||||||
// 3. Re-bind the regions back to `for<'a> &'a int : Copy`
|
// 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`
|
||||||
|
|
||||||
types
|
types
|
||||||
.skip_binder()
|
.skip_binder() // binder moved -\
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|ty| {
|
.flat_map(|ty| {
|
||||||
// binder moved -\
|
|
||||||
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
|
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
|
||||||
|
|
||||||
self.infcx.commit_unconditionally(|_| {
|
self.infcx.commit_unconditionally(|_| {
|
||||||
let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
|
let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
|
||||||
let Normalized { value: normalized_ty, mut obligations } =
|
let Normalized { value: normalized_ty, mut obligations } =
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
project::normalize_with_depth(
|
project::normalize_with_depth(
|
||||||
|
|
@ -1782,10 +1781,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
param_env,
|
param_env,
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
recursion_depth,
|
recursion_depth,
|
||||||
&skol_ty,
|
&placeholder_ty,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let skol_obligation = predicate_for_trait_def(
|
let placeholder_obligation = predicate_for_trait_def(
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
param_env,
|
param_env,
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
|
|
@ -1794,7 +1793,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
normalized_ty,
|
normalized_ty,
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
obligations.push(skol_obligation);
|
obligations.push(placeholder_obligation);
|
||||||
obligations
|
obligations
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -1844,9 +1843,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (skol_obligation, placeholder_map) =
|
let (placeholder_obligation, placeholder_map) =
|
||||||
self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
|
self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
|
||||||
let skol_obligation_trait_ref = skol_obligation.trait_ref;
|
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
|
||||||
|
|
||||||
let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
|
let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
|
||||||
|
|
||||||
|
|
@ -1865,14 +1864,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"match_impl(impl_def_id={:?}, obligation={:?}, \
|
"match_impl(impl_def_id={:?}, obligation={:?}, \
|
||||||
impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
|
impl_trait_ref={:?}, placeholder_obligation_trait_ref={:?})",
|
||||||
impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref
|
impl_def_id, obligation, impl_trait_ref, placeholder_obligation_trait_ref
|
||||||
);
|
);
|
||||||
|
|
||||||
let InferOk { obligations, .. } = self
|
let InferOk { obligations, .. } = self
|
||||||
.infcx
|
.infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.eq(skol_obligation_trait_ref, impl_trait_ref)
|
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
|
||||||
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
|
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
|
||||||
nested_obligations.extend(obligations);
|
nested_obligations.extend(obligations);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
|
||||||
|
|
||||||
// We determine whether there's a subset relationship by:
|
// We determine whether there's a subset relationship by:
|
||||||
//
|
//
|
||||||
// - skolemizing impl1,
|
// - replacing bound vars with placeholders in impl1,
|
||||||
// - assuming the where clauses for impl1,
|
// - assuming the where clauses for impl1,
|
||||||
// - instantiating impl2 with fresh inference variables,
|
// - instantiating impl2 with fresh inference variables,
|
||||||
// - unifying,
|
// - unifying,
|
||||||
|
|
|
||||||
|
|
@ -1394,13 +1394,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
// That is, consider this case:
|
// That is, consider this case:
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
// trait SubTrait: SuperTrait<int> { }
|
// trait SubTrait: SuperTrait<i32> { }
|
||||||
// trait SuperTrait<A> { type T; }
|
// trait SuperTrait<A> { type T; }
|
||||||
//
|
//
|
||||||
// ... B: SubTrait<T = foo> ...
|
// ... B: SubTrait<T = foo> ...
|
||||||
// ```
|
// ```
|
||||||
//
|
//
|
||||||
// We want to produce `<B as SuperTrait<int>>::T == foo`.
|
// We want to produce `<B as SuperTrait<i32>>::T == foo`.
|
||||||
|
|
||||||
// Find any late-bound regions declared in `ty` that are not
|
// Find any late-bound regions declared in `ty` that are not
|
||||||
// declared in the trait-ref. These are not well-formed.
|
// declared in the trait-ref. These are not well-formed.
|
||||||
|
|
|
||||||
|
|
@ -91,14 +91,14 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
|
|
||||||
// This code is best explained by example. Consider a trait:
|
// This code is best explained by example. Consider a trait:
|
||||||
//
|
//
|
||||||
// trait Trait<'t,T> {
|
// trait Trait<'t, T> {
|
||||||
// fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
|
// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// And an impl:
|
// And an impl:
|
||||||
//
|
//
|
||||||
// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
|
// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
|
||||||
// fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
|
// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// We wish to decide if those two method types are compatible.
|
// We wish to decide if those two method types are compatible.
|
||||||
|
|
@ -116,9 +116,9 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
// regions (Note: but only early-bound regions, i.e., those
|
// regions (Note: but only early-bound regions, i.e., those
|
||||||
// declared on the impl or used in type parameter bounds).
|
// declared on the impl or used in type parameter bounds).
|
||||||
//
|
//
|
||||||
// impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
|
// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
|
||||||
//
|
//
|
||||||
// Now we can apply skol_substs to the type of the impl method
|
// Now we can apply placeholder_substs to the type of the impl method
|
||||||
// to yield a new function type in terms of our fresh, placeholder
|
// to yield a new function type in terms of our fresh, placeholder
|
||||||
// types:
|
// types:
|
||||||
//
|
//
|
||||||
|
|
@ -127,11 +127,11 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
// We now want to extract and substitute the type of the *trait*
|
// We now want to extract and substitute the type of the *trait*
|
||||||
// method and compare it. To do so, we must create a compound
|
// method and compare it. To do so, we must create a compound
|
||||||
// substitution by combining trait_to_impl_substs and
|
// substitution by combining trait_to_impl_substs and
|
||||||
// impl_to_skol_substs, and also adding a mapping for the method
|
// impl_to_placeholder_substs, and also adding a mapping for the method
|
||||||
// type parameters. We extend the mapping to also include
|
// type parameters. We extend the mapping to also include
|
||||||
// the method parameters.
|
// the method parameters.
|
||||||
//
|
//
|
||||||
// trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
|
// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
|
||||||
//
|
//
|
||||||
// Applying this to the trait method type yields:
|
// Applying this to the trait method type yields:
|
||||||
//
|
//
|
||||||
|
|
@ -145,20 +145,20 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
// satisfied by the implementation's method.
|
// satisfied by the implementation's method.
|
||||||
//
|
//
|
||||||
// We do this by creating a parameter environment which contains a
|
// We do this by creating a parameter environment which contains a
|
||||||
// substitution corresponding to impl_to_skol_substs. We then build
|
// substitution corresponding to impl_to_placeholder_substs. We then build
|
||||||
// trait_to_skol_substs and use it to convert the predicates contained
|
// trait_to_placeholder_substs and use it to convert the predicates contained
|
||||||
// in the trait_m.generics to the placeholder form.
|
// in the trait_m.generics to the placeholder form.
|
||||||
//
|
//
|
||||||
// Finally we register each of these predicates as an obligation in
|
// Finally we register each of these predicates as an obligation in
|
||||||
// a fresh FulfillmentCtxt, and invoke select_all_or_error.
|
// a fresh FulfillmentCtxt, and invoke select_all_or_error.
|
||||||
|
|
||||||
// Create mapping from impl to placeholder.
|
// Create mapping from impl to placeholder.
|
||||||
let impl_to_skol_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
|
let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
|
||||||
|
|
||||||
// Create mapping from trait to placeholder.
|
// Create mapping from trait to placeholder.
|
||||||
let trait_to_skol_substs =
|
let trait_to_placeholder_substs =
|
||||||
impl_to_skol_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
|
impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
|
||||||
debug!("compare_impl_method: trait_to_skol_substs={:?}", trait_to_skol_substs);
|
debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
|
||||||
|
|
||||||
let impl_m_generics = tcx.generics_of(impl_m.def_id);
|
let impl_m_generics = tcx.generics_of(impl_m.def_id);
|
||||||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||||
|
|
@ -194,7 +194,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
// if all constraints hold.
|
// if all constraints hold.
|
||||||
hybrid_preds
|
hybrid_preds
|
||||||
.predicates
|
.predicates
|
||||||
.extend(trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
|
.extend(trait_m_predicates.instantiate_own(tcx, trait_to_placeholder_substs).predicates);
|
||||||
|
|
||||||
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
|
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
|
||||||
// The key step here is to update the caller_bounds's predicates to be
|
// The key step here is to update the caller_bounds's predicates to be
|
||||||
|
|
@ -220,7 +220,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
|
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
|
|
||||||
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
|
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
|
||||||
let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
|
let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
|
||||||
impl_m_span,
|
impl_m_span,
|
||||||
infer::HigherRankedType,
|
infer::HigherRankedType,
|
||||||
|
|
@ -261,7 +261,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||||
|
|
||||||
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, &tcx.fn_sig(trait_m.def_id));
|
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, &tcx.fn_sig(trait_m.def_id));
|
||||||
let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs);
|
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
|
||||||
let trait_sig =
|
let trait_sig =
|
||||||
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, &trait_sig);
|
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, &trait_sig);
|
||||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig));
|
let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig));
|
||||||
|
|
|
||||||
|
|
@ -1468,7 +1468,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// trait Foo { ... }
|
/// trait Foo { ... }
|
||||||
/// impl Foo for Vec<int> { ... }
|
/// impl Foo for Vec<i32> { ... }
|
||||||
/// impl Foo for Vec<usize> { ... }
|
/// impl Foo for Vec<usize> { ... }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// errors in some cases, such as this one:
|
// errors in some cases, such as this one:
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
// fn foo<'x>(x: &'x int) {
|
// fn foo<'x>(x: &'x i32) {
|
||||||
// let a = 1;
|
// let a = 1;
|
||||||
// let mut z = x;
|
// let mut z = x;
|
||||||
// z = &a;
|
// z = &a;
|
||||||
|
|
@ -220,7 +220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// ```
|
// ```
|
||||||
//
|
//
|
||||||
// The reason we might get an error is that `z` might be
|
// The reason we might get an error is that `z` might be
|
||||||
// assigned a type like `&'x int`, and then we would have
|
// assigned a type like `&'x i32`, and then we would have
|
||||||
// a problem when we try to assign `&a` to `z`, because
|
// a problem when we try to assign `&a` to `z`, because
|
||||||
// the lifetime of `&a` (i.e., the enclosing block) is
|
// the lifetime of `&a` (i.e., the enclosing block) is
|
||||||
// shorter than `'x`.
|
// shorter than `'x`.
|
||||||
|
|
@ -229,11 +229,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// expected type here is whatever type the user wrote, not
|
// expected type here is whatever type the user wrote, not
|
||||||
// the initializer's type. In this case the user wrote
|
// the initializer's type. In this case the user wrote
|
||||||
// nothing, so we are going to create a type variable `Z`.
|
// nothing, so we are going to create a type variable `Z`.
|
||||||
// Then we will assign the type of the initializer (`&'x
|
// Then we will assign the type of the initializer (`&'x i32`)
|
||||||
// int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
|
// as a subtype of `Z`: `&'x i32 <: Z`. And hence we
|
||||||
// will instantiate `Z` as a type `&'0 int` where `'0` is
|
// will instantiate `Z` as a type `&'0 i32` where `'0` is
|
||||||
// a fresh region variable, with the constraint that `'x :
|
// a fresh region variable, with the constraint that `'x : '0`.
|
||||||
// '0`. So basically we're all set.
|
// So basically we're all set.
|
||||||
//
|
//
|
||||||
// Note that there are two tests to check that this remains true
|
// Note that there are two tests to check that this remains true
|
||||||
// (`regions-reassign-{match,let}-bound-pointer.rs`).
|
// (`regions-reassign-{match,let}-bound-pointer.rs`).
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(vec_remove_item)]
|
|
||||||
#![feature(ptr_offset_from)]
|
#![feature(ptr_offset_from)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
|
||||||
|
|
@ -26,18 +26,10 @@ IMAGE_BASE:
|
||||||
.Lxsave_clear:
|
.Lxsave_clear:
|
||||||
.org .+24
|
.org .+24
|
||||||
.Lxsave_mxcsr:
|
.Lxsave_mxcsr:
|
||||||
.int 0
|
.short 0x1f80
|
||||||
|
|
||||||
/* We can store a bunch of data in the gap between MXCSR and the XSAVE header */
|
/* We can store a bunch of data in the gap between MXCSR and the XSAVE header */
|
||||||
|
|
||||||
/* MXCSR initialization value for ABI */
|
|
||||||
.Lmxcsr_init:
|
|
||||||
.int 0x1f80
|
|
||||||
|
|
||||||
/* x87 FPU control word initialization value for ABI */
|
|
||||||
.Lfpucw_init:
|
|
||||||
.int 0x037f
|
|
||||||
|
|
||||||
/* The following symbols point at read-only data that will be filled in by the */
|
/* The following symbols point at read-only data that will be filled in by the */
|
||||||
/* post-linker. */
|
/* post-linker. */
|
||||||
|
|
||||||
|
|
@ -177,13 +169,17 @@ sgx_entry:
|
||||||
jz .Lskip_debug_init
|
jz .Lskip_debug_init
|
||||||
mov %r10,%gs:tcsls_debug_panic_buf_ptr
|
mov %r10,%gs:tcsls_debug_panic_buf_ptr
|
||||||
.Lskip_debug_init:
|
.Lskip_debug_init:
|
||||||
|
/* reset cpu state */
|
||||||
|
mov %rdx, %r10
|
||||||
|
mov $-1, %rax
|
||||||
|
mov $-1, %rdx
|
||||||
|
xrstor .Lxsave_clear(%rip)
|
||||||
|
mov %r10, %rdx
|
||||||
|
|
||||||
/* check if returning from usercall */
|
/* check if returning from usercall */
|
||||||
mov %gs:tcsls_last_rsp,%r11
|
mov %gs:tcsls_last_rsp,%r11
|
||||||
test %r11,%r11
|
test %r11,%r11
|
||||||
jnz .Lusercall_ret
|
jnz .Lusercall_ret
|
||||||
/* reset user state */
|
|
||||||
ldmxcsr .Lmxcsr_init(%rip)
|
|
||||||
fldcw .Lfpucw_init(%rip)
|
|
||||||
/* setup stack */
|
/* setup stack */
|
||||||
mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
|
mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
|
||||||
/* here. This is fixed below under "adjust stack". */
|
/* here. This is fixed below under "adjust stack". */
|
||||||
|
|
|
||||||
|
|
@ -428,6 +428,7 @@ mod tests {
|
||||||
// ignored there.
|
// ignored there.
|
||||||
#[cfg_attr(target_arch = "arm", ignore)]
|
#[cfg_attr(target_arch = "arm", ignore)]
|
||||||
#[cfg_attr(target_arch = "aarch64", ignore)]
|
#[cfg_attr(target_arch = "aarch64", ignore)]
|
||||||
|
#[cfg_attr(target_arch = "riscv64", ignore)]
|
||||||
fn test_process_mask() {
|
fn test_process_mask() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Test to make sure that a signal mask does not get inherited.
|
// Test to make sure that a signal mask does not get inherited.
|
||||||
|
|
|
||||||
|
|
@ -811,11 +811,11 @@ mod tests {
|
||||||
|
|
||||||
// Right now for CI this test is run in an emulator, and apparently the
|
// Right now for CI this test is run in an emulator, and apparently the
|
||||||
// aarch64 emulator's sense of time is that we're still living in the
|
// aarch64 emulator's sense of time is that we're still living in the
|
||||||
// 70s.
|
// 70s. This is also true for riscv (also qemu)
|
||||||
//
|
//
|
||||||
// Otherwise let's assume that we're all running computers later than
|
// Otherwise let's assume that we're all running computers later than
|
||||||
// 2000.
|
// 2000.
|
||||||
if !cfg!(target_arch = "aarch64") {
|
if !cfg!(target_arch = "aarch64") && !cfg!(target_arch = "riscv64") {
|
||||||
assert!(a > thirty_years);
|
assert!(a > thirty_years);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// compile-flags: -Z control_flow_guard=checks
|
// compile-flags: -Z control-flow-guard=checks
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// compile-flags: -Z control_flow_guard=disabled
|
// compile-flags: -Z control-flow-guard=no
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// compile-flags: -Z control_flow_guard=nochecks
|
// compile-flags: -Z control-flow-guard=nochecks
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
|
|
||||||
9
src/test/ui/const-generics/auxiliary/impl-const.rs
Normal file
9
src/test/ui/const-generics/auxiliary/impl-const.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#![feature(const_generics)]
|
||||||
|
|
||||||
|
pub struct Num<const N: usize>;
|
||||||
|
|
||||||
|
// Braces around const expression causes crash
|
||||||
|
impl Num<{5}> {
|
||||||
|
pub fn five(&self) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// aux-build:impl-const.rs
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(const_generics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
extern crate impl_const;
|
||||||
|
|
||||||
|
use impl_const::*;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let n = Num::<5>;
|
||||||
|
n.five();
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
error: `-Zsanitizer=leak` only works with targets: x86_64-apple-darwin, x86_64-unknown-linux-gnu
|
error: `-Zsanitizer=leak` only works with targets: aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#![crate_name = "compiletest"]
|
#![crate_name = "compiletest"]
|
||||||
#![feature(vec_remove_item)]
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
// The `test` crate is the only unstable feature
|
// The `test` crate is the only unstable feature
|
||||||
// allowed here, just to share similar code.
|
// allowed here, just to share similar code.
|
||||||
|
|
|
||||||
|
|
@ -82,16 +82,22 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||||
("xcore", "xcore"),
|
("xcore", "xcore"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = &[
|
||||||
&["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"];
|
"aarch64-fuchsia",
|
||||||
|
"aarch64-unknown-linux-gnu",
|
||||||
|
"x86_64-apple-darwin",
|
||||||
|
"x86_64-fuchsia",
|
||||||
|
"x86_64-unknown-linux-gnu",
|
||||||
|
];
|
||||||
|
|
||||||
pub const LSAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
pub const LSAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
||||||
&["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
&["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
||||||
|
|
||||||
pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] = &["x86_64-unknown-linux-gnu"];
|
pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
||||||
|
&["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"];
|
||||||
|
|
||||||
pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
||||||
&["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
&["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
||||||
|
|
||||||
pub fn matches_os(triple: &str, name: &str) -> bool {
|
pub fn matches_os(triple: &str, name: &str) -> bool {
|
||||||
// For the wasm32 bare target we ignore anything also ignored on emscripten
|
// For the wasm32 bare target we ignore anything also ignored on emscripten
|
||||||
|
|
|
||||||
|
|
@ -107,13 +107,23 @@ fn start_android_emulator(server: &Path) {
|
||||||
Command::new("adb").arg("shell").arg("/data/tmp/testd").spawn().unwrap();
|
Command::new("adb").arg("shell").arg("/data/tmp/testd").spawn().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path) {
|
fn prepare_rootfs(target: &str, rootfs: &Path, server: &Path, rootfs_img: &Path) {
|
||||||
|
t!(fs::copy(server, rootfs.join("testd")));
|
||||||
|
|
||||||
|
match target {
|
||||||
|
"arm-unknown-linux-gnueabihf" | "aarch64-unknown-linux-gnu" => {
|
||||||
|
prepare_rootfs_cpio(rootfs, rootfs_img)
|
||||||
|
}
|
||||||
|
"riscv64gc-unknown-linux-gnu" => prepare_rootfs_ext4(rootfs, rootfs_img),
|
||||||
|
_ => panic!("{} is not supported", target),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_rootfs_cpio(rootfs: &Path, rootfs_img: &Path) {
|
||||||
// Generate a new rootfs image now that we've updated the test server
|
// Generate a new rootfs image now that we've updated the test server
|
||||||
// executable. This is the equivalent of:
|
// executable. This is the equivalent of:
|
||||||
//
|
//
|
||||||
// find $rootfs -print 0 | cpio --null -o --format=newc > rootfs.img
|
// find $rootfs -print 0 | cpio --null -o --format=newc > rootfs.img
|
||||||
t!(fs::copy(server, rootfs.join("testd")));
|
|
||||||
let rootfs_img = tmpdir.join("rootfs.img");
|
|
||||||
let mut cmd = Command::new("cpio");
|
let mut cmd = Command::new("cpio");
|
||||||
cmd.arg("--null")
|
cmd.arg("--null")
|
||||||
.arg("-o")
|
.arg("-o")
|
||||||
|
|
@ -128,6 +138,38 @@ fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path
|
||||||
t!(io::copy(&mut child.stdout.take().unwrap(), &mut t!(File::create(&rootfs_img))));
|
t!(io::copy(&mut child.stdout.take().unwrap(), &mut t!(File::create(&rootfs_img))));
|
||||||
assert!(t!(child.wait()).success());
|
assert!(t!(child.wait()).success());
|
||||||
|
|
||||||
|
fn add_files(w: &mut dyn Write, root: &Path, cur: &Path) {
|
||||||
|
for entry in t!(cur.read_dir()) {
|
||||||
|
let entry = t!(entry);
|
||||||
|
let path = entry.path();
|
||||||
|
let to_print = path.strip_prefix(root).unwrap();
|
||||||
|
t!(write!(w, "{}\u{0}", to_print.to_str().unwrap()));
|
||||||
|
if t!(entry.file_type()).is_dir() {
|
||||||
|
add_files(w, root, &path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_rootfs_ext4(rootfs: &Path, rootfs_img: &Path) {
|
||||||
|
let mut dd = Command::new("dd");
|
||||||
|
dd.arg("if=/dev/zero")
|
||||||
|
.arg(&format!("of={}", rootfs_img.to_string_lossy()))
|
||||||
|
.arg("bs=1M")
|
||||||
|
.arg("count=1024");
|
||||||
|
let mut dd_child = t!(dd.spawn());
|
||||||
|
assert!(t!(dd_child.wait()).success());
|
||||||
|
|
||||||
|
let mut mkfs = Command::new("mkfs.ext4");
|
||||||
|
mkfs.arg("-d").arg(rootfs).arg(rootfs_img);
|
||||||
|
let mut mkfs_child = t!(mkfs.spawn());
|
||||||
|
assert!(t!(mkfs_child.wait()).success());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path) {
|
||||||
|
let rootfs_img = &tmpdir.join("rootfs.img");
|
||||||
|
prepare_rootfs(target, rootfs, server, rootfs_img);
|
||||||
|
|
||||||
// Start up the emulator, in the background
|
// Start up the emulator, in the background
|
||||||
match target {
|
match target {
|
||||||
"arm-unknown-linux-gnueabihf" => {
|
"arm-unknown-linux-gnueabihf" => {
|
||||||
|
|
@ -170,19 +212,30 @@ fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path
|
||||||
.arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00");
|
.arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00");
|
||||||
t!(cmd.spawn());
|
t!(cmd.spawn());
|
||||||
}
|
}
|
||||||
_ => panic!("cannot start emulator for: {}" < target),
|
"riscv64gc-unknown-linux-gnu" => {
|
||||||
}
|
let mut cmd = Command::new("qemu-system-riscv64");
|
||||||
|
cmd.arg("-nographic")
|
||||||
fn add_files(w: &mut dyn Write, root: &Path, cur: &Path) {
|
.arg("-machine")
|
||||||
for entry in t!(cur.read_dir()) {
|
.arg("virt")
|
||||||
let entry = t!(entry);
|
.arg("-m")
|
||||||
let path = entry.path();
|
.arg("1024")
|
||||||
let to_print = path.strip_prefix(root).unwrap();
|
.arg("-bios")
|
||||||
t!(write!(w, "{}\u{0}", to_print.to_str().unwrap()));
|
.arg("none")
|
||||||
if t!(entry.file_type()).is_dir() {
|
.arg("-kernel")
|
||||||
add_files(w, root, &path);
|
.arg("/tmp/bbl")
|
||||||
}
|
.arg("-append")
|
||||||
|
.arg("quiet console=ttyS0 root=/dev/vda rw")
|
||||||
|
.arg("-netdev")
|
||||||
|
.arg("user,id=net0,hostfwd=tcp::12345-:12345")
|
||||||
|
.arg("-device")
|
||||||
|
.arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00")
|
||||||
|
.arg("-device")
|
||||||
|
.arg("virtio-blk-device,drive=hd0")
|
||||||
|
.arg("-drive")
|
||||||
|
.arg(&format!("file={},format=raw,id=hd0", &rootfs_img.to_string_lossy()));
|
||||||
|
t!(cmd.spawn());
|
||||||
}
|
}
|
||||||
|
_ => panic!("cannot start emulator for: {}", target),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue