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:
bors 2020-06-20 19:14:52 +00:00
commit f455e46eae
57 changed files with 545 additions and 299 deletions

View File

@ -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:

View File

@ -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

View File

@ -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")

View File

@ -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 {

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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
```

View File

@ -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)]

View File

@ -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];

View File

@ -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>,

View File

@ -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);

View File

@ -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)]

View File

@ -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

View File

@ -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(..) => {}
}
}
}

View File

@ -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);

View File

@ -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> {

View File

@ -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)]

View File

@ -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.

View File

@ -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);

View File

@ -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!(),
}
}

View File

@ -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());

View File

@ -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,

View File

@ -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)]

View File

@ -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])
/// }
/// ```
///

View File

@ -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 {

View File

@ -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) {

View File

@ -6,7 +6,6 @@
#![feature(hash_raw_entry)]
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]
#![feature(vec_remove_item)]
#[macro_use]
extern crate log;

View File

@ -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

View File

@ -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.

View File

@ -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],

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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.

View File

@ -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));

View File

@ -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> { ... }
/// ```
///

View File

@ -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`).

View File

@ -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)]

View File

@ -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". */

View File

@ -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.

View File

@ -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);
}

View File

@ -1,4 +1,4 @@
// compile-flags: -Z control_flow_guard=checks
// compile-flags: -Z control-flow-guard=checks
#![crate_type = "lib"]

View File

@ -1,4 +1,4 @@
// compile-flags: -Z control_flow_guard=disabled
// compile-flags: -Z control-flow-guard=no
#![crate_type = "lib"]

View File

@ -1,4 +1,4 @@
// compile-flags: -Z control_flow_guard=nochecks
// compile-flags: -Z control-flow-guard=nochecks
#![crate_type = "lib"]

View 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) {
}
}

View File

@ -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();
}

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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),
}
}