Auto merge of #64545 - nnethercote:ObligForest-more, r=nmatsakis
More `ObligationForest` improvements
Following on from #64500, these commits alsomake the code both nicer and faster.
r? @nikomatsakis
diff --git a/Cargo.lock b/Cargo.lock
index b717460..f52e973 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -201,9 +201,7 @@
name = "build-manifest"
version = "0.1.0"
dependencies = [
- "reqwest",
"serde",
- "serde_json",
"toml",
]
@@ -272,6 +270,7 @@
"atty",
"bytesize",
"cargo-test-macro",
+ "cargo-test-support",
"clap",
"core-foundation",
"crates-io",
@@ -288,8 +287,9 @@
"git2",
"git2-curl",
"glob",
- "hex",
+ "hex 0.4.0",
"home",
+ "humantime",
"ignore",
"im-rc",
"jobserver",
@@ -330,6 +330,23 @@
version = "0.1.0"
[[package]]
+name = "cargo-test-support"
+version = "0.1.0"
+dependencies = [
+ "cargo",
+ "cargo-test-macro",
+ "filetime",
+ "flate2",
+ "git2",
+ "glob",
+ "lazy_static 1.3.0",
+ "remove_dir_all",
+ "serde_json",
+ "tar",
+ "url 2.1.0",
+]
+
+[[package]]
name = "cargo_metadata"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -700,7 +717,7 @@
checksum = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
dependencies = [
"commoncrypto",
- "hex",
+ "hex 0.3.2",
"openssl",
"winapi 0.3.6",
]
@@ -1263,6 +1280,12 @@
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
+name = "hex"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e"
+
+[[package]]
name = "home"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2064,7 +2087,7 @@
"directories",
"env_logger",
"getrandom",
- "hex",
+ "hex 0.3.2",
"log",
"num-traits",
"rand 0.7.0",
@@ -3259,6 +3282,7 @@
"serde",
"serde_json",
"smallvec",
+ "url 2.1.0",
"winapi 0.3.6",
]
diff --git a/README.md b/README.md
index 4c2e4ee..96d7e93 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
### Building on *nix
1. Make sure you have installed the dependencies:
- * `g++` 4.7 or later or `clang++` 3.x or later
+ * `g++` 5.1 or later or `clang++` 3.5 or later
* `python` 2.7 (but not 3.x)
* GNU `make` 3.81 or later
* `cmake` 3.4.3 or later
@@ -151,6 +151,17 @@
> python x.py build
```
+### Building rustc with older host toolchains
+It is still possible to build Rust with the older toolchain versions listed below, but only if the
+LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN option is set to true in the config.toml file.
+
+* Clang 3.1
+* Apple Clang 3.1
+* GCC 4.8
+* Visual Studio 2015 (Update 3)
+
+Toolchain versions older than what is listed above cannot be used to build rustc.
+
#### Specifying an ABI
Each specific ABI can also be used from either environment (for example, using
diff --git a/RELEASES.md b/RELEASES.md
index f26f6e6..d634feb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,108 @@
+Version 1.38.0 (2019-09-26)
+==========================
+
+Language
+--------
+- [The `#[global_allocator]` attribute can now be used in submodules.][62735]
+- [The `#[deprecated]` attribute can now be used on macros.][62042]
+
+Compiler
+--------
+- [Added pipelined compilation support to `rustc`.][62766] This will
+ improve compilation times in some cases. For further information please refer
+ to the [_"Evaluating pipelined rustc compilation"_][pipeline-internals] thread.
+- [Added tier 3\* support for the `aarch64-uwp-windows-msvc`, `i686-uwp-windows-gnu`,
+ `i686-uwp-windows-msvc`, `x86_64-uwp-windows-gnu`, and
+ `x86_64-uwp-windows-msvc` targets.][60260]
+- [Added tier 3 support for the `armv7-unknown-linux-gnueabi` and
+ `armv7-unknown-linux-musleabi` targets.][63107]
+- [Added tier 3 support for the `hexagon-unknown-linux-musl` target.][62814]
+- [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+information on Rust's tiered platform support.
+
+Libraries
+---------
+- [`ascii::EscapeDefault` now implements `Clone` and `Display`.][63421]
+- [Derive macros for prelude traits (e.g. `Clone`, `Debug`, `Hash`) are now
+ available at the same path as the trait.][63056] (e.g. The `Clone` derive macro
+ is available at `std::clone::Clone`). This also makes all built-in macros
+ available in `std`/`core` root. e.g. `std::include_bytes!`.
+- [`str::Chars` now implements `Debug`.][63000]
+- [`slice::{concat, connect, join}` now accepts `&[T]` in addition to `&T`.][62528]
+- [`*const T` and `*mut T` now implement `marker::Unpin`.][62583]
+- [`Arc<[T]>` and `Rc<[T]>` now implement `FromIterator<T>`.][61953]
+- [Added euclidean remainder and division operations (`div_euclid`,
+ `rem_euclid`) to all numeric primitives.][61884] Additionally `checked`,
+ `overflowing`, and `wrapping` versions are available for all
+ integer primitives.
+- [`thread::AccessError` now implements `Clone`, `Copy`, `Eq`, `Error`, and
+ `PartialEq`.][61491]
+- [`iter::{StepBy, Peekable, Take}` now implement `DoubleEndedIterator`.][61457]
+
+Stabilized APIs
+---------------
+- [`<*const T>::cast`]
+- [`<*mut T>::cast`]
+- [`Duration::as_secs_f32`]
+- [`Duration::as_secs_f64`]
+- [`Duration::div_duration_f32`]
+- [`Duration::div_duration_f64`]
+- [`Duration::div_f32`]
+- [`Duration::div_f64`]
+- [`Duration::from_secs_f32`]
+- [`Duration::from_secs_f64`]
+- [`Duration::mul_f32`]
+- [`Duration::mul_f64`]
+- [`any::type_name`]
+
+Cargo
+-----
+- [Added pipelined compilation support to `cargo`.][cargo/7143]
+- [You can now pass the `--features` option multiple times to enable
+ multiple features.][cargo/7084]
+
+Misc
+----
+- [`rustc` will now warn about some incorrect uses of
+ `mem::{uninitialized, zeroed}` that are known to cause undefined behaviour.][63346]
+
+[60260]: https://github.com/rust-lang/rust/pull/60260/
+[61457]: https://github.com/rust-lang/rust/pull/61457/
+[61491]: https://github.com/rust-lang/rust/pull/61491/
+[61884]: https://github.com/rust-lang/rust/pull/61884/
+[61953]: https://github.com/rust-lang/rust/pull/61953/
+[62042]: https://github.com/rust-lang/rust/pull/62042/
+[62528]: https://github.com/rust-lang/rust/pull/62528/
+[62583]: https://github.com/rust-lang/rust/pull/62583/
+[62735]: https://github.com/rust-lang/rust/pull/62735/
+[62766]: https://github.com/rust-lang/rust/pull/62766/
+[62784]: https://github.com/rust-lang/rust/pull/62784/
+[62814]: https://github.com/rust-lang/rust/pull/62814/
+[63000]: https://github.com/rust-lang/rust/pull/63000/
+[63056]: https://github.com/rust-lang/rust/pull/63056/
+[63107]: https://github.com/rust-lang/rust/pull/63107/
+[63346]: https://github.com/rust-lang/rust/pull/63346/
+[63421]: https://github.com/rust-lang/rust/pull/63421/
+[cargo/7084]: https://github.com/rust-lang/cargo/pull/7084/
+[cargo/7143]: https://github.com/rust-lang/cargo/pull/7143/
+[`<*const T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
+[`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32
+[`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64
+[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32
+[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64
+[`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32
+[`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64
+[`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32
+[`Duration::from_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f64
+[`Duration::mul_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f32
+[`Duration::mul_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f64
+[`any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
+[forge-platform-support]: https://forge.rust-lang.org/platform-support.html
+[pipeline-internals]: https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199
+
Version 1.37.0 (2019-08-15)
==========================
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index 77c9cda..1656066 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -236,10 +236,16 @@
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
SCRIPT: make ci-subset-1
+ # FIXME(#59637)
+ NO_DEBUG_ASSERTIONS: 1
+ NO_LLVM_ASSERTIONS: 1
i686-msvc-2:
MSYS_BITS: 32
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
SCRIPT: make ci-subset-2
+ # FIXME(#59637)
+ NO_DEBUG_ASSERTIONS: 1
+ NO_LLVM_ASSERTIONS: 1
# MSVC aux tests
x86_64-msvc-aux:
MSYS_BITS: 64
@@ -250,6 +256,9 @@
SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
VCVARS_BAT: vcvars64.bat
+ # FIXME(#59637)
+ NO_DEBUG_ASSERTIONS: 1
+ NO_LLVM_ASSERTIONS: 1
# MSVC tools tests
x86_64-msvc-tools:
MSYS_BITS: 64
diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile
index 2041ba5..517b59c 100644
--- a/src/ci/docker/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/i686-gnu-nopt/Dockerfile
@@ -19,3 +19,6 @@
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
ENV SCRIPT python2.7 ../x.py test
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile
index 17441dd..03db3ba 100644
--- a/src/ci/docker/i686-gnu/Dockerfile
+++ b/src/ci/docker/i686-gnu/Dockerfile
@@ -25,3 +25,6 @@
--exclude src/test/rustdoc-js \
--exclude src/tools/error_index_generator \
--exclude src/tools/linkchecker
+
+# FIXME(#59637) takes too long on CI right now
+ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
diff --git a/src/doc/book b/src/doc/book
index 7ddc464..871416b 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 7ddc46460f09a5cd9bd2a620565bdc20b3315ea9
+Subproject commit 871416b85c1a73717d65d6f4a9ea29e5aef3db0e
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 38b9a76..4374786 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 38b9a76bc8b59ac862663807fc51c9b757337fd6
+Subproject commit 4374786f0b4bf0606b35d5c30a9681f342e5707b
diff --git a/src/doc/reference b/src/doc/reference
index 1944efe..fa5dfb8 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 1944efed35989ba57fa397c0724c4921310311fc
+Subproject commit fa5dfb832ef8a7568e17dabf612f486d641ff4ac
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index e76be6b..67cfbf3 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit e76be6b2dc84c6a992e186157efe29d625e29b94
+Subproject commit 67cfbf31df880728dcf7cb35b15b028ec92caf31
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 6439fa0..ee4be6c 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -49,28 +49,16 @@
intrinsics::unreachable()
}
-/// Signals the processor that it is entering a busy-wait spin-loop.
+/// Emits a machine instruction hinting to the processor that it is running in busy-wait
+/// spin-loop ("spin lock").
///
-/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
-/// power or switching hyper-threads.
-///
-/// This function is different than [`std::thread::yield_now`] which directly yields to the
-/// system's scheduler, whereas `spin_loop` only signals the processor that it is entering a
-/// busy-wait spin-loop without yielding control to the system's scheduler.
-///
-/// Using a busy-wait spin-loop with `spin_loop` is ideally used in situations where a
-/// contended lock is held by another thread executed on a different CPU and where the waiting
-/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
-/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
-/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
-/// before switching to the thread that holds the lock. If the contending lock is held by a thread
-/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
-/// use [`std::thread::yield_now`].
+/// For a discussion of different locking strategies and their trade-offs, see
+/// [`core::sync::atomic::spin_loop_hint`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
-/// [`std::thread::yield_now`]: ../../std/thread/fn.yield_now.html
+/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index d145f22..ecff40a 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -845,21 +845,26 @@
///
/// ```
/// let store = [0, 1, 2, 3];
- /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+ /// let v_orig = store.iter().collect::<Vec<&i32>>();
+ ///
+ /// // clone the vector as we will reuse them later
+ /// let v_clone = v_orig.clone();
///
/// // Using transmute: this is Undefined Behavior, and a bad idea.
/// // However, it is no-copy.
/// let v_transmuted = unsafe {
- /// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
- /// v_orig.clone())
+ /// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
/// };
///
+ /// let v_clone = v_orig.clone();
+ ///
/// // This is the suggested, safe way.
/// // It does copy the entire vector, though, into a new array.
- /// let v_collected = v_orig.clone()
- /// .into_iter()
- /// .map(|r| Some(r))
- /// .collect::<Vec<Option<&i32>>>();
+ /// let v_collected = v_clone.into_iter()
+ /// .map(Some)
+ /// .collect::<Vec<Option<&i32>>>();
+ ///
+ /// let v_clone = v_orig.clone();
///
/// // The no-copy, unsafe way, still using transmute, but not UB.
/// // This is equivalent to the original, but safer, and reuses the
@@ -869,11 +874,12 @@
/// // the original inner type (`&i32`) to the converted inner type
/// // (`Option<&i32>`), so read the nomicon pages linked above.
/// let v_from_raw = unsafe {
- /// Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>,
- /// v_orig.len(),
- /// v_orig.capacity())
+ /// // Ensure the original vector is not dropped.
+ /// let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
+ /// Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
+ /// v_clone.len(),
+ /// v_clone.capacity())
/// };
- /// std::mem::forget(v_orig);
/// ```
///
/// Implementing `split_at_mut`:
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index df1c00c..0cf2ebb 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -2092,11 +2092,14 @@
```
let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(bytes, if cfg!(target_endian = \"big\") {
+assert_eq!(
+ bytes,
+ if cfg!(target_endian = \"big\") {
", $be_bytes, "
} else {
", $le_bytes, "
- });
+ }
+);
```"),
#[stable(feature = "int_to_from_bytes", since = "1.32.0")]
#[rustc_const_unstable(feature = "const_int_conversion")]
@@ -2188,10 +2191,10 @@
```
let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
- ", $be_bytes, "
- } else {
- ", $le_bytes, "
- });
+ ", $be_bytes, "
+} else {
+ ", $le_bytes, "
+});
assert_eq!(value, ", $swap_op, ");
```
@@ -3911,11 +3914,14 @@
```
let bytes = ", $swap_op, stringify!($SelfT), ".to_ne_bytes();
-assert_eq!(bytes, if cfg!(target_endian = \"big\") {
+assert_eq!(
+ bytes,
+ if cfg!(target_endian = \"big\") {
", $be_bytes, "
} else {
", $le_bytes, "
- });
+ }
+);
```"),
#[stable(feature = "int_to_from_bytes", since = "1.32.0")]
#[rustc_const_unstable(feature = "const_int_conversion")]
@@ -4007,10 +4013,10 @@
```
let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"big\") {
- ", $be_bytes, "
- } else {
- ", $le_bytes, "
- });
+ ", $be_bytes, "
+} else {
+ ", $le_bytes, "
+});
assert_eq!(value, ", $swap_op, ");
```
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index be59e83..1dc6d54 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -584,6 +584,27 @@
/// the pointee cannot move after `Pin<Pointer<T>>` got created.
/// "Malicious" implementations of `Pointer::DerefMut` are likewise
/// ruled out by the contract of `Pin::new_unchecked`.
+ ///
+ /// This method is useful when doing multiple calls to functions that consume the pinned type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::pin::Pin;
+ ///
+ /// # struct Type {}
+ /// impl Type {
+ /// fn method(self: Pin<&mut Self>) {
+ /// // do something
+ /// }
+ ///
+ /// fn call_method_twice(mut self: Pin<&mut Self>) {
+ /// // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
+ /// self.as_mut().method();
+ /// self.as_mut().method();
+ /// }
+ /// }
+ /// ```
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index a731115..c9ccef9 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -124,28 +124,31 @@
use crate::hint::spin_loop;
-/// Signals the processor that it is entering a busy-wait spin-loop.
+/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
///
/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
/// power or switching hyper-threads.
///
-/// This function is different than [`std::thread::yield_now`] which directly yields to the
-/// system's scheduler, whereas `spin_loop_hint` only signals the processor that it is entering a
-/// busy-wait spin-loop without yielding control to the system's scheduler.
+/// This function is different from [`std::thread::yield_now`] which directly yields to the
+/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system.
///
-/// Using a busy-wait spin-loop with `spin_loop_hint` is ideally used in situations where a
-/// contended lock is held by another thread executed on a different CPU and where the waiting
-/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
-/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
-/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
-/// before switching to the thread that holds the lock. If the contending lock is held by a thread
-/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
-/// use [`std::thread::yield_now`].
+/// Spin locks can be very efficient for short lock durations because they do not involve context
+/// switches or interaction with the operating system. For long lock durations they become wasteful
+/// however because they use CPU cycles for the entire lock duration, and using a
+/// [`std::sync::Mutex`] is likely the better approach. If actively spinning for a long time is
+/// required, e.g. because code polls a non-blocking API, calling [`std::thread::yield_now`]
+/// or [`std::thread::sleep`] may be the best option.
+///
+/// **Note**: Spin locks are based on the underlying assumption that another thread will release
+/// the lock 'soon'. In order for this to work, that other thread must run on a different CPU or
+/// core (at least potentially). Spin locks do not work efficiently on single CPU / core platforms.
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
+/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html
+/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html
#[inline]
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
pub fn spin_loop_hint() {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 58789a1..48f7fc4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2682,12 +2682,8 @@
bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
}
- fn lower_block_with_stmts(
- &mut self,
- b: &Block,
- targeted_by_break: bool,
- mut stmts: Vec<hir::Stmt>,
- ) -> P<hir::Block> {
+ fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+ let mut stmts = vec![];
let mut expr = None;
for (index, stmt) in b.stmts.iter().enumerate() {
@@ -2712,8 +2708,11 @@
})
}
- fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
- self.lower_block_with_stmts(b, targeted_by_break, vec![])
+ /// Lowers a block directly to an expression, presuming that it
+ /// has no attributes and is not targeted by a `break`.
+ fn lower_block_expr(&mut self, b: &Block) -> hir::Expr {
+ let block = self.lower_block(b, false);
+ self.expr_block(block, ThinVec::new())
}
fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index a46cdab..990728f 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -90,10 +90,7 @@
),
ExprKind::Async(capture_clause, closure_node_id, ref block) => {
self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| {
- this.with_new_scopes(|this| {
- let block = this.lower_block(block, false);
- this.expr_block(block, ThinVec::new())
- })
+ this.with_new_scopes(|this| this.lower_block_expr(block))
})
}
ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
@@ -284,8 +281,7 @@
let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
// Handle then + scrutinee:
- let then_blk = self.lower_block(then, false);
- let then_expr = self.expr_block(then_blk, ThinVec::new());
+ let then_expr = self.lower_block_expr(then);
let (then_pat, scrutinee, desugar) = match cond.node {
// `<pat> => <then>`:
ExprKind::Let(ref pat, ref scrutinee) => {
@@ -335,8 +331,7 @@
};
// Handle then + scrutinee:
- let then_blk = self.lower_block(body, false);
- let then_expr = self.expr_block(then_blk, ThinVec::new());
+ let then_expr = self.lower_block_expr(body);
let (then_pat, scrutinee, desugar, source) = match cond.node {
ExprKind::Let(ref pat, ref scrutinee) => {
// to:
@@ -356,7 +351,7 @@
//
// ```
// 'label: loop {
- // match DropTemps($cond) {
+ // match drop-temps { $cond } {
// true => $body,
// _ => break,
// }
@@ -1310,7 +1305,7 @@
/// `{ let _t = $expr; _t }` but should provide better compile-time performance.
///
/// The drop order can be important in e.g. `if expr { .. }`.
- fn expr_drop_temps(
+ pub(super) fn expr_drop_temps(
&mut self,
span: Span,
expr: P<hir::Expr>,
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 5f82e42..61be40a 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -1071,10 +1071,7 @@
}
fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
- self.lower_fn_body(decl, |this| {
- let body = this.lower_block(body, false);
- this.expr_block(body, ThinVec::new())
- })
+ self.lower_fn_body(decl, |this| this.lower_block_expr(body))
}
pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
@@ -1102,8 +1099,7 @@
// from:
//
// async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
- // async move {
- // }
+ // <body>
// }
//
// into:
@@ -1116,11 +1112,19 @@
// let <pattern> = __arg1;
// let __arg0 = __arg0;
// let <pattern> = __arg0;
+ // drop-temps { <body> } // see comments later in fn for details
// }
// }
//
// If `<pattern>` is a simple ident, then it is lowered to a single
// `let <pattern> = <pattern>;` statement as an optimization.
+ //
+ // Note that the body is embedded in `drop-temps`; an
+ // equivalent desugaring would be `return { <body>
+ // };`. The key point is that we wish to drop all the
+ // let-bound variables and temporaries created in the body
+ // (and its tail expression!) before we drop the
+ // parameters (c.f. rust-lang/rust#64512).
for (index, parameter) in decl.inputs.iter().enumerate() {
let parameter = this.lower_param(parameter);
let span = parameter.pat.span;
@@ -1219,8 +1223,36 @@
let async_expr = this.make_async_expr(
CaptureBy::Value, closure_id, None, body.span,
|this| {
- let body = this.lower_block_with_stmts(body, false, statements);
- this.expr_block(body, ThinVec::new())
+ // Create a block from the user's function body:
+ let user_body = this.lower_block_expr(body);
+
+ // Transform into `drop-temps { <user-body> }`, an expression:
+ let desugared_span = this.mark_span_with_reason(
+ DesugaringKind::Async,
+ user_body.span,
+ None,
+ );
+ let user_body = this.expr_drop_temps(
+ desugared_span,
+ P(user_body),
+ ThinVec::new(),
+ );
+
+ // As noted above, create the final block like
+ //
+ // ```
+ // {
+ // let $param_pattern = $raw_param;
+ // ...
+ // drop-temps { <user-body> }
+ // }
+ // ```
+ let body = this.block_all(
+ desugared_span,
+ statements.into(),
+ Some(P(user_body)),
+ );
+ this.expr_block(P(body), ThinVec::new())
});
(HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new()))
})
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 5dfa0d2..96d40bc 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -97,7 +97,7 @@
self.tag(),
a,
b);
- let origin = Subtype(self.fields.trace.clone());
+ let origin = Subtype(box self.fields.trace.clone());
self.fields.infcx.borrow_region_constraints()
.make_eqregion(origin, a, b);
Ok(a)
diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
index 19bd38b..bfa8353 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -30,7 +30,7 @@
Some(RegionResolutionError::SubSupConflict(
vid,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -50,7 +50,7 @@
Some(RegionResolutionError::SubSupConflict(
vid,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -70,7 +70,7 @@
Some(RegionResolutionError::SubSupConflict(
vid,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -92,7 +92,7 @@
_,
_,
_,
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -108,7 +108,7 @@
)),
Some(RegionResolutionError::ConcreteFailure(
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -125,7 +125,7 @@
)),
Some(RegionResolutionError::ConcreteFailure(
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
@@ -142,7 +142,7 @@
)),
Some(RegionResolutionError::ConcreteFailure(
- SubregionOrigin::Subtype(TypeTrace {
+ SubregionOrigin::Subtype(box TypeTrace {
cause,
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
}),
diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs
index caed428..115ffea 100644
--- a/src/librustc/infer/error_reporting/note.rs
+++ b/src/librustc/infer/error_reporting/note.rs
@@ -138,7 +138,7 @@
sup: Region<'tcx>)
-> DiagnosticBuilder<'tcx> {
match origin {
- infer::Subtype(trace) => {
+ infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, &terr);
self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "...");
@@ -450,7 +450,7 @@
) -> DiagnosticBuilder<'tcx> {
// I can't think how to do better than this right now. -nikomatsakis
match placeholder_origin {
- infer::Subtype(trace) => {
+ infer::Subtype(box trace) => {
let terr = TypeError::RegionsPlaceholderMismatch;
self.report_and_explain_type_error(trace, &terr)
}
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index 2cef521..10e4532 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -57,7 +57,7 @@
a,
b);
- let origin = Subtype(self.fields.trace.clone());
+ let origin = Subtype(box self.fields.trace.clone());
Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
}
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index e20372f..8b64cda 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -57,7 +57,7 @@
a,
b);
- let origin = Subtype(self.fields.trace.clone());
+ let origin = Subtype(box self.fields.trace.clone());
Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
}
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 46a364c..c5712cc 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -254,7 +254,7 @@
#[derive(Clone, Debug)]
pub enum SubregionOrigin<'tcx> {
/// Arose from a subtyping relation
- Subtype(TypeTrace<'tcx>),
+ Subtype(Box<TypeTrace<'tcx>>),
/// Stack-allocated closures cannot outlive innermost loop
/// or function so as to ensure we only require finite stack
@@ -340,6 +340,10 @@
},
}
+// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(SubregionOrigin<'_>, 32);
+
/// Places that type/region parameters can appear.
#[derive(Clone, Copy, Debug)]
pub enum ParameterOrigin {
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index cd1d206..76db55e 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -130,7 +130,7 @@
// FIXME -- we have more fine-grained information available
// from the "cause" field, we could perhaps give more tailored
// error messages.
- let origin = SubregionOrigin::Subtype(self.fields.trace.clone());
+ let origin = SubregionOrigin::Subtype(box self.fields.trace.clone());
self.fields.infcx.borrow_region_constraints()
.make_subregion(origin, a, b);
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index 755cda7..15e6cb6 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -130,9 +130,9 @@
}
}
-impl Allocation<()> {
+impl Allocation<(), ()> {
/// Add Tag and Extra fields
- pub fn retag<T, E>(
+ pub fn with_tags_and_extra<T, E>(
self,
mut tagger: impl FnMut(AllocId) -> T,
extra: E,
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 09c822f..ac99ccd 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -213,6 +213,15 @@
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
}
+impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
+ fn from(err: ErrorHandled) -> Self {
+ match err {
+ ErrorHandled::Reported => err_inval!(ReferencedConstant),
+ ErrorHandled::TooGeneric => err_inval!(TooGeneric),
+ }.into()
+ }
+}
+
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
@@ -313,6 +322,9 @@
}
}
+/// Error information for when the program we executed turned out not to actually be a valid
+/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
+/// where we work on generic code or execution does not have all information available.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context.
@@ -342,6 +354,7 @@
}
}
+/// Error information for when the program caused Undefined Behavior.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum UndefinedBehaviorInfo {
/// Free-form case. Only for errors that are never caught!
@@ -364,12 +377,19 @@
}
}
+/// Error information for when the program did something that might (or might not) be correct
+/// to do according to the Rust spec, but due to limitations in the interpreter, the
+/// operation could not be carried out. These limitations can differ between CTFE and the
+/// Miri engine, e.g., CTFE does not support casting pointers to "real" integers.
+///
+/// Currently, we also use this as fall-back error kind for errors that have not been
+/// categorized yet.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum UnsupportedOpInfo<'tcx> {
/// Free-form case. Only for errors that are never caught!
Unsupported(String),
- // -- Everything below is not classified yet --
+ // -- Everything below is not categorized yet --
FunctionAbiMismatch(Abi, Abi),
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -536,6 +556,8 @@
}
}
+/// Error information for when the program exhausted the resources granted to it
+/// by the interpreter.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum ResourceExhaustionInfo {
/// The stack grew too big.
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 4ebc2e7..c726094 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -462,15 +462,6 @@
no_force
desc { "extract field of const" }
}
-
- /// Produces an absolute path representation of the given type. See also the documentation
- /// on `std::any::type_name`.
- query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
- eval_always
- no_force
- desc { "get absolute path of type" }
- }
-
}
TypeChecking {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 217c887..a54bc05 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -134,7 +134,7 @@
String::new()
};
format!(
- "upstream crates may add new impl of trait `{}`{} \
+ "upstream crates may add a new impl of trait `{}`{} \
in future versions",
trait_desc, self_desc
)
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 5fbfe91..3f3c5ac1 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -15,6 +15,7 @@
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
+use rustc::mir::interpret::GlobalId;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc::hir;
use syntax::ast::{self, FloatTy};
@@ -81,13 +82,14 @@
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
fn codegen_intrinsic_call(
&mut self,
- callee_ty: Ty<'tcx>,
+ instance: ty::Instance<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, &'ll Value>],
llresult: &'ll Value,
span: Span,
) {
let tcx = self.tcx;
+ let callee_ty = instance.ty(tcx);
let (def_id, substs) = match callee_ty.sty {
ty::FnDef(def_id, substs) => (def_id, substs),
@@ -133,10 +135,6 @@
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
self.call(llfn, &[], None)
}
- "size_of" => {
- let tp_ty = substs.type_at(0);
- self.const_usize(self.size_of(tp_ty).bytes())
- }
"va_start" => {
self.va_start(args[0].immediate())
}
@@ -188,10 +186,6 @@
self.const_usize(self.size_of(tp_ty).bytes())
}
}
- "min_align_of" => {
- let tp_ty = substs.type_at(0);
- self.const_usize(self.align_of(tp_ty).bytes())
- }
"min_align_of_val" => {
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
@@ -201,18 +195,19 @@
self.const_usize(self.align_of(tp_ty).bytes())
}
}
- "pref_align_of" => {
- let tp_ty = substs.type_at(0);
- self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
- }
+ "size_of" |
+ "pref_align_of" |
+ "min_align_of" |
+ "needs_drop" |
+ "type_id" |
"type_name" => {
- let tp_ty = substs.type_at(0);
- let ty_name = self.tcx.type_name(tp_ty);
+ let gid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
}
- "type_id" => {
- self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
- }
"init" => {
let ty = substs.type_at(0);
if !self.layout_of(ty).is_zst() {
@@ -235,11 +230,6 @@
"uninit" | "forget" => {
return;
}
- "needs_drop" => {
- let tp_ty = substs.type_at(0);
-
- self.const_bool(self.type_needs_drop(tp_ty))
- }
"offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 8829a33..1bb0ea5 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -667,8 +667,7 @@
}).collect();
- let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
- bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
+ bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
terminator.source_info.span);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs
index ede30a0..7c79cd6 100644
--- a/src/librustc_codegen_ssa/traits/intrinsic.rs
+++ b/src/librustc_codegen_ssa/traits/intrinsic.rs
@@ -1,6 +1,6 @@
use super::BackendTypes;
use crate::mir::operand::OperandRef;
-use rustc::ty::Ty;
+use rustc::ty::{self, Ty};
use rustc_target::abi::call::FnType;
use syntax_pos::Span;
@@ -10,7 +10,7 @@
/// add them to librustc_codegen_llvm/context.rs
fn codegen_intrinsic_call(
&mut self,
- callee_ty: Ty<'tcx>,
+ instance: ty::Instance<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
llresult: Self::Value,
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index c4d3ad9..fa9504e 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -326,6 +326,7 @@
}
fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
match node {
+ pprust::AnnNode::Crate(_) |
pprust::AnnNode::Ident(_) |
pprust::AnnNode::Name(_) => {},
@@ -431,14 +432,18 @@
match node {
pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
s.s.space();
- // FIXME #16420: this doesn't display the connections
- // between syntax contexts
s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
}
pprust::AnnNode::Name(&name) => {
s.s.space();
s.synth_comment(name.as_u32().to_string())
}
+ pprust::AnnNode::Crate(_) => {
+ s.s.hardbreak();
+ let verbose = self.sess.verbose();
+ s.synth_comment(syntax_pos::hygiene::debug_hygiene_data(verbose));
+ s.s.hardbreak_if_not_bol();
+ }
_ => {}
}
}
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 6660836..d238de2 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1144,15 +1144,18 @@
buffer.prepend(0, " ", Style::NoStyle);
}
draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
- let level_str = level.to_string();
- if !level_str.is_empty() {
- buffer.append(0, &level_str, Style::MainHeaderMsg);
- buffer.append(0, ": ", Style::NoStyle);
+ if *level != Level::FailureNote {
+ let level_str = level.to_string();
+ if !level_str.is_empty() {
+ buffer.append(0, &level_str, Style::MainHeaderMsg);
+ buffer.append(0, ": ", Style::NoStyle);
+ }
}
self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
} else {
let level_str = level.to_string();
- if !level_str.is_empty() {
+ // The failure note level itself does not provide any useful diagnostic information
+ if *level != Level::FailureNote && !level_str.is_empty() {
buffer.append(0, &level_str, Style::Level(level.clone()));
}
// only render error codes, not lint codes
@@ -1161,7 +1164,7 @@
buffer.append(0, &code, Style::Level(level.clone()));
buffer.append(0, "]", Style::Level(level.clone()));
}
- if !level_str.is_empty() {
+ if *level != Level::FailureNote && !level_str.is_empty() {
buffer.append(0, ": ", header_style);
}
for &(ref text, _) in msg.iter() {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index c1fba41..8b543be 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -833,7 +833,7 @@
Warning => "warning",
Note => "note",
Help => "help",
- FailureNote => "",
+ FailureNote => "failure-note",
Cancelled => panic!("Shouldn't call on cancelled error"),
}
}
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 75d7261..34c84b1 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -489,7 +489,11 @@
fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
- // with items in 'raw_proc_macros'
+ // with items in 'raw_proc_macros'.
+ // NOTE: If you update the order of macros in 'proc_macro_data' for any reason,
+ // you must also update src/libsyntax_ext/proc_macro_harness.rs
+ // Failing to do so will result in incorrect data being associated
+ // with proc macros when deserialized.
let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
&self.raw_proc_macros.unwrap()[pos]
}
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 3f53f84..4351598 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -15,6 +15,7 @@
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
use rustc::traits::Reveal;
use rustc_data_structures::fx::FxHashMap;
+use crate::interpret::eval_nullary_intrinsic;
use syntax::source_map::{Span, DUMMY_SP};
@@ -602,6 +603,23 @@
other => return other,
}
}
+
+ // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
+ // Catch such calls and evaluate them instead of trying to load a constant's MIR.
+ if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
+ let ty = key.value.instance.ty(tcx);
+ let substs = match ty.sty {
+ ty::FnDef(_, substs) => substs,
+ _ => bug!("intrinsic with type {:?}", ty),
+ };
+ return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
+ .map_err(|error| {
+ let span = tcx.def_span(def_id);
+ let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
+ error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
+ })
+ }
+
tcx.const_eval_raw(key).and_then(|val| {
validate_and_turn_into_const(tcx, val, key)
})
diff --git a/src/librustc_mir/dataflow/generic.rs b/src/librustc_mir/dataflow/generic.rs
new file mode 100644
index 0000000..886044c
--- /dev/null
+++ b/src/librustc_mir/dataflow/generic.rs
@@ -0,0 +1,512 @@
+//! Dataflow analysis with arbitrary transfer functions.
+//!
+//! This module is a work in progress. You should instead use `BitDenotation` in
+//! `librustc_mir/dataflow/mod.rs` and encode your transfer function as a [gen/kill set][gk]. In
+//! doing so, your analysis will run faster and you will be able to generate graphviz diagrams for
+//! debugging with no extra effort. The interface in this module is intended only for dataflow
+//! problems that cannot be expressed using gen/kill sets.
+//!
+//! FIXME(ecstaticmorse): In the long term, the plan is to preserve the existing `BitDenotation`
+//! interface, but make `Engine` and `ResultsCursor` the canonical way to perform and inspect a
+//! dataflow analysis. This requires porting the graphviz debugging logic to this module, deciding
+//! on a way to handle the `before` methods in `BitDenotation` and creating an adapter so that
+//! gen-kill problems can still be evaluated efficiently. See the discussion in [#64566][] for more
+//! information.
+//!
+//! [gk]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
+//! [#64566]: https://github.com/rust-lang/rust/pull/64566
+
+use std::cmp::Ordering;
+use std::ops;
+
+use rustc::mir::{self, traversal, BasicBlock, Location};
+use rustc_data_structures::bit_set::BitSet;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::work_queue::WorkQueue;
+
+use crate::dataflow::BottomValue;
+
+/// A specific kind of dataflow analysis.
+///
+/// To run a dataflow analysis, one must set the initial state of the `START_BLOCK` via
+/// `initialize_start_block` and define a transfer function for each statement or terminator via
+/// the various `effect` methods. The entry set for all other basic blocks is initialized to
+/// `Self::BOTTOM_VALUE`. The dataflow `Engine` then iteratively updates the various entry sets for
+/// each block with the cumulative effects of the transfer functions of all preceding blocks.
+///
+/// You should use an `Engine` to actually run an analysis, and a `ResultsCursor` to inspect the
+/// results of that analysis like so:
+///
+/// ```ignore(cross-crate-imports)
+/// fn do_my_analysis(body: &mir::Body<'tcx>, dead_unwinds: &BitSet<BasicBlock>) {
+/// // `MyAnalysis` implements `Analysis`.
+/// let analysis = MyAnalysis::new();
+///
+/// let results = Engine::new(body, dead_unwinds, analysis).iterate_to_fixpoint();
+/// let mut cursor = ResultsCursor::new(body, results);
+///
+/// for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() {
+/// cursor.seek_after(Location { block: START_BLOCK, statement_index });
+/// let state = cursor.get();
+/// println!("{:?}", state);
+/// }
+/// }
+/// ```
+pub trait Analysis<'tcx>: BottomValue {
+ /// The index type used to access the dataflow state.
+ type Idx: Idx;
+
+ /// A name, used for debugging, that describes this dataflow analysis.
+ ///
+ /// The name should be suitable as part of a filename, so avoid whitespace, slashes or periods
+ /// and try to keep it short.
+ const NAME: &'static str;
+
+ /// The size of each bitvector allocated for each block.
+ fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize;
+
+ /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow
+ /// analysis.
+ fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>);
+
+ /// Updates the current dataflow state with the effect of evaluating a statement.
+ fn apply_statement_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ statement: &mir::Statement<'tcx>,
+ location: Location,
+ );
+
+ /// Updates the current dataflow state with the effect of evaluating a statement.
+ ///
+ /// Note that the effect of a successful return from a `Call` terminator should **not** be
+ /// acounted for in this function. That should go in `apply_call_return_effect`. For example,
+ /// in the `InitializedPlaces` analyses, the return place is not marked as initialized here.
+ fn apply_terminator_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ terminator: &mir::Terminator<'tcx>,
+ location: Location,
+ );
+
+ /// Updates the current dataflow state with the effect of a successful return from a `Call`
+ /// terminator.
+ ///
+ /// This is separated from `apply_terminator_effect` to properly track state across
+ /// unwind edges for `Call`s.
+ fn apply_call_return_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ block: BasicBlock,
+ func: &mir::Operand<'tcx>,
+ args: &[mir::Operand<'tcx>],
+ return_place: &mir::Place<'tcx>,
+ );
+
+ /// Applies the cumulative effect of an entire basic block to the dataflow state (except for
+ /// `call_return_effect`, which is handled in the `Engine`).
+ ///
+ /// The default implementation calls `statement_effect` for every statement in the block before
+ /// finally calling `terminator_effect`. However, some dataflow analyses are able to coalesce
+ /// transfer functions for an entire block and apply them at once. Such analyses should
+ /// override `block_effect`.
+ fn apply_whole_block_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ block: BasicBlock,
+ block_data: &mir::BasicBlockData<'tcx>,
+ ) {
+ for (statement_index, stmt) in block_data.statements.iter().enumerate() {
+ let location = Location { block, statement_index };
+ self.apply_statement_effect(state, stmt, location);
+ }
+
+ let location = Location { block, statement_index: block_data.statements.len() };
+ self.apply_terminator_effect(state, block_data.terminator(), location);
+ }
+
+ /// Applies the cumulative effect of a sequence of statements (and possibly a terminator)
+ /// within a single basic block.
+ ///
+ /// When called with `0..block_data.statements.len() + 1` as the statement range, this function
+ /// is equivalent to `apply_whole_block_effect`.
+ fn apply_partial_block_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ block: BasicBlock,
+ block_data: &mir::BasicBlockData<'tcx>,
+ mut range: ops::Range<usize>,
+ ) {
+ if range.is_empty() {
+ return;
+ }
+
+ // The final location might be a terminator, so iterate through all statements until the
+ // final one, then check to see whether the final one is a statement or terminator.
+ //
+ // This can't cause the range to wrap-around since we check that the range contains at
+ // least one element above.
+ range.end -= 1;
+ let final_location = Location { block, statement_index: range.end };
+
+ for statement_index in range {
+ let location = Location { block, statement_index };
+ let stmt = &block_data.statements[statement_index];
+ self.apply_statement_effect(state, stmt, location);
+ }
+
+ if final_location.statement_index == block_data.statements.len() {
+ let terminator = block_data.terminator();
+ self.apply_terminator_effect(state, terminator, final_location);
+ } else {
+ let stmt = &block_data.statements[final_location.statement_index];
+ self.apply_statement_effect(state, stmt, final_location);
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+enum CursorPosition {
+ AtBlockStart(BasicBlock),
+ After(Location),
+}
+
+impl CursorPosition {
+ fn block(&self) -> BasicBlock {
+ match *self {
+ Self::AtBlockStart(block) => block,
+ Self::After(Location { block, .. }) => block,
+ }
+ }
+}
+
+/// Inspect the results of dataflow analysis.
+///
+/// This cursor has linear performance when visiting statements in a block in order. Visiting
+/// statements within a block in reverse order is `O(n^2)`, where `n` is the number of statements
+/// in that block.
+pub struct ResultsCursor<'mir, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ body: &'mir mir::Body<'tcx>,
+ results: Results<'tcx, A>,
+ state: BitSet<A::Idx>,
+
+ pos: CursorPosition,
+
+ /// Whether the effects of `apply_call_return_effect` are currently stored in `state`.
+ ///
+ /// This flag ensures that multiple calls to `seek_after_assume_call_returns` with the same
+ /// target only result in one invocation of `apply_call_return_effect`.
+ is_call_return_effect_applied: bool,
+}
+
+impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ /// Returns a new cursor for `results` that points to the start of the `START_BLOCK`.
+ pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self {
+ ResultsCursor {
+ body,
+ pos: CursorPosition::AtBlockStart(mir::START_BLOCK),
+ is_call_return_effect_applied: false,
+ state: results.entry_sets[mir::START_BLOCK].clone(),
+ results,
+ }
+ }
+
+ /// Resets the cursor to the start of the given `block`.
+ pub fn seek_to_block_start(&mut self, block: BasicBlock) {
+ self.state.overwrite(&self.results.entry_sets[block]);
+ self.pos = CursorPosition::AtBlockStart(block);
+ self.is_call_return_effect_applied = false;
+ }
+
+ /// Updates the cursor to hold the dataflow state immediately before `target`.
+ pub fn seek_before(&mut self, target: Location) {
+ assert!(target <= self.body.terminator_loc(target.block));
+
+ if target.statement_index == 0 {
+ self.seek_to_block_start(target.block);
+ } else {
+ self._seek_after(Location {
+ block: target.block,
+ statement_index: target.statement_index - 1,
+ });
+ }
+ }
+
+ /// Updates the cursor to hold the dataflow state at `target`.
+ ///
+ /// If `target` is a `Call` terminator, `apply_call_return_effect` will not be called. See
+ /// `seek_after_assume_call_returns` if you wish to observe the dataflow state upon a
+ /// successful return.
+ pub fn seek_after(&mut self, target: Location) {
+ assert!(target <= self.body.terminator_loc(target.block));
+
+ // This check ensures the correctness of a call to `seek_after_assume_call_returns`
+ // followed by one to `seek_after` with the same target.
+ if self.is_call_return_effect_applied {
+ self.seek_to_block_start(target.block);
+ }
+
+ self._seek_after(target);
+ }
+
+ /// Equivalent to `seek_after`, but also calls `apply_call_return_effect` if `target` is a
+ /// `Call` terminator whose callee is convergent.
+ pub fn seek_after_assume_call_returns(&mut self, target: Location) {
+ assert!(target <= self.body.terminator_loc(target.block));
+
+ self._seek_after(target);
+
+ if target != self.body.terminator_loc(target.block) {
+ return;
+ }
+
+ let term = self.body.basic_blocks()[target.block].terminator();
+ if let mir::TerminatorKind::Call {
+ destination: Some((return_place, _)),
+ func,
+ args,
+ ..
+ } = &term.kind {
+ if !self.is_call_return_effect_applied {
+ self.is_call_return_effect_applied = true;
+ self.results.analysis.apply_call_return_effect(
+ &mut self.state,
+ target.block,
+ func,
+ args,
+ return_place,
+ );
+ }
+ }
+ }
+
+ fn _seek_after(&mut self, target: Location) {
+ let Location { block: target_block, statement_index: target_index } = target;
+
+ if self.pos.block() != target_block {
+ self.seek_to_block_start(target_block);
+ }
+
+ // If we're in the same block but after the target statement, we need to reset to the start
+ // of the block.
+ if let CursorPosition::After(Location { statement_index: curr_index, .. }) = self.pos {
+ match curr_index.cmp(&target_index) {
+ Ordering::Equal => return,
+ Ordering::Less => {},
+ Ordering::Greater => self.seek_to_block_start(target_block),
+ }
+ }
+
+ // The cursor is now in the same block as the target location pointing at an earlier
+ // statement.
+ debug_assert_eq!(self.pos.block(), target_block);
+ if let CursorPosition::After(Location { statement_index, .. }) = self.pos {
+ debug_assert!(statement_index < target_index);
+ }
+
+ let first_unapplied_statement = match self.pos {
+ CursorPosition::AtBlockStart(_) => 0,
+ CursorPosition::After(Location { statement_index, .. }) => statement_index + 1,
+ };
+
+ let block_data = &self.body.basic_blocks()[target_block];
+ self.results.analysis.apply_partial_block_effect(
+ &mut self.state,
+ target_block,
+ block_data,
+ first_unapplied_statement..target_index + 1,
+ );
+
+ self.pos = CursorPosition::After(target);
+ self.is_call_return_effect_applied = false;
+ }
+
+ /// Gets the dataflow state at the current location.
+ pub fn get(&self) -> &BitSet<A::Idx> {
+ &self.state
+ }
+}
+
+/// A completed dataflow analysis.
+pub struct Results<'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ analysis: A,
+ entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
+}
+
+/// All information required to iterate a dataflow analysis to fixpoint.
+pub struct Engine<'a, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ analysis: A,
+ bits_per_block: usize,
+ body: &'a mir::Body<'tcx>,
+ dead_unwinds: &'a BitSet<BasicBlock>,
+ entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
+}
+
+impl<A> Engine<'a, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ pub fn new(
+ body: &'a mir::Body<'tcx>,
+ dead_unwinds: &'a BitSet<BasicBlock>,
+ analysis: A,
+ ) -> Self {
+ let bits_per_block = analysis.bits_per_block(body);
+
+ let bottom_value_set = if A::BOTTOM_VALUE == true {
+ BitSet::new_filled(bits_per_block)
+ } else {
+ BitSet::new_empty(bits_per_block)
+ };
+
+ let mut entry_sets = IndexVec::from_elem(bottom_value_set, body.basic_blocks());
+ analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
+
+ Engine {
+ analysis,
+ bits_per_block,
+ body,
+ dead_unwinds,
+ entry_sets,
+ }
+ }
+
+ pub fn iterate_to_fixpoint(mut self) -> Results<'tcx, A> {
+ let mut temp_state = BitSet::new_empty(self.bits_per_block);
+
+ let mut dirty_queue: WorkQueue<BasicBlock> =
+ WorkQueue::with_none(self.body.basic_blocks().len());
+
+ for (bb, _) in traversal::reverse_postorder(self.body) {
+ dirty_queue.insert(bb);
+ }
+
+ // Add blocks that are not reachable from START_BLOCK to the work queue. These blocks will
+ // be processed after the ones added above.
+ for bb in self.body.basic_blocks().indices() {
+ dirty_queue.insert(bb);
+ }
+
+ while let Some(bb) = dirty_queue.pop() {
+ let bb_data = &self.body[bb];
+ let on_entry = &self.entry_sets[bb];
+
+ temp_state.overwrite(on_entry);
+ self.analysis.apply_whole_block_effect(&mut temp_state, bb, bb_data);
+
+ self.propagate_bits_into_graph_successors_of(
+ &mut temp_state,
+ (bb, bb_data),
+ &mut dirty_queue,
+ );
+ }
+
+ Results {
+ analysis: self.analysis,
+ entry_sets: self.entry_sets,
+ }
+ }
+
+ fn propagate_bits_into_graph_successors_of(
+ &mut self,
+ in_out: &mut BitSet<A::Idx>,
+ (bb, bb_data): (BasicBlock, &'a mir::BasicBlockData<'tcx>),
+ dirty_list: &mut WorkQueue<BasicBlock>,
+ ) {
+ match bb_data.terminator().kind {
+ mir::TerminatorKind::Return
+ | mir::TerminatorKind::Resume
+ | mir::TerminatorKind::Abort
+ | mir::TerminatorKind::GeneratorDrop
+ | mir::TerminatorKind::Unreachable => {}
+
+ mir::TerminatorKind::Goto { target }
+ | mir::TerminatorKind::Assert { target, cleanup: None, .. }
+ | mir::TerminatorKind::Yield { resume: target, drop: None, .. }
+ | mir::TerminatorKind::Drop { target, location: _, unwind: None }
+ | mir::TerminatorKind::DropAndReplace { target, value: _, location: _, unwind: None } =>
+ {
+ self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+ }
+
+ mir::TerminatorKind::Yield { resume: target, drop: Some(drop), .. } => {
+ self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+ self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
+ }
+
+ mir::TerminatorKind::Assert { target, cleanup: Some(unwind), .. }
+ | mir::TerminatorKind::Drop { target, location: _, unwind: Some(unwind) }
+ | mir::TerminatorKind::DropAndReplace {
+ target,
+ value: _,
+ location: _,
+ unwind: Some(unwind),
+ } => {
+ self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+ if !self.dead_unwinds.contains(bb) {
+ self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+ }
+ }
+
+ mir::TerminatorKind::SwitchInt { ref targets, .. } => {
+ for target in targets {
+ self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list);
+ }
+ }
+
+ mir::TerminatorKind::Call { cleanup, ref destination, ref func, ref args, .. } => {
+ if let Some(unwind) = cleanup {
+ if !self.dead_unwinds.contains(bb) {
+ self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+ }
+ }
+
+ if let Some((ref dest_place, dest_bb)) = *destination {
+ // N.B.: This must be done *last*, after all other
+ // propagation, as documented in comment above.
+ self.analysis.apply_call_return_effect(in_out, bb, func, args, dest_place);
+ self.propagate_bits_into_entry_set_for(in_out, dest_bb, dirty_list);
+ }
+ }
+
+ mir::TerminatorKind::FalseEdges { real_target, imaginary_target } => {
+ self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
+ self.propagate_bits_into_entry_set_for(in_out, imaginary_target, dirty_list);
+ }
+
+ mir::TerminatorKind::FalseUnwind { real_target, unwind } => {
+ self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
+ if let Some(unwind) = unwind {
+ if !self.dead_unwinds.contains(bb) {
+ self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+ }
+ }
+ }
+ }
+ }
+
+ fn propagate_bits_into_entry_set_for(
+ &mut self,
+ in_out: &BitSet<A::Idx>,
+ bb: BasicBlock,
+ dirty_queue: &mut WorkQueue<BasicBlock>,
+ ) {
+ let entry_set = &mut self.entry_sets[bb];
+ let set_changed = self.analysis.join(entry_set, &in_out);
+ if set_changed {
+ dirty_queue.insert(bb);
+ }
+ }
+}
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 7fe2a89..5ab4e25 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -30,6 +30,7 @@
mod at_location;
pub mod drop_flag_effects;
+pub mod generic;
mod graphviz;
mod impls;
pub mod move_paths;
@@ -56,7 +57,7 @@
/// string (as well as that of rendering up-front); in exchange, you
/// don't have to hand over ownership of your value or deal with
/// borrowing it.
-pub(crate) struct DebugFormatted(String);
+pub struct DebugFormatted(String);
impl DebugFormatted {
pub fn new(input: &dyn fmt::Debug) -> DebugFormatted {
@@ -70,7 +71,7 @@
}
}
-pub(crate) trait Dataflow<'tcx, BD: BitDenotation<'tcx>> {
+pub trait Dataflow<'tcx, BD: BitDenotation<'tcx>> {
/// Sets up and runs the dataflow problem, using `p` to render results if
/// implementation so chooses.
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted {
@@ -121,7 +122,7 @@
pub(crate) param_env: ty::ParamEnv<'tcx>,
}
-pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(
+pub fn do_dataflow<'a, 'tcx, BD, P>(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
def_id: DefId,
@@ -453,34 +454,10 @@
{
self.flow_state.each_gen_bit(f)
}
-}
-pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
- analysis: &T,
- result: &DataflowResults<'tcx, T>,
- body: &Body<'tcx>)
- -> BitSet<T::Idx> {
- let mut trans = GenKill::from_elem(HybridBitSet::new_empty(analysis.bits_per_block()));
-
- for stmt in 0..loc.statement_index {
- let mut stmt_loc = loc;
- stmt_loc.statement_index = stmt;
- analysis.before_statement_effect(&mut trans, stmt_loc);
- analysis.statement_effect(&mut trans, stmt_loc);
+ pub fn get(&self) -> &BitSet<BD::Idx> {
+ self.flow_state.as_dense()
}
-
- // Apply the pre-statement effect of the statement we're evaluating.
- if loc.statement_index == body[loc.block].statements.len() {
- analysis.before_terminator_effect(&mut trans, loc);
- } else {
- analysis.before_statement_effect(&mut trans, loc);
- }
-
- // Apply the transfer function for all preceding statements to the fixpoint
- // at the start of the block.
- let mut state = result.sets().entry_set_for(loc.block.index()).to_owned();
- trans.apply(&mut state);
- state
}
pub struct DataflowAnalysis<'a, 'tcx, O>
@@ -565,7 +542,7 @@
pub(crate) kill_set: T,
}
-type GenKillSet<T> = GenKill<HybridBitSet<T>>;
+pub type GenKillSet<T> = GenKill<HybridBitSet<T>>;
impl<T> GenKill<T> {
/// Creates a new tuple where `gen_set == kill_set == elem`.
@@ -580,28 +557,28 @@
}
impl<E:Idx> GenKillSet<E> {
- pub(crate) fn clear(&mut self) {
+ pub fn clear(&mut self) {
self.gen_set.clear();
self.kill_set.clear();
}
- fn gen(&mut self, e: E) {
+ pub fn gen(&mut self, e: E) {
self.gen_set.insert(e);
self.kill_set.remove(e);
}
- fn gen_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
+ pub fn gen_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
for j in i {
self.gen(*j.borrow());
}
}
- fn kill(&mut self, e: E) {
+ pub fn kill(&mut self, e: E) {
self.gen_set.remove(e);
self.kill_set.insert(e);
}
- fn kill_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
+ pub fn kill_all(&mut self, i: impl IntoIterator<Item: Borrow<E>>) {
for j in i {
self.kill(*j.borrow());
}
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 054b65f..78996ed 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -14,7 +14,6 @@
use rustc::ty::query::TyCtxtAt;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::mir::interpret::{
- ErrorHandled,
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
InterpResult, truncate, sign_extend,
};
@@ -672,14 +671,7 @@
// Our result will later be validated anyway, and there seems no good reason
// to have to fail early here. This is also more consistent with
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
- let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
- match err {
- ErrorHandled::Reported =>
- err_inval!(ReferencedConstant),
- ErrorHandled::TooGeneric =>
- err_inval!(TooGeneric),
- }
- })?;
+ let val = self.tcx.const_eval_raw(param_env.and(gid))?;
self.raw_const_to_mplace(val)
}
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 0f2305e..ec09e69 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -5,17 +5,18 @@
use syntax::symbol::Symbol;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
+use rustc::ty::subst::SubstsRef;
+use rustc::hir::def_id::DefId;
+use rustc::ty::TyCtxt;
use rustc::mir::BinOp;
-use rustc::mir::interpret::{InterpResult, Scalar};
+use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
use super::{
- Machine, PlaceTy, OpTy, InterpCx, Immediate,
+ Machine, PlaceTy, OpTy, InterpCx,
};
mod type_name;
-pub use type_name::*;
-
fn numeric_intrinsic<'tcx, Tag>(
name: &str,
bits: u128,
@@ -37,6 +38,50 @@
Ok(Scalar::from_uint(bits_out, size))
}
+/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
+/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
+crate fn eval_nullary_intrinsic<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
+) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
+ let tp_ty = substs.type_at(0);
+ let name = &*tcx.item_name(def_id).as_str();
+ Ok(match name {
+ "type_name" => {
+ let alloc = type_name::alloc_type_name(tcx, tp_ty);
+ tcx.mk_const(ty::Const {
+ val: ConstValue::Slice {
+ data: alloc,
+ start: 0,
+ end: alloc.len(),
+ },
+ ty: tcx.mk_static_str(),
+ })
+ },
+ "needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+ "size_of" |
+ "min_align_of" |
+ "pref_align_of" => {
+ let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
+ let n = match name {
+ "pref_align_of" => layout.align.pref.bytes(),
+ "min_align_of" => layout.align.abi.bytes(),
+ "size_of" => layout.size.bytes(),
+ _ => bug!(),
+ };
+ ty::Const::from_usize(tcx, n)
+ },
+ "type_id" => ty::Const::from_bits(
+ tcx,
+ tcx.type_id_hash(tp_ty).into(),
+ param_env.and(tcx.types.u64),
+ ),
+ other => bug!("`{}` is not a zero arg intrinsic", other),
+ })
+}
+
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Returns `true` if emulation happened.
pub fn emulate_intrinsic(
@@ -49,41 +94,19 @@
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
match intrinsic_name {
- "min_align_of" => {
- let elem_ty = substs.type_at(0);
- let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
- let align_val = Scalar::from_uint(elem_align, dest.layout.size);
- self.write_scalar(align_val, dest)?;
- }
-
- "needs_drop" => {
- let ty = substs.type_at(0);
- let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
- let val = Scalar::from_bool(ty_needs_drop);
- self.write_scalar(val, dest)?;
- }
-
- "size_of" => {
- let ty = substs.type_at(0);
- let size = self.layout_of(ty)?.size.bytes() as u128;
- let size_val = Scalar::from_uint(size, dest.layout.size);
- self.write_scalar(size_val, dest)?;
- }
-
- "type_id" => {
- let ty = substs.type_at(0);
- let type_id = self.tcx.type_id_hash(ty) as u128;
- let id_val = Scalar::from_uint(type_id, dest.layout.size);
- self.write_scalar(id_val, dest)?;
- }
-
+ "min_align_of" |
+ "pref_align_of" |
+ "needs_drop" |
+ "size_of" |
+ "type_id" |
"type_name" => {
- let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
- let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
- let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
- let alloc_len = alloc.size.bytes();
- let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
- self.write_immediate(name_val, dest)?;
+ let gid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ let val = self.tcx.const_eval(self.param_env.and(gid))?;
+ let val = self.eval_const_to_op(val, None)?;
+ self.copy_op(val, dest)?;
}
| "ctpop"
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index 032d16a..1e765a4 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -7,7 +7,7 @@
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
use rustc::hir::def_id::CrateNum;
use std::fmt::Write;
-use rustc::mir::interpret::{Allocation, ConstValue};
+use rustc::mir::interpret::Allocation;
struct AbsolutePathPrinter<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -213,22 +213,11 @@
}
}
-/// Produces an absolute path representation of the given type. See also the documentation on
-/// `std::any::type_name`
-pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
- let alloc = alloc_type_name(tcx, ty);
- tcx.mk_const(ty::Const {
- val: ConstValue::Slice {
- data: alloc,
- start: 0,
- end: alloc.len(),
- },
- ty: tcx.mk_static_str(),
- })
-}
-
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
-pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
+crate fn alloc_type_name<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>
+) -> &'tcx Allocation {
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
tcx.intern_const_alloc(alloc)
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 45d2434..0c61be2 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -34,6 +34,6 @@
pub use self::validity::RefTracking;
-pub(super) use self::intrinsics::type_name;
-
pub use self::intern::intern_const_alloc_recursive;
+
+crate use self::intrinsics::eval_nullary_intrinsic;
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index f27db35..9a03719 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -23,6 +23,7 @@
#![feature(try_blocks)]
#![feature(mem_take)]
#![feature(associated_type_bounds)]
+#![feature(range_is_empty)]
#![recursion_limit="256"]
@@ -35,7 +36,7 @@
mod borrow_check;
mod build;
-mod dataflow;
+pub mod dataflow;
mod hair;
mod lints;
mod shim;
@@ -59,5 +60,4 @@
let (param_env, (value, field)) = param_env_and_value.into_parts();
const_eval::const_field(tcx, param_env, None, field, value)
};
- providers.type_name = interpret::type_name;
}
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 0ce2db9..caf588a 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -67,7 +67,7 @@
use crate::transform::simplify;
use crate::transform::no_landing_pads::no_landing_pads;
use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation};
-use crate::dataflow::{do_dataflow, DebugFormatted, state_for_location};
+use crate::dataflow::{do_dataflow, DebugFormatted, DataflowResultsCursor};
use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals, RequiresStorage};
use crate::util::dump_mir;
use crate::util::liveness;
@@ -436,9 +436,10 @@
// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
let storage_live_analysis = MaybeStorageLive::new(body);
- let storage_live =
+ let storage_live_results =
do_dataflow(tcx, body, def_id, &[], &dead_unwinds, storage_live_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+ let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body);
// Find the MIR locals which do not use StorageLive/StorageDead statements.
// The storage of these locals are always live.
@@ -448,17 +449,18 @@
// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body);
- let borrowed_locals_result =
+ let borrowed_locals_results =
do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+ let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body);
// Calculate the MIR locals that we actually need to keep storage around
// for.
- let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
- let requires_storage =
+ let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results);
+ let requires_storage_results =
do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
- let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
+ let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body);
// Calculate the liveness of MIR locals ignoring borrows.
let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len());
@@ -484,10 +486,6 @@
};
if !movable {
- let borrowed_locals = state_for_location(loc,
- &borrowed_locals_analysis,
- &borrowed_locals_result,
- body);
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
// This is correct for movable generators since borrows cannot live across
// suspension points. However for immovable generators we need to account for
@@ -498,22 +496,19 @@
// If a borrow is converted to a raw reference, we must also assume that it lives
// forever. Note that the final liveness is still bounded by the storage liveness
// of the local, which happens using the `intersect` operation below.
- liveness.outs[block].union(&borrowed_locals);
+ borrowed_locals_cursor.seek(loc);
+ liveness.outs[block].union(borrowed_locals_cursor.get());
}
- let storage_liveness = state_for_location(loc,
- &storage_live_analysis,
- &storage_live,
- body);
+ storage_live_cursor.seek(loc);
+ let storage_liveness = storage_live_cursor.get();
// Store the storage liveness for later use so we can restore the state
// after a suspension point
storage_liveness_map.insert(block, storage_liveness.clone());
- let mut storage_required = state_for_location(loc,
- &requires_storage_analysis,
- &requires_storage,
- body);
+ requires_storage_cursor.seek(loc);
+ let mut storage_required = requires_storage_cursor.get().clone();
// Mark locals without storage statements as always requiring storage
storage_required.union(&ignored.0);
@@ -549,8 +544,7 @@
body,
&live_locals,
&ignored,
- requires_storage,
- requires_storage_analysis);
+ requires_storage_results);
LivenessInfo {
live_locals,
@@ -588,7 +582,6 @@
stored_locals: &liveness::LiveVarSet,
ignored: &StorageIgnored,
requires_storage: DataflowResults<'tcx, RequiresStorage<'mir, 'tcx>>,
- _requires_storage_analysis: RequiresStorage<'mir, 'tcx>,
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
assert_eq!(body.local_decls.len(), ignored.0.domain_size());
assert_eq!(body.local_decls.len(), stored_locals.domain_size());
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 0386dbd..be364a1 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -2326,10 +2326,10 @@
/// An iterator over the contents of an instance of `BufRead` split on a
/// particular byte.
///
-/// This struct is generally created by calling [`split`][split] on a
-/// `BufRead`. Please see the documentation of `split()` for more details.
+/// This struct is generally created by calling [`split`] on a `BufRead`.
+/// Please see the documentation of [`split`] for more details.
///
-/// [split]: trait.BufRead.html#method.split
+/// [`split`]: trait.BufRead.html#method.split
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Split<B> {
@@ -2358,10 +2358,10 @@
/// An iterator over the lines of an instance of `BufRead`.
///
-/// This struct is generally created by calling [`lines`][lines] on a
-/// `BufRead`. Please see the documentation of `lines()` for more details.
+/// This struct is generally created by calling [`lines`] on a `BufRead`.
+/// Please see the documentation of [`lines`] for more details.
///
-/// [lines]: trait.BufRead.html#method.lines
+/// [`lines`]: trait.BufRead.html#method.lines
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Lines<B> {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bcbc0a1..b634dcc 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2387,7 +2387,7 @@
),
/// A macro invocation.
///
- /// E.g., `macro_rules! foo { .. }` or `foo!(..)`.
+ /// E.g., `foo!(..)`.
Mac(Mac),
/// A macro definition.
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5d8498f..bf36c0d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -35,6 +35,7 @@
SubItem(ast::NodeId),
Expr(&'a ast::Expr),
Pat(&'a ast::Pat),
+ Crate(&'a ast::Crate),
}
pub trait PpAnn {
@@ -140,6 +141,7 @@
s.print_mod(&krate.module, &krate.attrs);
s.print_remaining_comments();
+ s.ann.post(&mut s, AnnNode::Crate(krate));
s.s.eof()
}
@@ -1369,8 +1371,12 @@
}
}
ast::ItemKind::MacroDef(ref macro_def) => {
- let (kw, has_bang) =
- if macro_def.legacy { ("macro_rules", true) } else { ("macro", false) };
+ let (kw, has_bang) = if macro_def.legacy {
+ ("macro_rules", true)
+ } else {
+ self.print_visibility(&item.vis);
+ ("macro", false)
+ };
self.print_mac_common(
Some(MacHeader::Keyword(kw)),
has_bang,
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index a5dcfb9..f33c813 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -20,15 +20,24 @@
attrs: Vec<ast::Name>,
}
+enum ProcMacroDefType {
+ Attr,
+ Bang
+}
+
struct ProcMacroDef {
function_name: Ident,
span: Span,
+ def_type: ProcMacroDefType
+}
+
+enum ProcMacro {
+ Derive(ProcMacroDerive),
+ Def(ProcMacroDef)
}
struct CollectProcMacros<'a> {
- derives: Vec<ProcMacroDerive>,
- attr_macros: Vec<ProcMacroDef>,
- bang_macros: Vec<ProcMacroDef>,
+ macros: Vec<ProcMacro>,
in_root: bool,
handler: &'a errors::Handler,
is_proc_macro_crate: bool,
@@ -46,22 +55,22 @@
let ecfg = ExpansionConfig::default("proc_macro".to_string());
let mut cx = ExtCtxt::new(sess, ecfg, resolver);
- let (derives, attr_macros, bang_macros) = {
- let mut collect = CollectProcMacros {
- derives: Vec::new(),
- attr_macros: Vec::new(),
- bang_macros: Vec::new(),
- in_root: true,
- handler,
- is_proc_macro_crate,
- is_test_crate,
- };
- if has_proc_macro_decls || is_proc_macro_crate {
- visit::walk_crate(&mut collect, &krate);
- }
- (collect.derives, collect.attr_macros, collect.bang_macros)
+ let mut collect = CollectProcMacros {
+ macros: Vec::new(),
+ in_root: true,
+ handler,
+ is_proc_macro_crate,
+ is_test_crate,
};
+ if has_proc_macro_decls || is_proc_macro_crate {
+ visit::walk_crate(&mut collect, &krate);
+ }
+ // NOTE: If you change the order of macros in this vec
+ // for any reason, you must also update 'raw_proc_macro'
+ // in src/librustc_metadata/decoder.rs
+ let macros = collect.macros;
+
if !is_proc_macro_crate {
return krate
}
@@ -74,7 +83,7 @@
return krate;
}
- krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros));
+ krate.module.items.push(mk_decls(&mut cx, ¯os));
krate
}
@@ -161,12 +170,12 @@
};
if self.in_root && item.vis.node.is_pub() {
- self.derives.push(ProcMacroDerive {
+ self.macros.push(ProcMacro::Derive(ProcMacroDerive {
span: item.span,
trait_name: trait_ident.name,
function_name: item.ident,
attrs: proc_attrs,
- });
+ }));
} else {
let msg = if !self.in_root {
"functions tagged with `#[proc_macro_derive]` must \
@@ -180,10 +189,11 @@
fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
if self.in_root && item.vis.node.is_pub() {
- self.attr_macros.push(ProcMacroDef {
+ self.macros.push(ProcMacro::Def(ProcMacroDef {
span: item.span,
function_name: item.ident,
- });
+ def_type: ProcMacroDefType::Attr
+ }));
} else {
let msg = if !self.in_root {
"functions tagged with `#[proc_macro_attribute]` must \
@@ -197,10 +207,11 @@
fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
if self.in_root && item.vis.node.is_pub() {
- self.bang_macros.push(ProcMacroDef {
+ self.macros.push(ProcMacro::Def(ProcMacroDef {
span: item.span,
function_name: item.ident,
- });
+ def_type: ProcMacroDefType::Bang
+ }));
} else {
let msg = if !self.in_root {
"functions tagged with `#[proc_macro]` must \
@@ -322,9 +333,7 @@
// }
fn mk_decls(
cx: &mut ExtCtxt<'_>,
- custom_derives: &[ProcMacroDerive],
- custom_attrs: &[ProcMacroDef],
- custom_macros: &[ProcMacroDef],
+ macros: &[ProcMacro],
) -> P<ast::Item> {
let expn_id = cx.resolver.expansion_for_ast_pass(
DUMMY_SP,
@@ -354,26 +363,32 @@
let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
proc_macro, bridge, client, proc_macro_ty, method,
]));
- custom_derives.iter().map(|cd| {
- cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
- cx.expr_str(cd.span, cd.trait_name),
- cx.expr_vec_slice(
- span,
- cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
- ),
- local_path(cd.span, cd.function_name),
- ])
- }).chain(custom_attrs.iter().map(|ca| {
- cx.expr_call(span, proc_macro_ty_method_path(attr), vec![
- cx.expr_str(ca.span, ca.function_name.name),
- local_path(ca.span, ca.function_name),
- ])
- })).chain(custom_macros.iter().map(|cm| {
- cx.expr_call(span, proc_macro_ty_method_path(bang), vec![
- cx.expr_str(cm.span, cm.function_name.name),
- local_path(cm.span, cm.function_name),
- ])
- })).collect()
+ macros.iter().map(|m| {
+ match m {
+ ProcMacro::Derive(cd) => {
+ cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
+ cx.expr_str(cd.span, cd.trait_name),
+ cx.expr_vec_slice(
+ span,
+ cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
+ ),
+ local_path(cd.span, cd.function_name),
+ ])
+ },
+ ProcMacro::Def(ca) => {
+ let ident = match ca.def_type {
+ ProcMacroDefType::Attr => attr,
+ ProcMacroDefType::Bang => bang
+ };
+
+ cx.expr_call(span, proc_macro_ty_method_path(ident), vec![
+ cx.expr_str(ca.span, ca.function_name.name),
+ local_path(ca.span, ca.function_name),
+ ])
+
+ }
+ }
+ }).collect()
};
let decls_static = cx.item_static(
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 8971638..e28d932 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -343,6 +343,38 @@
}))
}
+pub fn debug_hygiene_data(verbose: bool) -> String {
+ HygieneData::with(|data| {
+ if verbose {
+ format!("{:#?}", data)
+ } else {
+ let mut s = String::from("");
+ s.push_str("Expansions:");
+ data.expn_data.iter().enumerate().for_each(|(id, expn_info)| {
+ let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID");
+ s.push_str(&format!(
+ "\n{}: parent: {:?}, call_site_ctxt: {:?}, kind: {:?}",
+ id,
+ expn_info.parent,
+ expn_info.call_site.ctxt(),
+ expn_info.kind,
+ ));
+ });
+ s.push_str("\n\nSyntaxContexts:");
+ data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
+ s.push_str(&format!(
+ "\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})",
+ id,
+ ctxt.parent,
+ ctxt.outer_expn,
+ ctxt.outer_transparency,
+ ));
+ });
+ s
+ }
+ })
+}
+
impl SyntaxContext {
#[inline]
pub const fn root() -> Self {
diff --git a/src/test/ui/issues/issue-44415.rs b/src/test/compile-fail/issue-44415.rs
similarity index 100%
rename from src/test/ui/issues/issue-44415.rs
rename to src/test/compile-fail/issue-44415.rs
diff --git a/src/test/debuginfo/issue-22656.rs b/src/test/debuginfo/issue-22656.rs
index 86d3190..e4634d9 100644
--- a/src/test/debuginfo/issue-22656.rs
+++ b/src/test/debuginfo/issue-22656.rs
@@ -15,7 +15,7 @@
// lldbg-check:[...]$0 = vec![1, 2, 3]
// lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
// lldb-command:print zs
-// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 }
+// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct[...], y: 123, z: ZeroSizedStruct[...], w: 456 }
// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
// lldbr-command:continue
diff --git a/src/test/pretty/macro.rs b/src/test/pretty/macro.rs
index 39677d1..1e1e1db 100644
--- a/src/test/pretty/macro.rs
+++ b/src/test/pretty/macro.rs
@@ -2,6 +2,6 @@
#![feature(decl_macro)]
-macro mac { ($ arg : expr) => { $ arg + $ arg } }
+pub(crate) macro mac { ($ arg : expr) => { $ arg + $ arg } }
fn main() { }
diff --git a/src/test/rustdoc/inline_cross/proc_macro.rs b/src/test/rustdoc/inline_cross/proc_macro.rs
index 6880e30..3dc8de3 100644
--- a/src/test/rustdoc/inline_cross/proc_macro.rs
+++ b/src/test/rustdoc/inline_cross/proc_macro.rs
@@ -10,8 +10,19 @@
// @has proc_macro/macro.some_proc_macro.html
// @has proc_macro/attr.some_proc_attr.html
// @has proc_macro/derive.SomeDerive.html
-pub use some_macros::{some_proc_macro, some_proc_attr, SomeDerive};
+
+// @has proc_macro/macro.some_proc_macro.html
+// @has - 'a proc-macro that swallows its input and does nothing.'
+pub use some_macros::some_proc_macro;
// @has proc_macro/macro.reexported_macro.html
// @has - 'Doc comment from the original crate'
pub use some_macros::reexported_macro;
+
+// @has proc_macro/attr.some_proc_attr.html
+// @has - 'a proc-macro attribute that passes its item through verbatim.'
+pub use some_macros::some_proc_attr;
+
+// @has proc_macro/derive.SomeDerive.html
+// @has - 'a derive attribute that adds nothing to its input.'
+pub use some_macros::SomeDerive;
diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
new file mode 100644
index 0000000..5f20367
--- /dev/null
+++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `x` does not live long enough
+ --> $DIR/async-borrowck-escaping-closure-error.rs:5:24
+ |
+LL | Box::new((async || x)())
+ | -------------------^----
+ | | | |
+ | | | borrowed value does not live long enough
+ | | value captured here
+ | borrow later used here
+LL |
+LL | }
+ | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
new file mode 100644
index 0000000..e40acff
--- /dev/null
+++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
@@ -0,0 +1,95 @@
+// aux-build:arc_wake.rs
+// edition:2018
+// run-pass
+
+#![allow(unused_variables)]
+
+// Test the drop order for parameters relative to local variables and
+// temporaries created in the tail return expression of the function
+// body. In particular, check that this drop order is the same between
+// a `async fn` and an ordinary `fn`. See #64512.
+
+extern crate arc_wake;
+
+use arc_wake::ArcWake;
+use std::cell::RefCell;
+use std::future::Future;
+use std::sync::Arc;
+use std::rc::Rc;
+use std::task::Context;
+
+struct EmptyWaker;
+
+impl ArcWake for EmptyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+#[derive(Debug, Eq, PartialEq)]
+enum DropOrder {
+ Function,
+ Val(&'static str),
+}
+
+type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
+
+struct D(&'static str, DropOrderListPtr);
+
+impl Drop for D {
+ fn drop(&mut self) {
+ self.1.borrow_mut().push(DropOrder::Val(self.0));
+ }
+}
+
+/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`.
+///
+/// Expected order:
+/// - `z`
+/// - temp
+/// - `y`
+/// - `x`
+async fn foo_async(x: D, _y: D) {
+ let l = x.1.clone();
+ let z = D("z", l.clone());
+ l.borrow_mut().push(DropOrder::Function);
+ helper_async(&D("temp", l)).await
+}
+
+async fn helper_async(v: &D) { }
+
+fn foo_sync(x: D, _y: D) {
+ let l = x.1.clone();
+ let z = D("z", l.clone());
+ l.borrow_mut().push(DropOrder::Function);
+ helper_sync(&D("temp", l))
+}
+
+fn helper_sync(v: &D) { }
+
+fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
+ f: impl FnOnce(DropOrderListPtr) -> Fut,
+ g: impl FnOnce(DropOrderListPtr),
+) {
+ let empty = Arc::new(EmptyWaker);
+ let waker = ArcWake::into_waker(empty);
+ let mut cx = Context::from_waker(&waker);
+
+ let actual_order = Rc::new(RefCell::new(Vec::new()));
+ let mut fut = Box::pin(f(actual_order.clone()));
+ let r = fut.as_mut().poll(&mut cx);
+
+ assert!(match r {
+ std::task::Poll::Ready(()) => true,
+ _ => false,
+ });
+
+ let expected_order = Rc::new(RefCell::new(Vec::new()));
+ g(expected_order.clone());
+
+ assert_eq!(*actual_order.borrow(), *expected_order.borrow());
+}
+
+fn main() {
+ // Free functions (see doc comment on function for what it tests).
+ assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())),
+ |l| foo_sync(D("x", l.clone()), D("_y", l.clone())));
+}
diff --git a/src/test/ui/async-await/issue-64391.rs b/src/test/ui/async-await/issue-64391.rs
new file mode 100644
index 0000000..c6faad3
--- /dev/null
+++ b/src/test/ui/async-await/issue-64391.rs
@@ -0,0 +1,14 @@
+// Regression test for Issue #64391. The goal here is that this
+// function compiles. In the past, due to incorrect drop order for
+// temporaries in the tail expression, we failed to compile this
+// example. The drop order itself is directly tested in
+// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`.
+//
+// check-pass
+// edition:2018
+
+async fn add(x: u32, y: u32) -> u32 {
+ async { x + y }.await
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
new file mode 100644
index 0000000..c818379
--- /dev/null
+++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/return-local-binding-from-desugaring.rs:26:18
+ |
+LL | for ref x in xs {
+ | ^^ creates a temporary which is freed while still in use
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+LL | result
+ | ------ borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
index 70c1093..8fe24ba 100644
--- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
+++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
@@ -25,7 +25,7 @@
LL | fn baz(&self) {}
| ---------------- other definition for `baz`
|
- = note: upstream crates may add new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
+ = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
error: aborting due to 3 previous errors
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
index 928b65e..3a3e1a4 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
@@ -7,7 +7,7 @@
LL | impl A<i16> { fn dummy(&self) { } }
| ------------------- other definition for `dummy`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
index 928b65e..3a3e1a4 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
@@ -7,7 +7,7 @@
LL | impl A<i16> { fn dummy(&self) { } }
| ------------------- other definition for `dummy`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
index 6c3484c..bd6f59f 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
@@ -6,7 +6,7 @@
LL | impl Foo for i16 {}
| ^^^^^^^^^^^^^^^^ conflicting implementation for `i16`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
index 6c3484c..bd6f59f 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
@@ -6,7 +6,7 @@
LL | impl Foo for i16 {}
| ^^^^^^^^^^^^^^^^ conflicting implementation for `i16`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
index cde9360..728eae5 100644
--- a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
@@ -7,7 +7,7 @@
LL | impl<A:Iterator> Foo<A::Item> for A { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
- = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
index cde9360..728eae5 100644
--- a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
@@ -7,7 +7,7 @@
LL | impl<A:Iterator> Foo<A::Item> for A { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
- = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
index 12c7a1f..4d9f55c 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
index 12c7a1f..4d9f55c 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
index 1b6c62e..f0bcf65 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyStruct<MyType> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct<MyType>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
index 1b6c62e..f0bcf65 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyStruct<MyType> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct<MyType>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
index 11bd788..a40153a 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for (MyType,) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
index 11bd788..a40153a 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for (MyType,) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index fdba359..1ae39e7 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -14,6 +14,11 @@
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
+ --> $SRC_DIR/libcore/intrinsics.rs:LL:COL
+ |
+LL | pub fn size_of<T>() -> usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
index dbcb0fc..5e93a02 100644
--- a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
@@ -8,7 +8,9 @@
| -
| |
| `o2` dropped here while still borrowed
- | borrow might be used here, when `o2` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ |
+ = note: values in a scope are dropped in the opposite order they are defined
error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:112:13
@@ -20,7 +22,9 @@
| -
| |
| `o3` dropped here while still borrowed
- | borrow might be used here, when `o3` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ |
+ = note: values in a scope are dropped in the opposite order they are defined
error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:113:13
@@ -38,7 +42,7 @@
--> $DIR/dropck_trait_cycle_checked.rs:114:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o3` is borrowed for `'static`
+ | -------- cast requires that `o3` is borrowed for `'static`
...
LL | o2.set1(&o3);
| ^^^ borrowed value does not live long enough
@@ -62,7 +66,7 @@
--> $DIR/dropck_trait_cycle_checked.rs:116:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+ | -------- cast requires that `o2` is borrowed for `'static`
...
LL | o3.set1(&o2);
| ^^^ borrowed value does not live long enough
diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout
index beac4c1..6971873 100644
--- a/src/test/ui/hygiene/unpretty-debug.stdout
+++ b/src/test/ui/hygiene/unpretty-debug.stdout
@@ -13,3 +13,13 @@
fn bar /* 0#0 */() { let x /* 0#0 */ = 1; y /* 0#1 */ + x /* 0#0 */ }
fn y /* 0#0 */() { }
+
+/*
+Expansions:
+0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root
+1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo)
+
+SyntaxContexts:
+#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
+#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
+*/
diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr
deleted file mode 100644
index 8008e53..0000000
--- a/src/test/ui/issues/issue-44415.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
- --> $DIR/issue-44415.rs:6:17
- |
-LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
- | ^^^^^^
- |
-note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
- --> $DIR/issue-44415.rs:6:17
- |
-LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
- | ^^^^^^
-note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
- --> $DIR/issue-44415.rs:6:26
- |
-LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing layout of `Foo`...
- = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
- = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
-note: cycle used when processing `Foo`
- --> $DIR/issue-44415.rs:5:1
- |
-LL | struct Foo {
- | ^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/issues/issue-48728.stderr b/src/test/ui/issues/issue-48728.stderr
index 99a9bf9..84c10d8 100644
--- a/src/test/ui/issues/issue-48728.stderr
+++ b/src/test/ui/issues/issue-48728.stderr
@@ -7,7 +7,7 @@
LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
| ------------------------------------------- first implementation here
|
- = note: upstream crates may add new impl of trait `std::clone::Clone` for type `[_]` in future versions
+ = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `[_]` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/json-multiple.polonius.stderr b/src/test/ui/json-multiple.polonius.stderr
new file mode 100644
index 0000000..0e4d442
--- /dev/null
+++ b/src/test/ui/json-multiple.polonius.stderr
@@ -0,0 +1 @@
+{"artifact":"$TEST_BUILD_DIR/json-multiple.polonius/libjson_multiple.rlib","emit":"link"}
diff --git a/src/test/ui/json-options.polonius.stderr b/src/test/ui/json-options.polonius.stderr
new file mode 100644
index 0000000..e21f6f8
--- /dev/null
+++ b/src/test/ui/json-options.polonius.stderr
@@ -0,0 +1 @@
+{"artifact":"$TEST_BUILD_DIR/json-options.polonius/libjson_options.rlib","emit":"link"}
diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr
index 86cb2f0..0a1fb56 100644
--- a/src/test/ui/json-short.stderr
+++ b/src/test/ui/json-short.stderr
@@ -15,5 +15,5 @@
"}
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
"}
-{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
+{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`.
"}
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index c7c53ab..678c888 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -412,7 +412,7 @@
{
"message": "For more information about this error, try `rustc --explain E0412`.",
"code": null,
- "level": "",
+ "level": "failure-note",
"spans": [],
"children": [],
"rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m
diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr
index dcb34f3..36f96b0 100644
--- a/src/test/ui/specialization/issue-52050.stderr
+++ b/src/test/ui/specialization/issue-52050.stderr
@@ -11,7 +11,7 @@
LL | impl IntoPyDictPointer for ()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
- = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `()` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
error: aborting due to previous error
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index 63ae445..c364479 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -7,5 +7,3 @@
[dependencies]
toml = "0.5"
serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
-reqwest = "0.9"
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index c2d642b..eab23f3 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -10,10 +10,9 @@
use std::collections::BTreeMap;
use std::env;
use std::fs;
-use std::io::{self, Read, Write, BufRead, BufReader};
+use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};
-use std::collections::HashMap;
static HOSTS: &[&str] = &[
"aarch64-unknown-linux-gnu",
@@ -153,9 +152,6 @@
"x86_64-pc-windows-gnu",
];
-static TOOLSTATE: &str =
- "https://raw.githubusercontent.com/rust-lang-nursery/rust-toolstate/master/history/linux.tsv";
-
#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
struct Manifest {
@@ -364,7 +360,6 @@
self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu");
self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu");
- self.check_toolstate();
self.digest_and_sign();
let manifest = self.build_manifest();
self.write_channel_files(&self.rust_release, &manifest);
@@ -374,36 +369,6 @@
}
}
- /// If a tool does not pass its tests, don't ship it.
- /// Right now, we do this only for Miri.
- fn check_toolstate(&mut self) {
- // Get the toolstate for this rust revision.
- let rev = self.rust_git_commit_hash.as_ref().expect("failed to determine rust git hash");
- let toolstates = reqwest::get(TOOLSTATE).expect("failed to get toolstates");
- let toolstates = BufReader::new(toolstates);
- let toolstate = toolstates.lines()
- .find_map(|line| {
- let line = line.expect("failed to read toolstate lines");
- let mut pieces = line.splitn(2, '\t');
- let commit = pieces.next().expect("malformed toolstate line");
- if commit != rev {
- // Not the right commit.
- return None;
- }
- // Return the 2nd piece, the JSON.
- Some(pieces.next().expect("malformed toolstate line").to_owned())
- })
- .expect("failed to find toolstate for rust commit");
- let toolstate: HashMap<String, String> =
- serde_json::from_str(&toolstate).expect("toolstate is malformed JSON");
- // Mark some tools as missing based on toolstate.
- if toolstate.get("miri").map(|s| &*s as &str) != Some("test-pass") {
- println!("Miri tests are not passing, removing component");
- self.miri_version = None;
- self.miri_git_commit_hash = None;
- }
- }
-
/// Hash all files, compute their signatures, and collect the hashes in `self.digests`.
fn digest_and_sign(&mut self) {
for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
diff --git a/src/tools/cargo b/src/tools/cargo
index 9655d70..3596cb8 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 9655d70af8a6dddac238e3afa2fec75088c9226f
+Subproject commit 3596cb86b2e87dd9b9c1bb90d4a9d73ec2c1512f
diff --git a/src/tools/miri b/src/tools/miri
index d881387..130f948 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit d88138723780d11ca2c09560111223dc20b9d5f3
+Subproject commit 130f9488d3b861e02c9282b686eec717e30912cf
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 4060b90..7cf3cc7 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -201,7 +201,9 @@
new = s.get(tool, old)
status[os] = new
maintainers = ' '.join('@'+name for name in MAINTAINERS[tool])
- if new > old: # comparing the strings, but they are ordered appropriately!
+ # comparing the strings, but they are ordered appropriately:
+ # "test-pass" > "test-fail" > "build-fail"
+ if new > old:
# things got fixed or at least the status quo improved
changed = True
message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
@@ -213,10 +215,17 @@
.format(tool, os, old, new)
message += '{} (cc {}, @rust-lang/infra).\n' \
.format(title, maintainers)
- # Most tools only create issues for build failures.
- # Other failures can be spurious.
- if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'):
- create_issue_for_status = new
+ # See if we need to create an issue.
+ if tool == 'miri':
+ # Create issue if tests used to pass before. Don't open a *second*
+ # issue when we regress from "test-fail" to "build-fail".
+ if old == 'test-pass':
+ create_issue_for_status = new
+ else:
+ # Create issue if things no longer build.
+ # (No issue for mere test failures to avoid spurious issues.)
+ if new == 'build-fail':
+ create_issue_for_status = new
if create_issue_for_status is not None:
try:
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index 930279c..980c975 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -62,6 +62,7 @@
serde = { version = "1.0.82", features = ['derive'] }
serde_json = { version = "1.0.31", features = ["raw_value"] }
smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
+url = { version = "2.0", features = ['serde'] }
[target.'cfg(not(windows))'.dependencies]