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
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -152,10 +152,6 @@ jobs:
|
||||
- name: dist-x86_64-linux
|
||||
os: ubuntu-latest-xl
|
||||
env: {}
|
||||
- name: dist-x86_64-linux-alt
|
||||
env:
|
||||
IMAGE: dist-x86_64-linux
|
||||
os: ubuntu-latest-xl
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
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
|
||||
// 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.
|
||||
@ -1217,7 +1217,7 @@ impl<'a> Builder<'a> {
|
||||
&& self.config.control_flow_guard
|
||||
&& 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
|
||||
|
@ -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")
|
||||
v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
|
||||
"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",
|
||||
"experimental LLVM targets 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>,
|
||||
channel: &str,
|
||||
) -> 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 {
|
||||
"x86_64-apple-darwin" => {
|
||||
for s in &["asan", "lsan", "tsan"] {
|
||||
result.push(SanitizerRuntime {
|
||||
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),
|
||||
});
|
||||
}
|
||||
"aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
|
||||
"aarch64-unknown-linux-gnu" => {
|
||||
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"])
|
||||
}
|
||||
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
|
||||
"x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
|
||||
"x86_64-unknown-linux-gnu" => {
|
||||
for s in &["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),
|
||||
});
|
||||
}
|
||||
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
|
||||
}
|
||||
"x86_64-fuchsia" => {
|
||||
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),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
struct HashStamp {
|
||||
|
@ -26,8 +26,6 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
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
|
||||
# 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 \
|
||||
--enable-full-tools \
|
||||
--enable-profiler \
|
||||
--enable-sanitizers \
|
||||
--disable-docs
|
||||
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
@ -281,11 +281,6 @@ jobs:
|
||||
- name: dist-x86_64-linux
|
||||
<<: *job-linux-xl
|
||||
|
||||
- name: dist-x86_64-linux-alt
|
||||
env:
|
||||
IMAGE: dist-x86_64-linux
|
||||
<<: *job-linux-xl
|
||||
|
||||
auto:
|
||||
<<: *base-ci-job
|
||||
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 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.
|
||||
|
||||
@ -29,7 +29,7 @@ The CFG checks and metadata can potentially increase binary size and runtime ove
|
||||
|
||||
## 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
|
||||
@ -44,14 +44,14 @@ For example:
|
||||
```cmd
|
||||
rustup toolchain install --force nightly
|
||||
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
|
||||
```
|
||||
|
||||
```PowerShell
|
||||
rustup toolchain install --force nightly
|
||||
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
|
||||
```
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(binary_heap_into_iter_sorted)]
|
||||
#![feature(binary_heap_drain_sorted)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(split_inclusive)]
|
||||
#![feature(binary_heap_retain)]
|
||||
|
||||
|
@ -131,21 +131,6 @@ fn test_extend_ref() {
|
||||
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]
|
||||
fn test_slice_from_mut() {
|
||||
let mut values = vec![1, 2, 3, 4, 5];
|
||||
|
@ -1760,17 +1760,15 @@ impl<T: PartialEq> Vec<T> {
|
||||
impl<T> Vec<T> {
|
||||
/// Removes the first instance of `item` from the vector if the item exists.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(vec_remove_item)]
|
||||
/// let mut vec = vec![1, 2, 3, 1];
|
||||
///
|
||||
/// vec.remove_item(&1);
|
||||
///
|
||||
/// assert_eq!(vec, vec![2, 3, 1]);
|
||||
/// ```
|
||||
/// This method will be removed soon.
|
||||
#[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>
|
||||
where
|
||||
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.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 path = default_tlib.join(&filename);
|
||||
linker.link_whole_rlib(&path);
|
||||
|
@ -1,6 +1,6 @@
|
||||
A `break` statement without a label appeared inside a labeled block.
|
||||
|
||||
Example of erroneous code:
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0695
|
||||
# #![feature(label_break_value)]
|
||||
|
@ -63,14 +63,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
/// placeholder region. This is the first step of checking subtyping
|
||||
/// when higher-ranked things are involved.
|
||||
///
|
||||
/// **Important:** you must call this function from within a snapshot.
|
||||
/// Moreover, before committing the snapshot, you must eventually call
|
||||
/// 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
|
||||
/// **Important:** You have to be careful to not leak these placeholders,
|
||||
/// for more information about how placeholders and HRTBs work, see
|
||||
/// the [rustc dev guide].
|
||||
///
|
||||
/// [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(),
|
||||
"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".
|
||||
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)]
|
||||
@ -357,9 +349,6 @@ impl<'tcx> RegionConstraintStorage<'tcx> {
|
||||
|
||||
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
|
||||
match undo_entry {
|
||||
Purged => {
|
||||
// nothing to do here
|
||||
}
|
||||
AddVar(vid) => {
|
||||
self.var_infos.pop().unwrap();
|
||||
assert_eq!(self.var_infos.len(), vid.index() as usize);
|
||||
@ -488,62 +477,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
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>) {
|
||||
// cannot add constraints once regions are resolved
|
||||
debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
|
||||
|
@ -198,10 +198,6 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
|
||||
assert!(self.logs.len() >= snapshot.undo_len);
|
||||
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> {
|
||||
|
@ -29,10 +29,10 @@ crate use self::util::elaborate_predicates;
|
||||
|
||||
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
|
||||
/// 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
|
||||
/// scope. The eventual result is usually a `Selection` (defined below).
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -63,11 +63,11 @@ impl PredicateSet<'tcx> {
|
||||
fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
|
||||
// We have to be careful here because we want
|
||||
//
|
||||
// for<'a> Foo<&'a int>
|
||||
// for<'a> Foo<&'a i32>
|
||||
//
|
||||
// and
|
||||
//
|
||||
// for<'b> Foo<&'b int>
|
||||
// for<'b> Foo<&'b i32>
|
||||
//
|
||||
// to be considered equivalent. So normalize all late-bound
|
||||
// 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!(borrowck, String::from("other"));
|
||||
untracked!(borrowck_stats, true);
|
||||
untracked!(control_flow_guard, CFGuard::Checks);
|
||||
untracked!(deduplicate_diagnostics, true);
|
||||
untracked!(dep_tasks, true);
|
||||
untracked!(dont_buffer_diagnostics, true);
|
||||
@ -539,6 +538,7 @@ fn test_debugging_options_tracking_hash() {
|
||||
tracked!(binary_dep_depinfo, true);
|
||||
tracked!(chalk, true);
|
||||
tracked!(codegen_backend, Some("abc".to_string()));
|
||||
tracked!(control_flow_guard, CFGuard::Checks);
|
||||
tracked!(crate_attr, vec!["abc".to_string()]);
|
||||
tracked!(debug_macros, true);
|
||||
tracked!(dep_info_omit_d_target, true);
|
||||
|
@ -565,6 +565,7 @@ impl MetadataBlob {
|
||||
impl EntryKind {
|
||||
fn def_kind(&self) -> DefKind {
|
||||
match *self {
|
||||
EntryKind::AnonConst(..) => DefKind::AnonConst,
|
||||
EntryKind::Const(..) => DefKind::Const,
|
||||
EntryKind::AssocConst(..) => DefKind::AssocConst,
|
||||
EntryKind::ImmStatic
|
||||
@ -1121,7 +1122,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
|
||||
fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs {
|
||||
match self.kind(id) {
|
||||
EntryKind::Const(qualif, _)
|
||||
EntryKind::AnonConst(qualif, _)
|
||||
| EntryKind::Const(qualif, _)
|
||||
| EntryKind::AssocConst(
|
||||
AssocContainer::ImplDefault
|
||||
| AssocContainer::ImplFinal
|
||||
@ -1340,7 +1342,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
|
||||
fn get_rendered_const(&self, id: DefIndex) -> String {
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
|
@ -1358,7 +1358,7 @@ impl EncodeContext<'tcx> {
|
||||
let const_data = self.encode_rendered_const_for_body(body_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.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
|
||||
self.encode_item_type(def_id.to_def_id());
|
||||
|
@ -281,6 +281,7 @@ define_tables! {
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
enum EntryKind {
|
||||
AnonConst(mir::ConstQualifs, Lazy<RenderedConst>),
|
||||
Const(mir::ConstQualifs, Lazy<RenderedConst>),
|
||||
ImmStatic,
|
||||
MutStatic,
|
||||
|
@ -45,7 +45,6 @@
|
||||
#![feature(min_specialization)]
|
||||
#![feature(track_caller)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(test)]
|
||||
#![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 Box<T> { ... } // Impl_2
|
||||
/// impl Clone for int { ... } // Impl_3
|
||||
/// impl Clone for i32 { ... } // Impl_3
|
||||
///
|
||||
/// fn foo<T:Clone>(concrete: Option<Box<int>>,
|
||||
/// param: T,
|
||||
/// mixed: Option<T>) {
|
||||
/// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
|
||||
/// // Case A: Vtable points at a specific impl. Only possible when
|
||||
/// // 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
|
||||
/// // type is concretely known. If the impl itself has bounded
|
||||
/// // type parameters, ImplSource will carry resolutions for those as well:
|
||||
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
|
||||
/// // Case A: ImplSource points at a specific impl. Only possible when
|
||||
/// // type is concretely known. If the impl itself has bounded
|
||||
/// // type parameters, ImplSource will carry resolutions for those as well:
|
||||
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
|
||||
///
|
||||
/// // Case B: ImplSource must be provided by caller. This applies when
|
||||
/// // type is a type parameter.
|
||||
/// param.clone(); // ImplSourceParam
|
||||
/// // Case B: ImplSource must be provided by caller. This applies when
|
||||
/// // type is a type parameter.
|
||||
/// param.clone(); // ImplSourceParam
|
||||
///
|
||||
/// // Case C: A mix of cases A and B.
|
||||
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
|
||||
/// // Case C: A mix of cases A and B.
|
||||
/// mixed.clone(); // ImplSource(Impl_1, [ImplSourceParam])
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
@ -599,12 +599,12 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
|
||||
///
|
||||
/// ```
|
||||
/// 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
|
||||
///
|
||||
/// for<'a> fn(fn(&'a int))
|
||||
/// for<'a> fn(fn(&'a i32))
|
||||
/// ^~ ^~ ^~~
|
||||
/// | | |
|
||||
/// | | 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
|
||||
/// 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
|
||||
/// 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
|
||||
/// 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 MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>)
|
||||
/// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>)
|
||||
/// ```
|
||||
///
|
||||
/// 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 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
|
||||
/// 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 {
|
||||
|
@ -22,13 +22,13 @@ impl<'tcx> TypeWalker<'tcx> {
|
||||
/// Skips the subtree corresponding to the last type
|
||||
/// 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 = ...;
|
||||
/// iter.next(); // yields Foo
|
||||
/// iter.next(); // yields Bar<int>
|
||||
/// iter.skip_current_subtree(); // skips int
|
||||
/// iter.next(); // yields Bar<i32>
|
||||
/// iter.skip_current_subtree(); // skips i32
|
||||
/// iter.next(); // yields usize
|
||||
/// ```
|
||||
pub fn skip_current_subtree(&mut self) {
|
||||
|
@ -6,7 +6,6 @@
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(vec_remove_item)]
|
||||
|
||||
#[macro_use]
|
||||
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
|
||||
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
|
||||
|
@ -103,7 +103,7 @@ pub enum Strip {
|
||||
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)]
|
||||
pub enum CFGuard {
|
||||
/// 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_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_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_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
|
||||
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 {
|
||||
match v {
|
||||
Some("disabled") => *slot = CFGuard::Disabled,
|
||||
Some("nochecks") => *slot = CFGuard::NoChecks,
|
||||
Some("checks") => *slot = CFGuard::Checks,
|
||||
_ => return false,
|
||||
if v.is_some() {
|
||||
let mut bool_arg = None;
|
||||
if parse_opt_bool(&mut bool_arg, v) {
|
||||
*slot = if bool_arg.unwrap() {
|
||||
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
|
||||
}
|
||||
|
||||
@ -796,8 +809,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"enable the experimental Chalk-based trait solving engine"),
|
||||
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||
"the backend to use"),
|
||||
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [UNTRACKED],
|
||||
"use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"),
|
||||
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
|
||||
"use Windows Control Flow Guard (default: no)"),
|
||||
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
|
||||
"inject the given attribute in the crate"),
|
||||
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] =
|
||||
&["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"];
|
||||
const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
||||
const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
|
||||
const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
|
||||
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
|
||||
"aarch64-fuchsia",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"x86_64-apple-darwin",
|
||||
"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.
|
||||
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
|
||||
// otherwise we wind up a need to normalize when doing
|
||||
// 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
|
||||
// far now we just ignore binders but only normalize
|
||||
// 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
|
||||
// otherwise we wind up a need to normalize when doing
|
||||
// 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
|
||||
// far now we just ignore binders but only normalize
|
||||
// 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
|
||||
/// 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:
|
||||
///
|
||||
/// 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
|
||||
/// 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,
|
||||
/// because these output type parameters should not affect the
|
||||
|
@ -1754,27 +1754,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> Vec<PredicateObligation<'tcx>> {
|
||||
// Because the types were potentially derived from
|
||||
// higher-ranked obligations they may reference late-bound
|
||||
// regions. For example, `for<'a> Foo<&'a int> : Copy` would
|
||||
// yield a type like `for<'a> &'a int`. In general, we
|
||||
// regions. For example, `for<'a> Foo<&'a i32> : Copy` would
|
||||
// yield a type like `for<'a> &'a i32`. In general, we
|
||||
// maintain the invariant that we never manipulate bound
|
||||
// regions, so we have to process these bound regions somehow.
|
||||
//
|
||||
// The strategy is to:
|
||||
//
|
||||
// 1. Instantiate those regions to placeholder regions (e.g.,
|
||||
// `for<'a> &'a int` becomes `&0 int`.
|
||||
// 2. Produce something like `&'0 int : Copy`
|
||||
// 3. Re-bind the regions back to `for<'a> &'a int : Copy`
|
||||
// `for<'a> &'a i32` becomes `&0 i32`.
|
||||
// 2. Produce something like `&'0 i32 : Copy`
|
||||
// 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`
|
||||
|
||||
types
|
||||
.skip_binder()
|
||||
.skip_binder() // binder moved -\
|
||||
.iter()
|
||||
.flat_map(|ty| {
|
||||
// binder moved -\
|
||||
let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
|
||||
|
||||
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 } =
|
||||
ensure_sufficient_stack(|| {
|
||||
project::normalize_with_depth(
|
||||
@ -1782,10 +1781,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
param_env,
|
||||
cause.clone(),
|
||||
recursion_depth,
|
||||
&skol_ty,
|
||||
&placeholder_ty,
|
||||
)
|
||||
});
|
||||
let skol_obligation = predicate_for_trait_def(
|
||||
let placeholder_obligation = predicate_for_trait_def(
|
||||
self.tcx(),
|
||||
param_env,
|
||||
cause.clone(),
|
||||
@ -1794,7 +1793,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
normalized_ty,
|
||||
&[],
|
||||
);
|
||||
obligations.push(skol_obligation);
|
||||
obligations.push(placeholder_obligation);
|
||||
obligations
|
||||
})
|
||||
})
|
||||
@ -1844,9 +1843,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let (skol_obligation, placeholder_map) =
|
||||
let (placeholder_obligation, placeholder_map) =
|
||||
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);
|
||||
|
||||
@ -1865,14 +1864,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
debug!(
|
||||
"match_impl(impl_def_id={:?}, obligation={:?}, \
|
||||
impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
|
||||
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, placeholder_obligation_trait_ref
|
||||
);
|
||||
|
||||
let InferOk { obligations, .. } = self
|
||||
.infcx
|
||||
.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))?;
|
||||
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:
|
||||
//
|
||||
// - skolemizing impl1,
|
||||
// - replacing bound vars with placeholders in impl1,
|
||||
// - assuming the where clauses for impl1,
|
||||
// - instantiating impl2 with fresh inference variables,
|
||||
// - unifying,
|
||||
|
@ -1394,13 +1394,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// That is, consider this case:
|
||||
//
|
||||
// ```
|
||||
// trait SubTrait: SuperTrait<int> { }
|
||||
// trait SubTrait: SuperTrait<i32> { }
|
||||
// trait SuperTrait<A> { type T; }
|
||||
//
|
||||
// ... 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
|
||||
// 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:
|
||||
//
|
||||
// trait Trait<'t,T> {
|
||||
// fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
|
||||
// trait Trait<'t, T> {
|
||||
// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
|
||||
// }
|
||||
//
|
||||
// And an impl:
|
||||
//
|
||||
// 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.
|
||||
@ -116,9 +116,9 @@ fn compare_predicate_entailment<'tcx>(
|
||||
// regions (Note: but only early-bound regions, i.e., those
|
||||
// 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
|
||||
// types:
|
||||
//
|
||||
@ -127,11 +127,11 @@ fn compare_predicate_entailment<'tcx>(
|
||||
// We now want to extract and substitute the type of the *trait*
|
||||
// method and compare it. To do so, we must create a compound
|
||||
// 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
|
||||
// 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:
|
||||
//
|
||||
@ -145,20 +145,20 @@ fn compare_predicate_entailment<'tcx>(
|
||||
// satisfied by the implementation's method.
|
||||
//
|
||||
// We do this by creating a parameter environment which contains a
|
||||
// substitution corresponding to impl_to_skol_substs. We then build
|
||||
// trait_to_skol_substs and use it to convert the predicates contained
|
||||
// substitution corresponding to impl_to_placeholder_substs. We then build
|
||||
// trait_to_placeholder_substs and use it to convert the predicates contained
|
||||
// in the trait_m.generics to the placeholder form.
|
||||
//
|
||||
// Finally we register each of these predicates as an obligation in
|
||||
// a fresh FulfillmentCtxt, and invoke select_all_or_error.
|
||||
|
||||
// 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.
|
||||
let trait_to_skol_substs =
|
||||
impl_to_skol_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
|
||||
debug!("compare_impl_method: trait_to_skol_substs={:?}", trait_to_skol_substs);
|
||||
let trait_to_placeholder_substs =
|
||||
impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_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 trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
@ -194,7 +194,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||
// if all constraints hold.
|
||||
hybrid_preds
|
||||
.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.
|
||||
// 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 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(
|
||||
impl_m_span,
|
||||
infer::HigherRankedType,
|
||||
@ -261,7 +261,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||
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 = trait_sig.subst(tcx, trait_to_skol_substs);
|
||||
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
|
||||
let 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));
|
||||
|
@ -1468,7 +1468,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
///
|
||||
/// ```
|
||||
/// trait Foo { ... }
|
||||
/// impl Foo for Vec<int> { ... }
|
||||
/// impl Foo for Vec<i32> { ... }
|
||||
/// impl Foo for Vec<usize> { ... }
|
||||
/// ```
|
||||
///
|
||||
|
@ -212,7 +212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// errors in some cases, such as this one:
|
||||
//
|
||||
// ```
|
||||
// fn foo<'x>(x: &'x int) {
|
||||
// fn foo<'x>(x: &'x i32) {
|
||||
// let a = 1;
|
||||
// let mut z = x;
|
||||
// z = &a;
|
||||
@ -220,7 +220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// ```
|
||||
//
|
||||
// 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
|
||||
// the lifetime of `&a` (i.e., the enclosing block) is
|
||||
// shorter than `'x`.
|
||||
@ -229,11 +229,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// expected type here is whatever type the user wrote, not
|
||||
// the initializer's type. In this case the user wrote
|
||||
// nothing, so we are going to create a type variable `Z`.
|
||||
// Then we will assign the type of the initializer (`&'x
|
||||
// int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
|
||||
// will instantiate `Z` as a type `&'0 int` where `'0` is
|
||||
// a fresh region variable, with the constraint that `'x :
|
||||
// '0`. So basically we're all set.
|
||||
// Then we will assign the type of the initializer (`&'x i32`)
|
||||
// as a subtype of `Z`: `&'x i32 <: Z`. And hence we
|
||||
// will instantiate `Z` as a type `&'0 i32` where `'0` is
|
||||
// a fresh region variable, with the constraint that `'x : '0`.
|
||||
// So basically we're all set.
|
||||
//
|
||||
// Note that there are two tests to check that this remains true
|
||||
// (`regions-reassign-{match,let}-bound-pointer.rs`).
|
||||
|
@ -9,7 +9,6 @@
|
||||
#![feature(nll)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(test)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(ptr_offset_from)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(never_type)]
|
||||
|
@ -26,18 +26,10 @@ IMAGE_BASE:
|
||||
.Lxsave_clear:
|
||||
.org .+24
|
||||
.Lxsave_mxcsr:
|
||||
.int 0
|
||||
.short 0x1f80
|
||||
|
||||
/* 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 */
|
||||
/* post-linker. */
|
||||
|
||||
@ -177,13 +169,17 @@ sgx_entry:
|
||||
jz .Lskip_debug_init
|
||||
mov %r10,%gs:tcsls_debug_panic_buf_ptr
|
||||
.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 */
|
||||
mov %gs:tcsls_last_rsp,%r11
|
||||
test %r11,%r11
|
||||
jnz .Lusercall_ret
|
||||
/* reset user state */
|
||||
ldmxcsr .Lmxcsr_init(%rip)
|
||||
fldcw .Lfpucw_init(%rip)
|
||||
/* setup stack */
|
||||
mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
|
||||
/* here. This is fixed below under "adjust stack". */
|
||||
|
@ -428,6 +428,7 @@ mod tests {
|
||||
// ignored there.
|
||||
#[cfg_attr(target_arch = "arm", ignore)]
|
||||
#[cfg_attr(target_arch = "aarch64", ignore)]
|
||||
#[cfg_attr(target_arch = "riscv64", ignore)]
|
||||
fn test_process_mask() {
|
||||
unsafe {
|
||||
// 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
|
||||
// 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
|
||||
// 2000.
|
||||
if !cfg!(target_arch = "aarch64") {
|
||||
if !cfg!(target_arch = "aarch64") && !cfg!(target_arch = "riscv64") {
|
||||
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"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -Z control_flow_guard=disabled
|
||||
// compile-flags: -Z control-flow-guard=no
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -Z control_flow_guard=nochecks
|
||||
// compile-flags: -Z control-flow-guard=nochecks
|
||||
|
||||
#![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
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![crate_name = "compiletest"]
|
||||
#![feature(vec_remove_item)]
|
||||
#![deny(warnings)]
|
||||
// The `test` crate is the only unstable feature
|
||||
// allowed here, just to share similar code.
|
||||
|
@ -82,16 +82,22 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
|
||||
("xcore", "xcore"),
|
||||
];
|
||||
|
||||
pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] =
|
||||
&["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"];
|
||||
pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = &[
|
||||
"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] =
|
||||
&["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] =
|
||||
&["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 {
|
||||
// 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();
|
||||
}
|
||||
|
||||
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
|
||||
// executable. This is the equivalent of:
|
||||
//
|
||||
// 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");
|
||||
cmd.arg("--null")
|
||||
.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))));
|
||||
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
|
||||
match target {
|
||||
"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");
|
||||
t!(cmd.spawn());
|
||||
}
|
||||
_ => panic!("cannot start emulator for: {}" < target),
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
"riscv64gc-unknown-linux-gnu" => {
|
||||
let mut cmd = Command::new("qemu-system-riscv64");
|
||||
cmd.arg("-nographic")
|
||||
.arg("-machine")
|
||||
.arg("virt")
|
||||
.arg("-m")
|
||||
.arg("1024")
|
||||
.arg("-bios")
|
||||
.arg("none")
|
||||
.arg("-kernel")
|
||||
.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…
x
Reference in New Issue
Block a user