Rollup merge of #64486 - matthewjasper:hygiene-debugging, r=petrochenkov
Print out more information for `-Zunpretty=expanded,hygiene`
I've found this helpful when trying to understand how hygiene works.
Closes #16420
diff --git a/Cargo.lock b/Cargo.lock
index 679a024..326f3b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -232,9 +232,9 @@
[[package]]
name = "byteorder"
-version = "1.2.7"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
+checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
[[package]]
name = "bytes"
@@ -2065,7 +2065,7 @@
"hex",
"log",
"num-traits",
- "rand 0.6.1",
+ "rand 0.7.0",
"rustc-workspace-hack",
"rustc_version",
"shell-escape",
@@ -2180,9 +2180,9 @@
[[package]]
name = "openssl-src"
-version = "111.3.0+1.1.1c"
+version = "111.6.0+1.1.1d"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53ed5f31d294bdf5f7a4ba0a206c2754b0f60e9a63b7e3076babc5317873c797"
+checksum = "b9c2da1de8a7a3f860919c01540b03a6db16de042405a8a07a5e9d0b4b825d9c"
dependencies = [
"cc",
]
@@ -3017,7 +3017,7 @@
"log",
"measureme",
"num_cpus",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
"polonius-engine",
"rustc-rayon",
"rustc-rayon-core",
@@ -3253,7 +3253,6 @@
name = "rustc-workspace-hack"
version = "1.0.0"
dependencies = [
- "byteorder",
"crossbeam-utils 0.6.5",
"serde",
"serde_json",
@@ -3311,7 +3310,7 @@
"log",
"memmap",
"num_cpus",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
"rustc",
"rustc_apfloat",
"rustc_codegen_utils",
@@ -3354,7 +3353,7 @@
"jobserver",
"lazy_static 1.3.0",
"log",
- "parking_lot 0.7.1",
+ "parking_lot 0.9.0",
"rustc-hash",
"rustc-rayon",
"rustc-rayon-core",
@@ -4261,13 +4260,13 @@
[[package]]
name = "tempfile"
-version = "3.0.5"
+version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
+checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
"cfg-if",
"libc",
- "rand 0.6.1",
+ "rand 0.7.0",
"redox_syscall",
"remove_dir_all",
"winapi 0.3.6",
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/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 500d576..076bcd8 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -2000,6 +2000,8 @@
}
fn run(self, builder: &Builder<'_>) {
+ // This gets called by `promote-release`
+ // (https://github.com/rust-lang/rust-central-station/tree/master/promote-release).
let mut cmd = builder.tool_cmd(Tool::BuildManifest);
if builder.config.dry_run {
return;
@@ -2010,10 +2012,14 @@
let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
});
- let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
- panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
- });
- let pass = t!(fs::read_to_string(&file));
+ let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() {
+ let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
+ panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
+ });
+ t!(fs::read_to_string(&file))
+ } else {
+ String::new()
+ };
let today = output(Command::new("date").arg("+%Y-%m-%d"));
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/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml
index ac6b344..da0a899 100644
--- a/src/ci/azure-pipelines/steps/run.yml
+++ b/src/ci/azure-pipelines/steps/run.yml
@@ -147,8 +147,15 @@
git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git
cd rust-toolstate
python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" ""
+ # Only check maintainers if this build is supposed to publish toolstate.
+ # Builds that are not supposed to publish don't have the access token.
+ if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
+ TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python2.7 "${BUILD_SOURCESDIRECTORY}/src/tools/publish_toolstate.py"
+ fi
cd ..
rm -rf rust-toolstate
+ env:
+ TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN)
condition: and(succeeded(), not(variables.SKIP_JOB), eq(variables['IMAGE'], 'mingw-check'))
displayName: Verify the publish_toolstate script works
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/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index d3af910..0cb91ba 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -3,7 +3,7 @@
use core::borrow::Borrow;
use core::cmp::Ordering::{self, Less, Greater, Equal};
-use core::cmp::max;
+use core::cmp::{max, min};
use core::fmt::{self, Debug};
use core::iter::{Peekable, FromIterator, FusedIterator};
use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds};
@@ -187,8 +187,8 @@
}
enum IntersectionInner<'a, T: 'a> {
Stitch {
- small_iter: Iter<'a, T>, // for size_hint, should be the smaller of the sets
- other_iter: Iter<'a, T>,
+ a: Iter<'a, T>,
+ b: Iter<'a, T>,
},
Search {
small_iter: Iter<'a, T>,
@@ -201,12 +201,12 @@
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.inner {
IntersectionInner::Stitch {
- small_iter,
- other_iter,
+ a,
+ b,
} => f
.debug_tuple("Intersection")
- .field(&small_iter)
- .field(&other_iter)
+ .field(&a)
+ .field(&b)
.finish(),
IntersectionInner::Search {
small_iter,
@@ -397,8 +397,8 @@
// Iterate both sets jointly, spotting matches along the way.
Intersection {
inner: IntersectionInner::Stitch {
- small_iter: small.iter(),
- other_iter: other.iter(),
+ a: small.iter(),
+ b: other.iter(),
},
}
} else {
@@ -1221,11 +1221,11 @@
Intersection {
inner: match &self.inner {
IntersectionInner::Stitch {
- small_iter,
- other_iter,
+ a,
+ b,
} => IntersectionInner::Stitch {
- small_iter: small_iter.clone(),
- other_iter: other_iter.clone(),
+ a: a.clone(),
+ b: b.clone(),
},
IntersectionInner::Search {
small_iter,
@@ -1245,16 +1245,16 @@
fn next(&mut self) -> Option<&'a T> {
match &mut self.inner {
IntersectionInner::Stitch {
- small_iter,
- other_iter,
+ a,
+ b,
} => {
- let mut small_next = small_iter.next()?;
- let mut other_next = other_iter.next()?;
+ let mut a_next = a.next()?;
+ let mut b_next = b.next()?;
loop {
- match Ord::cmp(small_next, other_next) {
- Less => small_next = small_iter.next()?,
- Greater => other_next = other_iter.next()?,
- Equal => return Some(small_next),
+ match Ord::cmp(a_next, b_next) {
+ Less => a_next = a.next()?,
+ Greater => b_next = b.next()?,
+ Equal => return Some(a_next),
}
}
}
@@ -1272,7 +1272,7 @@
fn size_hint(&self) -> (usize, Option<usize>) {
let min_len = match &self.inner {
- IntersectionInner::Stitch { small_iter, .. } => small_iter.len(),
+ IntersectionInner::Stitch { a, b } => min(a.len(), b.len()),
IntersectionInner::Search { small_iter, .. } => small_iter.len(),
};
(0, Some(min_len))
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 370e5cf..9e6ed92 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -117,7 +117,7 @@
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![feature(rustc_const_unstable)]
-#![feature(const_vec_new)]
+#![cfg_attr(bootstrap, feature(const_vec_new))]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit_extra, maybe_uninit_slice)]
#![feature(alloc_layout_extra)]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index cf025ee..ee75fc2 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -113,13 +113,38 @@
}
impl<T> RawVec<T, Global> {
+ /// HACK(Centril): This exists because `#[unstable]` `const fn`s needn't conform
+ /// to `min_const_fn` and so they cannot be called in `min_const_fn`s either.
+ ///
+ /// If you change `RawVec<T>::new` or dependencies, please take care to not
+ /// introduce anything that would truly violate `min_const_fn`.
+ ///
+ /// NOTE: We could avoid this hack and check conformance with some
+ /// `#[rustc_force_min_const_fn]` attribute which requires conformance
+ /// with `min_const_fn` but does not necessarily allow calling it in
+ /// `stable(...) const fn` / user code not enabling `foo` when
+ /// `#[rustc_const_unstable(feature = "foo", ..)]` is present.
+ pub const NEW: Self = Self::new();
+
/// Creates the biggest possible `RawVec` (on the system heap)
/// without allocating. If `T` has positive size, then this makes a
/// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a
/// `RawVec` with capacity `usize::MAX`. Useful for implementing
/// delayed allocation.
pub const fn new() -> Self {
- Self::new_in(Global)
+ // FIXME(Centril): Reintegrate this with `fn new_in` when we can.
+
+ // `!0` is `usize::MAX`. This branch should be stripped at compile time.
+ // FIXME(mark-i-m): use this line when `if`s are allowed in `const`:
+ //let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+
+ // `Unique::empty()` doubles as "unallocated" and "zero-sized allocation".
+ RawVec {
+ ptr: Unique::empty(),
+ // FIXME(mark-i-m): use `cap` when ifs are allowed in const
+ cap: [0, !0][(mem::size_of::<T>() == 0) as usize],
+ a: Global,
+ }
}
/// Creates a `RawVec` (on the system heap) with exactly the
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index b65f191..1166e7b 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -369,7 +369,7 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_string_new")]
+ #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))]
pub const fn new() -> String {
String { vec: Vec::new() }
}
diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs
index 62ccb53..35db18c 100644
--- a/src/liballoc/tests/btree/set.rs
+++ b/src/liballoc/tests/btree/set.rs
@@ -91,6 +91,17 @@
}
#[test]
+fn test_intersection_size_hint() {
+ let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
+ let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+ let mut iter = x.intersection(&y);
+ assert_eq!(iter.size_hint(), (0, Some(2)));
+ assert_eq!(iter.next(), Some(&3));
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+}
+
+#[test]
fn test_difference() {
fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
check(a, b, expected, |x, y, f| x.difference(y).all(f))
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index c513658..405969a 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -314,10 +314,10 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_vec_new")]
+ #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))]
pub const fn new() -> Vec<T> {
Vec {
- buf: RawVec::new(),
+ buf: RawVec::NEW,
len: 0,
}
}
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 402a7b2..06f2b7b 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -42,11 +42,11 @@
use crate::fmt;
-/// An identity function.
+/// The identity function.
///
/// Two things are important to note about this function:
///
-/// - It is not always equivalent to a closure like `|x| x` since the
+/// - It is not always equivalent to a closure like `|x| x`, since the
/// closure may coerce `x` into a different type.
///
/// - It moves the input `x` passed to the function.
@@ -56,31 +56,32 @@
///
/// # Examples
///
-/// Using `identity` to do nothing among other interesting functions:
+/// Using `identity` to do nothing in a sequence of other, interesting,
+/// functions:
///
/// ```rust
/// use std::convert::identity;
///
/// fn manipulation(x: u32) -> u32 {
-/// // Let's assume that this function does something interesting.
+/// // Let's pretend that adding one is an interesting function.
/// x + 1
/// }
///
/// let _arr = &[identity, manipulation];
/// ```
///
-/// Using `identity` to get a function that changes nothing in a conditional:
+/// Using `identity` as a "do nothing" base case in a conditional:
///
/// ```rust
/// use std::convert::identity;
///
/// # let condition = true;
-///
+/// #
/// # fn manipulation(x: u32) -> u32 { x + 1 }
-///
+/// #
/// let do_stuff = if condition { manipulation } else { identity };
///
-/// // do more interesting stuff..
+/// // Do more interesting stuff...
///
/// let _results = do_stuff(42);
/// ```
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/option.rs b/src/libcore/option.rs
index 79bd04b..5569d99 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -295,7 +295,7 @@
/// [`Pin`]: ../pin/struct.Pin.html
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
- pub fn as_pin_ref<'a>(self: Pin<&'a Option<T>>) -> Option<Pin<&'a T>> {
+ pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
unsafe {
Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x))
}
@@ -306,7 +306,7 @@
/// [`Pin`]: ../pin/struct.Pin.html
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
- pub fn as_pin_mut<'a>(self: Pin<&'a mut Option<T>>) -> Option<Pin<&'a mut T>> {
+ pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
unsafe {
Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x))
}
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 1080fd3..1dc6d54 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -233,7 +233,7 @@
//! # type Field = i32;
//! # struct Struct { field: Field }
//! impl Struct {
-//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field {
+//! fn pin_get_field(self: Pin<&mut Self>) -> &mut Field {
//! // This is okay because `field` is never considered pinned.
//! unsafe { &mut self.get_unchecked_mut().field }
//! }
@@ -257,7 +257,7 @@
//! # type Field = i32;
//! # struct Struct { field: Field }
//! impl Struct {
-//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> {
+//! fn pin_get_field(self: Pin<&mut Self>) -> Pin<&mut Field> {
//! // This is okay because `field` is pinned when `self` is.
//! unsafe { self.map_unchecked_mut(|s| &mut s.field) }
//! }
@@ -549,7 +549,7 @@
/// ruled out by the contract of `Pin::new_unchecked`.
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
+ pub fn as_ref(&self) -> Pin<&P::Target> {
unsafe { Pin::new_unchecked(&*self.pointer) }
}
@@ -584,9 +584,30 @@
/// 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(self: &mut Pin<P>) -> Pin<&mut P::Target> {
+ pub fn as_mut(&mut self) -> Pin<&mut P::Target> {
unsafe { Pin::new_unchecked(&mut *self.pointer) }
}
@@ -596,7 +617,7 @@
/// run before being overwritten, so no pinning guarantee is violated.
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub fn set(self: &mut Pin<P>, value: P::Target)
+ pub fn set(&mut self, value: P::Target)
where
P::Target: Sized,
{
@@ -621,7 +642,7 @@
///
/// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
#[stable(feature = "pin", since = "1.33.0")]
- pub unsafe fn map_unchecked<U, F>(self: Pin<&'a T>, func: F) -> Pin<&'a U> where
+ pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U> where
F: FnOnce(&T) -> &U,
{
let pointer = &*self.pointer;
@@ -648,7 +669,7 @@
/// ["pinning projections"]: ../../std/pin/index.html#projections-and-structural-pinning
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub fn get_ref(self: Pin<&'a T>) -> &'a T {
+ pub fn get_ref(self) -> &'a T {
self.pointer
}
}
@@ -657,7 +678,7 @@
/// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> {
+ pub fn into_ref(self) -> Pin<&'a T> {
Pin { pointer: self.pointer }
}
@@ -672,7 +693,7 @@
/// with the same lifetime as the original `Pin`.
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T
+ pub fn get_mut(self) -> &'a mut T
where T: Unpin,
{
self.pointer
@@ -690,7 +711,7 @@
/// instead.
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T {
+ pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
self.pointer
}
@@ -710,7 +731,7 @@
///
/// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
#[stable(feature = "pin", since = "1.33.0")]
- pub unsafe fn map_unchecked_mut<U, F>(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where
+ pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U> where
F: FnOnce(&mut T) -> &mut U,
{
let pointer = Pin::get_unchecked_mut(self);
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 66071d6..0834faf 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -30,8 +30,8 @@
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
backtrace = "0.3.3"
-parking_lot = "0.7"
-byteorder = { version = "1.1", features = ["i128"]}
+parking_lot = "0.9"
+byteorder = { version = "1.3" }
chalk-engine = { version = "0.9.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b50cfa0..48f7fc4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1316,7 +1316,7 @@
ImplTraitContext::Universal(in_band_ty_params),
);
// Set the name to `impl Bound1 + Bound2`.
- let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span);
+ let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
in_band_ty_params.push(hir::GenericParam {
hir_id: self.lower_node_id(def_node_id),
name: ParamName::Plain(ident),
@@ -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 b4fb018..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 }),
}),
@@ -192,23 +192,28 @@
vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
);
- let mut err = self.tcx().sess.struct_span_err(
- cause.span(self.tcx()),
- &format!(
- "implementation of `{}` is not general enough",
- self.tcx().def_path_str(trait_def_id),
- ),
+ let span = cause.span(self.tcx());
+ let msg = format!(
+ "implementation of `{}` is not general enough",
+ self.tcx().def_path_str(trait_def_id),
+ );
+ let mut err = self.tcx().sess.struct_span_err(span, &msg);
+ err.span_label(
+ self.tcx().def_span(trait_def_id),
+ format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)),
);
- match cause.code {
- ObligationCauseCode::ItemObligation(def_id) => {
- err.note(&format!(
- "Due to a where-clause on `{}`,",
- self.tcx().def_path_str(def_id),
- ));
- }
- _ => (),
- }
+ let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
+ err.span_label(span, "doesn't satisfy where-clause");
+ err.span_label(
+ self.tcx().def_span(def_id),
+ &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
+ );
+ true
+ } else {
+ err.span_label(span, &msg);
+ false
+ };
let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
def_id: trait_def_id,
@@ -295,6 +300,7 @@
expected_has_vid,
actual_has_vid,
any_self_ty_has_vid,
+ leading_ellipsis,
);
err
@@ -318,6 +324,7 @@
expected_has_vid: Option<usize>,
actual_has_vid: Option<usize>,
any_self_ty_has_vid: bool,
+ leading_ellipsis: bool,
) {
// HACK(eddyb) maybe move this in a more central location.
#[derive(Copy, Clone)]
@@ -392,13 +399,15 @@
let mut note = if passive_voice {
format!(
- "`{}` would have to be implemented for the type `{}`",
+ "{}`{}` would have to be implemented for the type `{}`",
+ if leading_ellipsis { "..." } else { "" },
expected_trait_ref,
expected_trait_ref.map(|tr| tr.self_ty()),
)
} else {
format!(
- "`{}` must implement `{}`",
+ "{}`{}` must implement `{}`",
+ if leading_ellipsis { "..." } else { "" },
expected_trait_ref.map(|tr| tr.self_ty()),
expected_trait_ref,
)
@@ -407,20 +416,20 @@
match (has_sub, has_sup) {
(Some(n1), Some(n2)) => {
let _ = write!(note,
- ", for any two lifetimes `'{}` and `'{}`",
+ ", for any two lifetimes `'{}` and `'{}`...",
std::cmp::min(n1, n2),
std::cmp::max(n1, n2),
);
}
(Some(n), _) | (_, Some(n)) => {
let _ = write!(note,
- ", for any lifetime `'{}`",
+ ", for any lifetime `'{}`...",
n,
);
}
(None, None) => if let Some(n) = expected_has_vid {
let _ = write!(note,
- ", for some specific lifetime `'{}`",
+ ", for some specific lifetime `'{}`...",
n,
);
},
@@ -439,13 +448,13 @@
let mut note = if passive_voice {
format!(
- "but `{}` is actually implemented for the type `{}`",
+ "...but `{}` is actually implemented for the type `{}`",
actual_trait_ref,
actual_trait_ref.map(|tr| tr.self_ty()),
)
} else {
format!(
- "but `{}` actually implements `{}`",
+ "...but `{}` actually implements `{}`",
actual_trait_ref.map(|tr| tr.self_ty()),
actual_trait_ref,
)
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 8638f42..a886c44 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/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/session/config.rs b/src/librustc/session/config.rs
index c74b2fe..723855c 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -7,6 +7,7 @@
use crate::session::search_paths::SearchPath;
use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
use rustc_target::spec::{Target, TargetTriple};
@@ -19,6 +20,7 @@
use syntax::parse::token;
use syntax::symbol::{sym, Symbol};
use syntax::feature_gate::UnstableFeatures;
+use syntax::source_map::SourceMap;
use errors::emitter::HumanReadableErrorType;
use errors::{ColorConfig, FatalError, Handler};
@@ -1850,11 +1852,20 @@
opts
}
+struct NullEmitter;
+
+impl errors::emitter::Emitter for NullEmitter {
+ fn emit_diagnostic(&mut self, _: &errors::DiagnosticBuilder<'_>) {}
+}
+
// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
syntax::with_default_globals(move || {
let cfg = cfgspecs.into_iter().map(|s| {
- let sess = ParseSess::new(FilePathMapping::empty());
+
+ let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+ let handler = Handler::with_emitter(false, None, Box::new(NullEmitter));
+ let sess = ParseSess::with_span_handler(handler, cm);
let filename = FileName::cfg_spec_source_code(&s);
let mut parser = new_parser_from_source_str(&sess, filename, s.to_string());
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 25d921b..0155803 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -205,26 +205,24 @@
fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>,
hir_id: hir::HirId,
mut_access: bool) {
- if cfg!(debug_assertions) {
- if let Some(local_id_root) = local_id_root {
- if hir_id.owner != local_id_root.index {
- ty::tls::with(|tcx| {
- bug!("node {} with HirId::owner {:?} cannot be placed in \
- TypeckTables with local_id_root {:?}",
- tcx.hir().node_to_string(hir_id),
- DefId::local(hir_id.owner),
- local_id_root)
- });
- }
- } else {
- // We use "Null Object" TypeckTables in some of the analysis passes.
- // These are just expected to be empty and their `local_id_root` is
- // `None`. Therefore we cannot verify whether a given `HirId` would
- // be a valid key for the given table. Instead we make sure that
- // nobody tries to write to such a Null Object table.
- if mut_access {
- bug!("access to invalid TypeckTables")
- }
+ if let Some(local_id_root) = local_id_root {
+ if hir_id.owner != local_id_root.index {
+ ty::tls::with(|tcx| {
+ bug!("node {} with HirId::owner {:?} cannot be placed in \
+ TypeckTables with local_id_root {:?}",
+ tcx.hir().node_to_string(hir_id),
+ DefId::local(hir_id.owner),
+ local_id_root)
+ });
+ }
+ } else {
+ // We use "Null Object" TypeckTables in some of the analysis passes.
+ // These are just expected to be empty and their `local_id_root` is
+ // `None`. Therefore we cannot verify whether a given `HirId` would
+ // be a valid key for the given table. Instead we make sure that
+ // nobody tries to write to such a Null Object table.
+ if mut_access {
+ bug!("access to invalid TypeckTables")
}
}
}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 41e4295..5ca819e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1938,9 +1938,15 @@
pub vis: Visibility,
}
-/// The definition of an abstract data type -- a struct or enum.
+/// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`.
///
/// These are all interned (by `intern_adt_def`) into the `adt_defs` table.
+///
+/// The initialism *"Adt"* stands for an [*algebraic data type (ADT)*][adt].
+/// This is slightly wrong because `union`s are not ADTs.
+/// Moreover, Rust only allows recursive data types through indirection.
+///
+/// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type
pub struct AdtDef {
/// `DefId` of the struct, enum or union item.
pub did: DefId,
@@ -2894,6 +2900,13 @@
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
-> Option<ImplOverlapKind>
{
+ // If either trait impl references an error, they're allowed to overlap,
+ // as one of them essentially doesn't exist.
+ if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) ||
+ self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) {
+ return Some(ImplOverlapKind::Permitted);
+ }
+
let is_legit = if self.features().overlapping_marker_traits {
let trait1_is_empty = self.impl_trait_ref(def_id1)
.map_or(false, |trait_ref| {
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
index cc856ba..645707c 100644
--- a/src/librustc_asan/build.rs
+++ b/src/librustc_asan/build.rs
@@ -4,6 +4,7 @@
use cmake::Config;
fn main() {
+ println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
return;
}
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_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 9f2c303..34e39af 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -226,21 +226,21 @@
for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
println!(" {}", name);
}
- println!("");
+ println!();
}
PrintRequest::CodeModels => {
println!("Available code models:");
for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
println!(" {}", name);
}
- println!("");
+ println!();
}
PrintRequest::TlsModels => {
println!("Available TLS models:");
for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
println!(" {}", name);
}
- println!("");
+ println!();
}
req => llvm_util::print(req, sess),
}
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index 89a6ec2..bc028d6 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -17,8 +17,8 @@
log = "0.4.5"
libc = "0.2.44"
jobserver = "0.1.11"
-parking_lot = "0.7"
-tempfile = "3.0.5"
+parking_lot = "0.9"
+tempfile = "3.1"
rustc_serialize = { path = "../libserialize", package = "serialize" }
syntax = { path = "../libsyntax" }
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_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 288676c..be9f79c 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -26,5 +26,5 @@
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
[dependencies.parking_lot]
-version = "0.7"
+version = "0.9"
features = ["nightly"]
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 6f40d05..6e80b48 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -149,7 +149,7 @@
#[inline]
$v const unsafe fn from_u32_unchecked(value: u32) -> Self {
- unsafe { $type { private: value } }
+ $type { private: value }
}
/// Extracts the value of this index as an integer.
diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs
index a0363e1..b2120b1 100644
--- a/src/librustc_data_structures/obligation_forest/graphviz.rs
+++ b/src/librustc_data_structures/obligation_forest/graphviz.rs
@@ -74,9 +74,9 @@
.flat_map(|i| {
let node = &self.nodes[i];
- node.parent.iter().map(|p| p.get())
- .chain(node.dependents.iter().map(|p| p.get()))
- .map(move |p| (p, i))
+ node.parent.iter()
+ .chain(node.dependents.iter())
+ .map(move |p| (p.index(), i))
})
.collect()
}
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 6c52e62..189506b 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -9,7 +9,7 @@
//! `ObligationForest` supports two main public operations (there are a
//! few others not discussed here):
//!
-//! 1. Add a new root obligations (`push_tree`).
+//! 1. Add a new root obligations (`register_obligation`).
//! 2. Process the pending obligations (`process_obligations`).
//!
//! When a new obligation `N` is added, it becomes the root of an
@@ -20,13 +20,13 @@
//! with every pending obligation (so that will include `N`, the first
//! time). The callback also receives a (mutable) reference to the
//! per-tree state `T`. The callback should process the obligation `O`
-//! that it is given and return one of three results:
+//! that it is given and return a `ProcessResult`:
//!
-//! - `Ok(None)` -> ambiguous result. Obligation was neither a success
+//! - `Unchanged` -> ambiguous result. Obligation was neither a success
//! nor a failure. It is assumed that further attempts to process the
//! obligation will yield the same result unless something in the
//! surrounding environment changes.
-//! - `Ok(Some(C))` - the obligation was *shallowly successful*. The
+//! - `Changed(C)` - the obligation was *shallowly successful*. The
//! vector `C` is a list of subobligations. The meaning of this is that
//! `O` was successful on the assumption that all the obligations in `C`
//! are also successful. Therefore, `O` is only considered a "true"
@@ -34,7 +34,7 @@
//! state and the obligations in `C` become the new pending
//! obligations. They will be processed the next time you call
//! `process_obligations`.
-//! - `Err(E)` -> obligation failed with error `E`. We will collect this
+//! - `Error(E)` -> obligation failed with error `E`. We will collect this
//! error and return it from `process_obligations`, along with the
//! "backtrace" of obligations (that is, the list of obligations up to
//! and including the root of the failed obligation). No further
@@ -47,55 +47,50 @@
//! - `completed`: a list of obligations where processing was fully
//! completed without error (meaning that all transitive subobligations
//! have also been completed). So, for example, if the callback from
-//! `process_obligations` returns `Ok(Some(C))` for some obligation `O`,
+//! `process_obligations` returns `Changed(C)` for some obligation `O`,
//! then `O` will be considered completed right away if `C` is the
//! empty vector. Otherwise it will only be considered completed once
//! all the obligations in `C` have been found completed.
//! - `errors`: a list of errors that occurred and associated backtraces
//! at the time of error, which can be used to give context to the user.
//! - `stalled`: if true, then none of the existing obligations were
-//! *shallowly successful* (that is, no callback returned `Ok(Some(_))`).
+//! *shallowly successful* (that is, no callback returned `Changed(_)`).
//! This implies that all obligations were either errors or returned an
//! ambiguous result, which means that any further calls to
//! `process_obligations` would simply yield back further ambiguous
//! results. This is used by the `FulfillmentContext` to decide when it
//! has reached a steady state.
//!
-//! #### Snapshots
-//!
-//! The `ObligationForest` supports a limited form of snapshots; see
-//! `start_snapshot`, `commit_snapshot`, and `rollback_snapshot`. In
-//! particular, you can use a snapshot to roll back new root
-//! obligations. However, it is an error to attempt to
-//! `process_obligations` during a snapshot.
-//!
//! ### Implementation details
//!
//! For the most part, comments specific to the implementation are in the
//! code. This file only contains a very high-level overview. Basically,
//! the forest is stored in a vector. Each element of the vector is a node
-//! in some tree. Each node in the vector has the index of an (optional)
-//! parent and (for convenience) its root (which may be itself). It also
-//! has a current state, described by `NodeState`. After each
-//! processing step, we compress the vector to remove completed and error
-//! nodes, which aren't needed anymore.
+//! in some tree. Each node in the vector has the index of its dependents,
+//! including the first dependent which is known as the parent. It also
+//! has a current state, described by `NodeState`. After each processing
+//! step, we compress the vector to remove completed and error nodes, which
+//! aren't needed anymore.
use crate::fx::{FxHashMap, FxHashSet};
+use crate::indexed_vec::Idx;
+use crate::newtype_index;
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash;
use std::marker::PhantomData;
-mod node_index;
-use self::node_index::NodeIndex;
-
mod graphviz;
#[cfg(test)]
mod tests;
+newtype_index! {
+ pub struct NodeIndex { .. }
+}
+
pub trait ForestObligation : Clone + Debug {
type Predicate : Clone + hash::Hash + Eq + Debug;
@@ -148,18 +143,22 @@
/// At the end of processing, those nodes will be removed by a
/// call to `compress`.
///
- /// At all times we maintain the invariant that every node appears
- /// at a higher index than its parent. This is needed by the
- /// backtrace iterator (which uses `split_at`).
+ /// Ideally, this would be an `IndexVec<NodeIndex, Node<O>>`. But that is
+ /// slower, because this vector is accessed so often that the
+ /// `u32`-to-`usize` conversions required for accesses are significant.
nodes: Vec<Node<O>>,
/// A cache of predicates that have been successfully completed.
done_cache: FxHashSet<O::Predicate>,
- /// An cache of the nodes in `nodes`, indexed by predicate.
+ /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
+ /// its contents are not guaranteed to match those of `nodes`. See the
+ /// comments in `process_obligation` for details.
waiting_cache: FxHashMap<O::Predicate, NodeIndex>,
- scratch: Option<Vec<usize>>,
+ /// A scratch vector reused in various operations, to avoid allocating new
+ /// vectors.
+ scratch: RefCell<Vec<usize>>,
obligation_tree_id_generator: ObligationTreeIdGenerator,
@@ -178,19 +177,41 @@
obligation: O,
state: Cell<NodeState>,
- /// The parent of a node - the original obligation of
- /// which it is a subobligation. Except for error reporting,
- /// it is just like any member of `dependents`.
+ /// The parent of a node - the original obligation of which it is a
+ /// subobligation. Except for error reporting, it is just like any member
+ /// of `dependents`.
+ ///
+ /// Unlike `ObligationForest::nodes`, this uses `NodeIndex` rather than
+ /// `usize` for the index, because keeping the size down is more important
+ /// than the cost of converting to a `usize` for indexing.
parent: Option<NodeIndex>,
- /// Obligations that depend on this obligation for their
- /// completion. They must all be in a non-pending state.
+ /// Obligations that depend on this obligation for their completion. They
+ /// must all be in a non-pending state.
+ ///
+ /// This uses `NodeIndex` for the same reason as `parent`.
dependents: Vec<NodeIndex>,
/// Identifier of the obligation tree to which this node belongs.
obligation_tree_id: ObligationTreeId,
}
+impl<O> Node<O> {
+ fn new(
+ parent: Option<NodeIndex>,
+ obligation: O,
+ obligation_tree_id: ObligationTreeId
+ ) -> Node<O> {
+ Node {
+ obligation,
+ state: Cell::new(NodeState::Pending),
+ parent,
+ dependents: vec![],
+ obligation_tree_id,
+ }
+ }
+}
+
/// The state of one node in some tree within the forest. This
/// represents the current state of processing for the obligation (of
/// type `O`) associated with this node.
@@ -262,7 +283,7 @@
nodes: vec![],
done_cache: Default::default(),
waiting_cache: Default::default(),
- scratch: Some(vec![]),
+ scratch: RefCell::new(vec![]),
obligation_tree_id_generator: (0..).map(ObligationTreeId),
error_cache: Default::default(),
}
@@ -275,14 +296,12 @@
}
/// Registers an obligation.
- ///
- /// This CAN be done in a snapshot
pub fn register_obligation(&mut self, obligation: O) {
// Ignore errors here - there is no guarantee of success.
let _ = self.register_obligation_at(obligation, None);
}
- // returns Err(()) if we already know this obligation failed.
+ // Returns Err(()) if we already know this obligation failed.
fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
-> Result<(), ()>
{
@@ -294,15 +313,16 @@
Entry::Occupied(o) => {
debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
obligation, parent, o.get());
- let node = &mut self.nodes[o.get().get()];
- if let Some(parent) = parent {
+ let node = &mut self.nodes[o.get().index()];
+ if let Some(parent_index) = parent {
// If the node is already in `waiting_cache`, it's already
// been marked with a parent. (It's possible that parent
// has been cleared by `apply_rewrites`, though.) So just
// dump `parent` into `node.dependents`... unless it's
// already in `node.dependents` or `node.parent`.
- if !node.dependents.contains(&parent) && Some(parent) != node.parent {
- node.dependents.push(parent);
+ if !node.dependents.contains(&parent_index) &&
+ Some(parent_index) != node.parent {
+ node.dependents.push(parent_index);
}
}
if let NodeState::Error = node.state.get() {
@@ -316,9 +336,8 @@
obligation, parent, self.nodes.len());
let obligation_tree_id = match parent {
- Some(p) => {
- let parent_node = &self.nodes[p.get()];
- parent_node.obligation_tree_id
+ Some(parent_index) => {
+ self.nodes[parent_index.index()].obligation_tree_id
}
None => self.obligation_tree_id_generator.next().unwrap()
};
@@ -342,13 +361,11 @@
}
/// Converts all remaining obligations to the given error.
- ///
- /// This cannot be done during a snapshot.
pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
let mut errors = vec![];
- for index in 0..self.nodes.len() {
- if let NodeState::Pending = self.nodes[index].state.get() {
- let backtrace = self.error_at(index);
+ for (i, node) in self.nodes.iter().enumerate() {
+ if let NodeState::Pending = node.state.get() {
+ let backtrace = self.error_at(i);
errors.push(Error {
error: error.clone(),
backtrace,
@@ -373,7 +390,6 @@
fn insert_into_error_cache(&mut self, node_index: usize) {
let node = &self.nodes[node_index];
-
self.error_cache
.entry(node.obligation_tree_id)
.or_default()
@@ -393,16 +409,22 @@
let mut errors = vec![];
let mut stalled = true;
- for index in 0..self.nodes.len() {
- debug!("process_obligations: node {} == {:?}", index, self.nodes[index]);
+ for i in 0..self.nodes.len() {
+ let node = &mut self.nodes[i];
- let result = match self.nodes[index] {
- Node { ref state, ref mut obligation, .. } if state.get() == NodeState::Pending =>
- processor.process_obligation(obligation),
+ debug!("process_obligations: node {} == {:?}", i, node);
+
+ // `processor.process_obligation` can modify the predicate within
+ // `node.obligation`, and that predicate is the key used for
+ // `self.waiting_cache`. This means that `self.waiting_cache` can
+ // get out of sync with `nodes`. It's not very common, but it does
+ // happen, and code in `compress` has to allow for it.
+ let result = match node.state.get() {
+ NodeState::Pending => processor.process_obligation(&mut node.obligation),
_ => continue
};
- debug!("process_obligations: node {} got result {:?}", index, result);
+ debug!("process_obligations: node {} got result {:?}", i, result);
match result {
ProcessResult::Unchanged => {
@@ -411,23 +433,23 @@
ProcessResult::Changed(children) => {
// We are not (yet) stalled.
stalled = false;
- self.nodes[index].state.set(NodeState::Success);
+ node.state.set(NodeState::Success);
for child in children {
let st = self.register_obligation_at(
child,
- Some(NodeIndex::new(index))
+ Some(NodeIndex::new(i))
);
if let Err(()) = st {
- // error already reported - propagate it
+ // Error already reported - propagate it
// to our node.
- self.error_at(index);
+ self.error_at(i);
}
}
}
ProcessResult::Error(err) => {
stalled = false;
- let backtrace = self.error_at(index);
+ let backtrace = self.error_at(i);
errors.push(Error {
error: err,
backtrace,
@@ -448,8 +470,6 @@
self.mark_as_waiting();
self.process_cycles(processor);
-
- // Now we have to compress the result
let completed = self.compress(do_completed);
debug!("process_obligations: complete");
@@ -465,97 +485,92 @@
/// report all cycles between them. This should be called
/// after `mark_as_waiting` marks all nodes with pending
/// subobligations as NodeState::Waiting.
- fn process_cycles<P>(&mut self, processor: &mut P)
+ fn process_cycles<P>(&self, processor: &mut P)
where P: ObligationProcessor<Obligation=O>
{
- let mut stack = self.scratch.take().unwrap();
+ let mut stack = self.scratch.replace(vec![]);
debug_assert!(stack.is_empty());
debug!("process_cycles()");
- for index in 0..self.nodes.len() {
+ for (i, node) in self.nodes.iter().enumerate() {
// For rustc-benchmarks/inflate-0.1.0 this state test is extremely
// hot and the state is almost always `Pending` or `Waiting`. It's
// a win to handle the no-op cases immediately to avoid the cost of
// the function call.
- let state = self.nodes[index].state.get();
- match state {
+ match node.state.get() {
NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {},
- _ => self.find_cycles_from_node(&mut stack, processor, index),
+ _ => self.find_cycles_from_node(&mut stack, processor, i),
}
}
debug!("process_cycles: complete");
debug_assert!(stack.is_empty());
- self.scratch = Some(stack);
+ self.scratch.replace(stack);
}
- fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>,
- processor: &mut P, index: usize)
+ fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, i: usize)
where P: ObligationProcessor<Obligation=O>
{
- let node = &self.nodes[index];
- let state = node.state.get();
- match state {
+ let node = &self.nodes[i];
+ match node.state.get() {
NodeState::OnDfsStack => {
- let index =
- stack.iter().rposition(|n| *n == index).unwrap();
- processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)),
+ let i = stack.iter().rposition(|n| *n == i).unwrap();
+ processor.process_backedge(stack[i..].iter().map(GetObligation(&self.nodes)),
PhantomData);
}
NodeState::Success => {
node.state.set(NodeState::OnDfsStack);
- stack.push(index);
- for dependent in node.parent.iter().chain(node.dependents.iter()) {
- self.find_cycles_from_node(stack, processor, dependent.get());
+ stack.push(i);
+ for index in node.parent.iter().chain(node.dependents.iter()) {
+ self.find_cycles_from_node(stack, processor, index.index());
}
stack.pop();
node.state.set(NodeState::Done);
},
NodeState::Waiting | NodeState::Pending => {
- // this node is still reachable from some pending node. We
+ // This node is still reachable from some pending node. We
// will get to it when they are all processed.
}
NodeState::Done | NodeState::Error => {
- // already processed that node
+ // Already processed that node.
}
};
}
/// Returns a vector of obligations for `p` and all of its
/// ancestors, putting them into the error state in the process.
- fn error_at(&mut self, p: usize) -> Vec<O> {
- let mut error_stack = self.scratch.take().unwrap();
+ fn error_at(&self, mut i: usize) -> Vec<O> {
+ let mut error_stack = self.scratch.replace(vec![]);
let mut trace = vec![];
- let mut n = p;
loop {
- self.nodes[n].state.set(NodeState::Error);
- trace.push(self.nodes[n].obligation.clone());
- error_stack.extend(self.nodes[n].dependents.iter().map(|x| x.get()));
+ let node = &self.nodes[i];
+ node.state.set(NodeState::Error);
+ trace.push(node.obligation.clone());
+ error_stack.extend(node.dependents.iter().map(|index| index.index()));
- // loop to the parent
- match self.nodes[n].parent {
- Some(q) => n = q.get(),
+ // Loop to the parent.
+ match node.parent {
+ Some(parent_index) => i = parent_index.index(),
None => break
}
}
while let Some(i) = error_stack.pop() {
- match self.nodes[i].state.get() {
+ let node = &self.nodes[i];
+ match node.state.get() {
NodeState::Error => continue,
- _ => self.nodes[i].state.set(NodeState::Error),
+ _ => node.state.set(NodeState::Error),
}
- let node = &self.nodes[i];
-
error_stack.extend(
- node.parent.iter().chain(node.dependents.iter()).map(|x| x.get())
+ node.parent.iter().chain(node.dependents.iter()).map(|index| index.index())
);
}
- self.scratch = Some(error_stack);
+ self.scratch.replace(error_stack);
trace
}
@@ -563,7 +578,7 @@
#[inline(always)]
fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
for dependent in node.parent.iter().chain(node.dependents.iter()) {
- self.mark_as_waiting_from(&self.nodes[dependent.get()]);
+ self.mark_as_waiting_from(&self.nodes[dependent.index()]);
}
}
@@ -609,7 +624,7 @@
#[inline(never)]
fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
let nodes_len = self.nodes.len();
- let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
+ let mut node_rewrites: Vec<_> = self.scratch.replace(vec![]);
node_rewrites.extend(0..nodes_len);
let mut dead_nodes = 0;
@@ -620,7 +635,8 @@
// self.nodes[i - dead_nodes..i] are all dead
// self.nodes[i..] are unchanged
for i in 0..self.nodes.len() {
- match self.nodes[i].state.get() {
+ let node = &self.nodes[i];
+ match node.state.get() {
NodeState::Pending | NodeState::Waiting => {
if dead_nodes > 0 {
self.nodes.swap(i, i - dead_nodes);
@@ -628,13 +644,16 @@
}
}
NodeState::Done => {
- // Avoid cloning the key (predicate) in case it exists in the waiting cache
+ // This lookup can fail because the contents of
+ // `self.waiting_cache` is not guaranteed to match those of
+ // `self.nodes`. See the comment in `process_obligation`
+ // for more details.
if let Some((predicate, _)) = self.waiting_cache
- .remove_entry(self.nodes[i].obligation.as_predicate())
+ .remove_entry(node.obligation.as_predicate())
{
self.done_cache.insert(predicate);
} else {
- self.done_cache.insert(self.nodes[i].obligation.as_predicate().clone());
+ self.done_cache.insert(node.obligation.as_predicate().clone());
}
node_rewrites[i] = nodes_len;
dead_nodes += 1;
@@ -643,7 +662,7 @@
// We *intentionally* remove the node from the cache at this point. Otherwise
// tests must come up with a different type on every type error they
// check against.
- self.waiting_cache.remove(self.nodes[i].obligation.as_predicate());
+ self.waiting_cache.remove(node.obligation.as_predicate());
node_rewrites[i] = nodes_len;
dead_nodes += 1;
self.insert_into_error_cache(i);
@@ -655,12 +674,11 @@
// No compression needed.
if dead_nodes == 0 {
node_rewrites.truncate(0);
- self.scratch = Some(node_rewrites);
+ self.scratch.replace(node_rewrites);
return if do_completed == DoCompleted::Yes { Some(vec![]) } else { None };
}
- // Pop off all the nodes we killed and extract the success
- // stories.
+ // Pop off all the nodes we killed and extract the success stories.
let successful = if do_completed == DoCompleted::Yes {
Some((0..dead_nodes)
.map(|_| self.nodes.pop().unwrap())
@@ -679,7 +697,7 @@
self.apply_rewrites(&node_rewrites);
node_rewrites.truncate(0);
- self.scratch = Some(node_rewrites);
+ self.scratch.replace(node_rewrites);
successful
}
@@ -689,58 +707,41 @@
for node in &mut self.nodes {
if let Some(index) = node.parent {
- let new_index = node_rewrites[index.get()];
- if new_index >= nodes_len {
- // parent dead due to error
+ let new_i = node_rewrites[index.index()];
+ if new_i >= nodes_len {
node.parent = None;
} else {
- node.parent = Some(NodeIndex::new(new_index));
+ node.parent = Some(NodeIndex::new(new_i));
}
}
let mut i = 0;
while i < node.dependents.len() {
- let new_index = node_rewrites[node.dependents[i].get()];
- if new_index >= nodes_len {
+ let new_i = node_rewrites[node.dependents[i].index()];
+ if new_i >= nodes_len {
node.dependents.swap_remove(i);
} else {
- node.dependents[i] = NodeIndex::new(new_index);
+ node.dependents[i] = NodeIndex::new(new_i);
i += 1;
}
}
}
- let mut kill_list = vec![];
- for (predicate, index) in &mut self.waiting_cache {
- let new_index = node_rewrites[index.get()];
- if new_index >= nodes_len {
- kill_list.push(predicate.clone());
+ // This updating of `self.waiting_cache` is necessary because the
+ // removal of nodes within `compress` can fail. See above.
+ self.waiting_cache.retain(|_predicate, index| {
+ let new_i = node_rewrites[index.index()];
+ if new_i >= nodes_len {
+ false
} else {
- *index = NodeIndex::new(new_index);
+ *index = NodeIndex::new(new_i);
+ true
}
- }
-
- for predicate in kill_list { self.waiting_cache.remove(&predicate); }
+ });
}
}
-impl<O> Node<O> {
- fn new(
- parent: Option<NodeIndex>,
- obligation: O,
- obligation_tree_id: ObligationTreeId
- ) -> Node<O> {
- Node {
- obligation,
- state: Cell::new(NodeState::Pending),
- parent,
- dependents: vec![],
- obligation_tree_id,
- }
- }
-}
-
-// I need a Clone closure
+// I need a Clone closure.
#[derive(Clone)]
struct GetObligation<'a, O>(&'a [Node<O>]);
diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs
deleted file mode 100644
index 69ea473..0000000
--- a/src/librustc_data_structures/obligation_forest/node_index.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::num::NonZeroU32;
-use std::u32;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct NodeIndex {
- index: NonZeroU32,
-}
-
-impl NodeIndex {
- #[inline]
- pub fn new(value: usize) -> NodeIndex {
- assert!(value < (u32::MAX as usize));
- NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() }
- }
-
- #[inline]
- pub fn get(self) -> usize {
- (self.index.get() - 1) as usize
- }
-}
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 005cdcf..8c5d853 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -134,8 +134,11 @@
impl Callbacks for TimePassesCallbacks {
fn config(&mut self, config: &mut interface::Config) {
+ // If a --prints=... option has been given, we don't print the "total"
+ // time because it will mess up the --prints output. See #64339.
self.time_passes =
- config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time;
+ config.opts.prints.is_empty() &&
+ (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time);
}
}
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_lint/unused.rs b/src/librustc_lint/unused.rs
index 561bf20..c397509 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -370,7 +370,8 @@
right_pos: Option<BytePos>) {
match value.node {
ast::ExprKind::Paren(ref inner) => {
- if !Self::is_expr_parens_necessary(inner, followed_by_block) {
+ if !Self::is_expr_parens_necessary(inner, followed_by_block) &&
+ value.attrs.is_empty() {
let expr_text = if let Ok(snippet) = cx.sess().source_map()
.span_to_snippet(value.span) {
snippet
@@ -618,24 +619,19 @@
}
// Trigger the lint if the nested item is a non-self single item
- let node_ident;
- match items[0].0.kind {
+ let node_name = match items[0].0.kind {
ast::UseTreeKind::Simple(rename, ..) => {
let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
if orig_ident.name == kw::SelfLower {
return;
}
- node_ident = rename.unwrap_or(orig_ident);
+ rename.unwrap_or(orig_ident).name
}
- ast::UseTreeKind::Glob => {
- node_ident = ast::Ident::from_str("*");
- }
- ast::UseTreeKind::Nested(_) => {
- return;
- }
- }
+ ast::UseTreeKind::Glob => Symbol::intern("*"),
+ ast::UseTreeKind::Nested(_) => return,
+ };
- let msg = format!("braces around {} is unnecessary", node_ident.name);
+ let msg = format!("braces around {} is unnecessary", node_name);
cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg);
}
}
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
index d5f3e37..73720d8 100644
--- a/src/librustc_lsan/build.rs
+++ b/src/librustc_lsan/build.rs
@@ -4,6 +4,7 @@
use cmake::Config;
fn main() {
+ println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
return;
}
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index d6450f0..a1e3bbc 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -444,7 +444,8 @@
.insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
LoadedMacro::MacroDef(ast::Item {
- ident: ast::Ident::from_str(&name.as_str()),
+ // FIXME: cross-crate hygiene
+ ident: ast::Ident::with_dummy_span(name.as_symbol()),
id: ast::DUMMY_NODE_ID,
span: local_span,
attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index e027360..0691390 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -24,6 +24,6 @@
rustc_serialize = { path = "../libserialize", package = "serialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
-byteorder = { version = "1.1", features = ["i128"] }
+byteorder = { version = "1.3" }
rustc_apfloat = { path = "../librustc_apfloat" }
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 4b4516d..81359c6 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -614,8 +614,9 @@
projection,
} = first_borrowed_place;
- for (i, elem) in projection.iter().enumerate().rev() {
- let proj_base = &projection[..i];
+ let mut cursor = &**projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
match elem {
ProjectionElem::Field(field, _) if union_ty(base, proj_base).is_some() => {
@@ -637,8 +638,9 @@
projection,
} = second_borrowed_place;
- for (i, elem) in projection.iter().enumerate().rev() {
- let proj_base = &projection[..i];
+ let mut cursor = &**projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
if let ProjectionElem::Field(field, _) = elem {
if let Some(union_ty) = union_ty(base, proj_base) {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 5ef7046..1d35762 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1758,7 +1758,10 @@
debug!("check_if_assigned_path_is_moved place: {:?}", place);
// None case => assigning to `x` does not require `x` be initialized.
- for (i, elem) in place.projection.iter().enumerate().rev() {
+ let mut cursor = &*place.projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
+
match elem {
ProjectionElem::Index(_/*operand*/) |
ProjectionElem::ConstantIndex { .. } |
@@ -1771,8 +1774,6 @@
// assigning to (*P) requires P to be initialized
ProjectionElem::Deref => {
- let proj_base = &place.projection[..i];
-
self.check_if_full_path_is_moved(
location, InitializationRequiringAction::Use,
(PlaceRef {
@@ -1790,7 +1791,6 @@
}
ProjectionElem::Field(..) => {
- let proj_base = &place.projection[..i];
// if type of `P` has a dtor, then
// assigning to `P.f` requires `P` itself
// be already initialized
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index efa1858..26a89b4 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -13,7 +13,7 @@
use rustc::mir::{ConstraintCategory, Location, Body};
use rustc::ty::{self, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_errors::DiagnosticBuilder;
use std::collections::VecDeque;
use syntax::errors::Applicability;
use syntax::symbol::kw;
@@ -22,7 +22,7 @@
mod region_name;
mod var_name;
-crate use self::region_name::{RegionName, RegionNameSource};
+crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
impl ConstraintDescription for ConstraintCategory {
fn description(&self) -> &'static str {
@@ -54,6 +54,39 @@
NotVisited,
}
+/// Various pieces of state used when reporting borrow checker errors.
+pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
+ /// The region inference context used for borrow chekcing this MIR body.
+ #[allow(dead_code)] // FIXME(mark-i-m): used by outlives suggestions
+ region_infcx: &'b RegionInferenceContext<'tcx>,
+
+ /// The inference context used for type checking.
+ infcx: &'b InferCtxt<'a, 'tcx>,
+
+ /// The MIR def we are reporting errors on.
+ mir_def_id: DefId,
+
+ /// The MIR body we are reporting errors on (for convenience).
+ body: &'b Body<'tcx>,
+
+ /// Any upvars for the MIR body we have kept track of during borrow checking.
+ upvars: &'b [Upvar],
+}
+
+/// Information about the various region constraints involved in a borrow checker error.
+#[derive(Clone, Debug)]
+pub struct ErrorConstraintInfo {
+ // fr: outlived_fr
+ fr: RegionVid,
+ fr_is_local: bool,
+ outlived_fr: RegionVid,
+ outlived_fr_is_local: bool,
+
+ // Category and span for best blame constraint
+ category: ConstraintCategory,
+ span: Span,
+}
+
impl<'tcx> RegionInferenceContext<'tcx> {
/// Tries to find the best constraint to blame for the fact that
/// `R: from_region`, where `R` is some region that meets
@@ -257,16 +290,16 @@
/// ```
///
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
- pub(super) fn report_error(
- &self,
+ pub(super) fn report_error<'a>(
+ &'a self,
body: &Body<'tcx>,
upvars: &[Upvar],
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &'a InferCtxt<'a, 'tcx>,
mir_def_id: DefId,
fr: RegionVid,
outlived_fr: RegionVid,
- errors_buffer: &mut Vec<Diagnostic>,
- ) {
+ renctx: &mut RegionErrorNamingCtx,
+ ) -> DiagnosticBuilder<'a> {
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
let (category, _, span) = self.best_blame_constraint(body, fr, |r| {
@@ -279,8 +312,7 @@
let tables = infcx.tcx.typeck_tables_of(mir_def_id);
let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables));
if let Some(diag) = nice.try_report_from_nll() {
- diag.buffer(errors_buffer);
- return;
+ return diag;
}
}
@@ -293,45 +325,28 @@
"report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
fr_is_local, outlived_fr_is_local, category
);
+
+ let errctx = ErrorReportingCtx {
+ region_infcx: self,
+ infcx,
+ mir_def_id,
+ body,
+ upvars,
+ };
+
+ let errci = ErrorConstraintInfo {
+ fr, outlived_fr, fr_is_local, outlived_fr_is_local, category, span
+ };
+
match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
- self.report_fnmut_error(
- body,
- upvars,
- infcx,
- mir_def_id,
- fr,
- outlived_fr,
- span,
- errors_buffer,
- )
+ self.report_fnmut_error(&errctx, &errci, renctx)
}
(ConstraintCategory::Assignment, true, false)
- | (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
- body,
- upvars,
- infcx,
- mir_def_id,
- fr,
- outlived_fr,
- category,
- span,
- errors_buffer,
- ),
- _ => self.report_general_error(
- body,
- upvars,
- infcx,
- mir_def_id,
- fr,
- fr_is_local,
- outlived_fr,
- outlived_fr_is_local,
- category,
- span,
- errors_buffer,
- ),
- };
+ | (ConstraintCategory::CallArgument, true, false) =>
+ self.report_escaping_data_error(&errctx, &errci, renctx),
+ _ => self.report_general_error(&errctx, &errci, renctx),
+ }
}
/// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +394,19 @@
/// ```
fn report_fnmut_error(
&self,
- body: &Body<'tcx>,
- upvars: &[Upvar],
- infcx: &InferCtxt<'_, 'tcx>,
- mir_def_id: DefId,
- _fr: RegionVid,
- outlived_fr: RegionVid,
- span: Span,
- errors_buffer: &mut Vec<Diagnostic>,
- ) {
- let mut diag = infcx
+ errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+ errci: &ErrorConstraintInfo,
+ renctx: &mut RegionErrorNamingCtx,
+ ) -> DiagnosticBuilder<'_> {
+ let ErrorConstraintInfo {
+ outlived_fr, span, ..
+ } = errci;
+
+ let mut diag = errctx
+ .infcx
.tcx
.sess
- .struct_span_err(span, "captured variable cannot escape `FnMut` closure body");
+ .struct_span_err(*span, "captured variable cannot escape `FnMut` closure body");
// We should check if the return type of this closure is in fact a closure - in that
// case, we can special case the error further.
@@ -403,11 +418,9 @@
"returns a reference to a captured variable which escapes the closure body"
};
- diag.span_label(span, message);
+ diag.span_label(*span, message);
- match self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, &mut 1)
- .unwrap().source
- {
+ match self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap().source {
RegionNameSource::NamedEarlyBoundRegion(fr_span)
| RegionNameSource::NamedFreeRegion(fr_span)
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -427,7 +440,7 @@
);
diag.note("...therefore, they cannot allow references to captured variables to escape");
- diag.buffer(errors_buffer);
+ diag
}
/// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +457,22 @@
/// ```
fn report_escaping_data_error(
&self,
- body: &Body<'tcx>,
- upvars: &[Upvar],
- infcx: &InferCtxt<'_, 'tcx>,
- mir_def_id: DefId,
- fr: RegionVid,
- outlived_fr: RegionVid,
- category: ConstraintCategory,
- span: Span,
- errors_buffer: &mut Vec<Diagnostic>,
- ) {
+ errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+ errci: &ErrorConstraintInfo,
+ renctx: &mut RegionErrorNamingCtx,
+ ) -> DiagnosticBuilder<'_> {
+ let ErrorReportingCtx {
+ infcx, body, upvars, ..
+ } = errctx;
+
+ let ErrorConstraintInfo {
+ span, category, ..
+ } = errci;
+
let fr_name_and_span =
- self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, fr);
+ self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.fr);
let outlived_fr_name_and_span =
- self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, outlived_fr);
+ self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.outlived_fr);
let escapes_from = match self.universal_regions.defining_ty {
DefiningTy::Closure(..) => "closure",
@@ -469,27 +484,23 @@
// Revert to the normal error in these cases.
// Assignments aren't "escapes" in function items.
if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none())
- || (category == ConstraintCategory::Assignment && escapes_from == "function")
+ || (*category == ConstraintCategory::Assignment && escapes_from == "function")
|| escapes_from == "const"
{
return self.report_general_error(
- body,
- upvars,
- infcx,
- mir_def_id,
- fr,
- true,
- outlived_fr,
- false,
- category,
- span,
- errors_buffer,
+ errctx,
+ &ErrorConstraintInfo {
+ fr_is_local: true,
+ outlived_fr_is_local: false,
+ .. *errci
+ },
+ renctx,
);
}
let mut diag = borrowck_errors::borrowed_data_escapes_closure(
infcx.tcx,
- span,
+ *span,
escapes_from,
);
@@ -513,12 +524,12 @@
);
diag.span_label(
- span,
+ *span,
format!("`{}` escapes the {} body here", fr_name, escapes_from),
);
}
- diag.buffer(errors_buffer);
+ diag
}
/// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +549,37 @@
/// ```
fn report_general_error(
&self,
- body: &Body<'tcx>,
- upvars: &[Upvar],
- infcx: &InferCtxt<'_, 'tcx>,
- mir_def_id: DefId,
- fr: RegionVid,
- fr_is_local: bool,
- outlived_fr: RegionVid,
- outlived_fr_is_local: bool,
- category: ConstraintCategory,
- span: Span,
- errors_buffer: &mut Vec<Diagnostic>,
- ) {
+ errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+ errci: &ErrorConstraintInfo,
+ renctx: &mut RegionErrorNamingCtx,
+ ) -> DiagnosticBuilder<'_> {
+ let ErrorReportingCtx {
+ infcx, mir_def_id, ..
+ } = errctx;
+ let ErrorConstraintInfo {
+ fr, fr_is_local, outlived_fr, outlived_fr_is_local, span, category, ..
+ } = errci;
+
let mut diag = infcx.tcx.sess.struct_span_err(
- span,
+ *span,
"lifetime may not live long enough"
);
- let counter = &mut 1;
- let fr_name = self.give_region_a_name(
- infcx, body, upvars, mir_def_id, fr, counter).unwrap();
- fr_name.highlight_region_name(&mut diag);
- let outlived_fr_name =
- self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_fr, counter).unwrap();
- outlived_fr_name.highlight_region_name(&mut diag);
-
- let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
+ let mir_def_name = if infcx.tcx.is_closure(*mir_def_id) {
"closure"
} else {
"function"
};
+ let fr_name = self.give_region_a_name(errctx, renctx, *fr).unwrap();
+ fr_name.highlight_region_name(&mut diag);
+ let outlived_fr_name = self.give_region_a_name(errctx, renctx, *outlived_fr).unwrap();
+ outlived_fr_name.highlight_region_name(&mut diag);
+
match (category, outlived_fr_is_local, fr_is_local) {
(ConstraintCategory::Return, true, _) => {
diag.span_label(
- span,
+ *span,
format!(
"{} was supposed to return data with lifetime `{}` but it is returning \
data with lifetime `{}`",
@@ -582,7 +589,7 @@
}
_ => {
diag.span_label(
- span,
+ *span,
format!(
"{}requires that `{}` must outlive `{}`",
category.description(),
@@ -593,9 +600,9 @@
}
}
- self.add_static_impl_trait_suggestion(infcx, &mut diag, fr, fr_name, outlived_fr);
+ self.add_static_impl_trait_suggestion(infcx, &mut diag, *fr, fr_name, *outlived_fr);
- diag.buffer(errors_buffer);
+ diag
}
/// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +711,14 @@
borrow_region,
|r| self.provides_universal_region(r, borrow_region, outlived_region)
);
- let outlived_fr_name =
- self.give_region_a_name(infcx, body, upvars, mir_def_id, outlived_region, &mut 1);
+
+ let mut renctx = RegionErrorNamingCtx::new();
+ let errctx = ErrorReportingCtx {
+ infcx, body, upvars, mir_def_id,
+ region_infcx: self,
+ };
+ let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region);
+
(category, from_closure, span, outlived_fr_name)
}
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 75a3162..6fa9426 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -1,5 +1,9 @@
use std::fmt::{self, Display};
-use crate::borrow_check::nll::region_infer::RegionInferenceContext;
+
+use crate::borrow_check::nll::region_infer::{
+ RegionInferenceContext,
+ error_reporting::ErrorReportingCtx,
+};
use crate::borrow_check::nll::universal_regions::DefiningTy;
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::Upvar;
@@ -13,29 +17,75 @@
use rustc::ty::print::RegionHighlightMode;
use rustc_errors::DiagnosticBuilder;
use syntax::symbol::kw;
-use syntax_pos::Span;
-use syntax_pos::symbol::InternedString;
+use rustc_data_structures::fx::FxHashMap;
+use syntax_pos::{Span, symbol::InternedString};
-#[derive(Debug)]
+/// A name for a particular region used in emitting diagnostics. This name could be a generated
+/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
+#[derive(Debug, Clone)]
crate struct RegionName {
+ /// The name of the region (interned).
crate name: InternedString,
+ /// Where the region comes from.
crate source: RegionNameSource,
}
-#[derive(Debug)]
+/// Denotes the source of a region that is named by a `RegionName`. For example, a free region that
+/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`.
+/// This helps to print the right kinds of diagnostics.
+#[derive(Debug, Clone)]
crate enum RegionNameSource {
+ /// A bound (not free) region that was substituted at the def site (not an HRTB).
NamedEarlyBoundRegion(Span),
+ /// A free region that the user has a name (`'a`) for.
NamedFreeRegion(Span),
+ /// The `'static` region.
Static,
+ /// The free region corresponding to the environment of a closure.
SynthesizedFreeEnvRegion(Span, String),
+ /// The region name corresponds to a region where the type annotation is completely missing
+ /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
CannotMatchHirTy(Span, String),
+ /// The region name corresponds a reference that was found by traversing the type in the HIR.
MatchedHirTy(Span),
+ /// A region name from the generics list of a struct/enum/union.
MatchedAdtAndSegment(Span),
+ /// The region corresponding to a closure upvar.
AnonRegionFromUpvar(Span, String),
+ /// The region corresponding to the return type of a closure.
AnonRegionFromOutput(Span, String, String),
AnonRegionFromYieldTy(Span, String),
}
+/// Records region names that have been assigned before so that we can use the same ones in later
+/// diagnostics.
+#[derive(Debug, Clone)]
+crate struct RegionErrorNamingCtx {
+ /// Record the region names generated for each region in the given
+ /// MIR def so that we can reuse them later in help/error messages.
+ renctx: FxHashMap<RegionVid, RegionName>,
+
+ /// The counter for generating new region names.
+ counter: usize,
+}
+
+impl RegionErrorNamingCtx {
+ crate fn new() -> Self {
+ Self {
+ counter: 1,
+ renctx: FxHashMap::default(),
+ }
+ }
+
+ crate fn get(&self, region: &RegionVid) -> Option<&RegionName> {
+ self.renctx.get(region)
+ }
+
+ crate fn insert(&mut self, region: RegionVid, name: RegionName) {
+ self.renctx.insert(region, name);
+ }
+}
+
impl RegionName {
#[allow(dead_code)]
crate fn was_named(&self) -> bool {
@@ -63,43 +113,40 @@
self.name
}
- crate fn highlight_region_name(
- &self,
- diag: &mut DiagnosticBuilder<'_>
- ) {
+ crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) {
match &self.source {
- RegionNameSource::NamedFreeRegion(span) |
- RegionNameSource::NamedEarlyBoundRegion(span) => {
- diag.span_label(
- *span,
- format!("lifetime `{}` defined here", self),
- );
- },
+ RegionNameSource::NamedFreeRegion(span)
+ | RegionNameSource::NamedEarlyBoundRegion(span) => {
+ diag.span_label(*span, format!("lifetime `{}` defined here", self));
+ }
RegionNameSource::SynthesizedFreeEnvRegion(span, note) => {
diag.span_label(
*span,
format!("lifetime `{}` represents this closure's body", self),
);
diag.note(¬e);
- },
+ }
RegionNameSource::CannotMatchHirTy(span, type_name) => {
diag.span_label(*span, format!("has type `{}`", type_name));
- },
+ }
RegionNameSource::MatchedHirTy(span) => {
diag.span_label(
*span,
format!("let's call the lifetime of this reference `{}`", self),
);
- },
+ }
RegionNameSource::MatchedAdtAndSegment(span) => {
diag.span_label(*span, format!("let's call this `{}`", self));
- },
+ }
RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => {
diag.span_label(
*span,
- format!("lifetime `{}` appears in the type of `{}`", self, upvar_name),
+ format!(
+ "lifetime `{}` appears in the type of `{}`",
+ self, upvar_name
+ ),
);
- },
+ }
RegionNameSource::AnonRegionFromOutput(span, mir_description, type_name) => {
diag.span_label(
*span,
@@ -151,39 +198,49 @@
/// and then return the name `'1` for us to use.
crate fn give_region_a_name(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
- body: &Body<'tcx>,
- upvars: &[Upvar],
- mir_def_id: DefId,
+ errctx: &ErrorReportingCtx<'_, '_, 'tcx>,
+ renctx: &mut RegionErrorNamingCtx,
fr: RegionVid,
- counter: &mut usize,
) -> Option<RegionName> {
- debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
+ let ErrorReportingCtx {
+ infcx, body, mir_def_id, upvars, ..
+ } = errctx;
+
+ debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
assert!(self.universal_regions.is_universal_region(fr));
- let value = self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter)
+ if let Some(value) = renctx.get(&fr) {
+ return Some(value.clone());
+ }
+
+ let value = self
+ .give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx)
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_arguments(
- infcx, body, mir_def_id, fr, counter,
+ infcx, body, *mir_def_id, fr, renctx,
)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_upvars(
- infcx.tcx, upvars, fr, counter,
+ infcx.tcx, upvars, fr, renctx
)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_output(
- infcx, body, mir_def_id, fr, counter,
+ infcx, body, *mir_def_id, fr, renctx,
)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_yield_ty(
- infcx, body, mir_def_id, fr, counter,
+ infcx, body, *mir_def_id, fr, renctx,
)
});
+ if let Some(ref value) = value {
+ renctx.insert(fr, value.clone());
+ }
+
debug!("give_region_a_name: gave name {:?}", value);
value
}
@@ -197,7 +254,7 @@
tcx: TyCtxt<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let error_region = self.to_error_region(fr)?;
@@ -208,7 +265,7 @@
let span = self.get_named_span(tcx, error_region, ebr.name);
Some(RegionName {
name: ebr.name,
- source: RegionNameSource::NamedEarlyBoundRegion(span)
+ source: RegionNameSource::NamedEarlyBoundRegion(span),
})
} else {
None
@@ -227,12 +284,10 @@
name,
source: RegionNameSource::NamedFreeRegion(span),
})
- },
+ }
ty::BoundRegion::BrEnv => {
- let mir_hir_id = tcx.hir()
- .as_local_hir_id(mir_def_id)
- .expect("non-local mir");
+ let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
let def_ty = self.universal_regions.defining_ty;
if let DefiningTy::Closure(def_id, substs) = def_ty {
@@ -243,7 +298,7 @@
} else {
bug!("Closure is not defined by a closure expr");
};
- let region_name = self.synthesize_region_name(counter);
+ let region_name = self.synthesize_region_name(renctx);
let closure_kind_ty = substs.closure_kind_ty(def_id, tcx);
let note = match closure_kind_ty.to_opt_closure_kind() {
@@ -265,7 +320,7 @@
name: region_name,
source: RegionNameSource::SynthesizedFreeEnvRegion(
args_span,
- note.to_string()
+ note.to_string(),
),
})
} else {
@@ -335,7 +390,7 @@
body: &Body<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
@@ -349,12 +404,12 @@
fr,
arg_ty,
argument_index,
- counter,
+ renctx,
) {
return Some(region_name);
}
- self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, counter)
+ self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, renctx)
}
fn give_name_if_we_can_match_hir_ty_from_argument(
@@ -365,7 +420,7 @@
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
argument_index: usize,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?;
let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
@@ -379,7 +434,7 @@
body,
needle_fr,
argument_ty,
- counter,
+ renctx,
),
_ => self.give_name_if_we_can_match_hir_ty(
@@ -387,7 +442,7 @@
needle_fr,
argument_ty,
argument_hir_ty,
- counter,
+ renctx,
),
}
}
@@ -409,10 +464,11 @@
body: &Body<'tcx>,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
+ let counter = renctx.counter;
let mut highlight = RegionHighlightMode::default();
- highlight.highlighting_region_vid(needle_fr, *counter);
+ highlight.highlighting_region_vid(needle_fr, counter);
let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)).0;
debug!(
@@ -428,7 +484,7 @@
// This counter value will already have been used, so this function will increment
// it so the next value will be used next and return the region name that would
// have been used.
- name: self.synthesize_region_name(counter),
+ name: self.synthesize_region_name(renctx),
source: RegionNameSource::CannotMatchHirTy(span, type_name),
})
} else {
@@ -455,7 +511,7 @@
/// type. Once we find that, we can use the span of the `hir::Ty`
/// to add the highlight.
///
- /// This is a somewhat imperfect process, so long the way we also
+ /// This is a somewhat imperfect process, so along the way we also
/// keep track of the **closest** type we've found. If we fail to
/// find the exact `&` or `'_` to highlight, then we may fall back
/// to highlighting that closest type instead.
@@ -465,7 +521,7 @@
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
argument_hir_ty: &hir::Ty,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty)> =
&mut vec![(argument_ty, argument_hir_ty)];
@@ -483,7 +539,7 @@
hir::TyKind::Rptr(_lifetime, referent_hir_ty),
) => {
if region.to_region_vid() == needle_fr {
- let region_name = self.synthesize_region_name(counter);
+ let region_name = self.synthesize_region_name(renctx);
// Just grab the first character, the `&`.
let source_map = tcx.sess.source_map();
@@ -515,7 +571,7 @@
substs,
needle_fr,
last_segment,
- counter,
+ renctx,
search_stack,
) {
return Some(name);
@@ -559,18 +615,19 @@
substs: SubstsRef<'tcx>,
needle_fr: RegionVid,
last_segment: &'hir hir::PathSegment,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty)>,
) -> Option<RegionName> {
// Did the user give explicit arguments? (e.g., `Foo<..>`)
let args = last_segment.args.as_ref()?;
- let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
+ let lifetime =
+ self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
match lifetime.name {
hir::LifetimeName::Param(_)
| hir::LifetimeName::Error
| hir::LifetimeName::Static
| hir::LifetimeName::Underscore => {
- let region_name = self.synthesize_region_name(counter);
+ let region_name = self.synthesize_region_name(renctx);
let ampersand_span = lifetime.span;
Some(RegionName {
name: region_name,
@@ -657,12 +714,12 @@
tcx: TyCtxt<'tcx>,
upvars: &[Upvar],
fr: RegionVid,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
let (upvar_name, upvar_span) =
self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
- let region_name = self.synthesize_region_name(counter);
+ let region_name = self.synthesize_region_name(renctx);
Some(RegionName {
name: region_name,
@@ -680,7 +737,7 @@
body: &Body<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
let tcx = infcx.tcx;
@@ -694,7 +751,7 @@
}
let mut highlight = RegionHighlightMode::default();
- highlight.highlighting_region_vid(fr, *counter);
+ highlight.highlighting_region_vid(fr, renctx.counter);
let type_name = infcx.extract_type_name(&return_ty, Some(highlight)).0;
let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
@@ -725,11 +782,11 @@
// This counter value will already have been used, so this function will increment it
// so the next value will be used next and return the region name that would have been
// used.
- name: self.synthesize_region_name(counter),
+ name: self.synthesize_region_name(renctx),
source: RegionNameSource::AnonRegionFromOutput(
return_span,
mir_description.to_string(),
- type_name
+ type_name,
),
})
}
@@ -740,7 +797,7 @@
body: &Body<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
- counter: &mut usize,
+ renctx: &mut RegionErrorNamingCtx,
) -> Option<RegionName> {
// Note: generators from `async fn` yield `()`, so we don't have to
// worry about them here.
@@ -757,7 +814,7 @@
}
let mut highlight = RegionHighlightMode::default();
- highlight.highlighting_region_vid(fr, *counter);
+ highlight.highlighting_region_vid(fr, renctx.counter);
let type_name = infcx.extract_type_name(&yield_ty, Some(highlight)).0;
let mir_hir_id = tcx.hir().as_local_hir_id(mir_def_id).expect("non-local mir");
@@ -780,16 +837,15 @@
);
Some(RegionName {
- name: self.synthesize_region_name(counter),
+ name: self.synthesize_region_name(renctx),
source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
})
}
- /// Creates a synthetic region named `'1`, incrementing the
- /// counter.
- fn synthesize_region_name(&self, counter: &mut usize) -> InternedString {
- let c = *counter;
- *counter += 1;
+ /// Creates a synthetic region named `'1`, incrementing the counter.
+ fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString {
+ let c = renctx.counter;
+ renctx.counter += 1;
InternedString::intern(&format!("'{:?}", c))
}
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 4038872..78e7943 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1,15 +1,20 @@
-use super::universal_regions::UniversalRegions;
-use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
-use crate::borrow_check::nll::constraints::{
- ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
+use std::rc::Rc;
+
+use crate::borrow_check::nll::{
+ constraints::{
+ graph::NormalConstraintGraph,
+ ConstraintSccIndex,
+ OutlivesConstraint,
+ OutlivesConstraintSet,
+ },
+ member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
+ region_infer::values::{
+ PlaceholderIndices, RegionElement, ToElementIndex
+ },
+ type_check::{free_region_relations::UniversalRegionRelations, Locations},
};
-use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
-use crate::borrow_check::nll::region_infer::values::{
- PlaceholderIndices, RegionElement, ToElementIndex,
-};
-use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
-use crate::borrow_check::nll::type_check::Locations;
use crate::borrow_check::Upvar;
+
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::QueryOutlivesConstraint;
use rustc::infer::opaque_types;
@@ -31,16 +36,16 @@
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use syntax_pos::Span;
-use std::rc::Rc;
+crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
+use self::values::{LivenessValues, RegionValueElements, RegionValues};
+use super::universal_regions::UniversalRegions;
+use super::ToRegionVid;
mod dump_mir;
mod error_reporting;
-crate use self::error_reporting::{RegionName, RegionNameSource};
mod graphviz;
-pub mod values;
-use self::values::{LivenessValues, RegionValueElements, RegionValues};
-use super::ToRegionVid;
+pub mod values;
pub struct RegionInferenceContext<'tcx> {
/// Contains the definition for every region variable. Region
@@ -487,6 +492,12 @@
errors_buffer,
);
+ // If we produce any errors, we keep track of the names of all regions, so that we can use
+ // the same error names in any suggestions we produce. Note that we need names to be unique
+ // across different errors for the same MIR def so that we can make suggestions that fix
+ // multiple problems.
+ let mut region_naming = RegionErrorNamingCtx::new();
+
self.check_universal_regions(
infcx,
body,
@@ -494,6 +505,7 @@
mir_def_id,
outlives_requirements.as_mut(),
errors_buffer,
+ &mut region_naming,
);
self.check_member_constraints(infcx, mir_def_id, errors_buffer);
@@ -1312,6 +1324,7 @@
mir_def_id: DefId,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut Vec<Diagnostic>,
+ region_naming: &mut RegionErrorNamingCtx,
) {
for (fr, fr_definition) in self.definitions.iter_enumerated() {
match fr_definition.origin {
@@ -1327,6 +1340,7 @@
fr,
&mut propagated_outlives_requirements,
errors_buffer,
+ region_naming,
);
}
@@ -1358,6 +1372,7 @@
longer_fr: RegionVid,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut Vec<Diagnostic>,
+ region_naming: &mut RegionErrorNamingCtx,
) {
debug!("check_universal_region(fr={:?})", longer_fr);
@@ -1385,6 +1400,7 @@
mir_def_id,
propagated_outlives_requirements,
errors_buffer,
+ region_naming,
);
return;
}
@@ -1401,8 +1417,13 @@
mir_def_id,
propagated_outlives_requirements,
errors_buffer,
+ region_naming,
) {
// continuing to iterate just reports more errors than necessary
+ //
+ // FIXME It would also allow us to report more Outlives Suggestions, though, so
+ // it's not clear that that's a bad thing. Somebody should try commenting out this
+ // line and see it is actually a regression.
return;
}
}
@@ -1418,6 +1439,7 @@
mir_def_id: DefId,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut Vec<Diagnostic>,
+ region_naming: &mut RegionErrorNamingCtx,
) -> Option<ErrorReported> {
// If it is known that `fr: o`, carry on.
if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
@@ -1466,7 +1488,18 @@
//
// Note: in this case, we use the unapproximated regions to report the
// error. This gives better error messages in some cases.
- self.report_error(body, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
+ let db = self.report_error(
+ body,
+ upvars,
+ infcx,
+ mir_def_id,
+ longer_fr,
+ shorter_fr,
+ region_naming,
+ );
+
+ db.buffer(errors_buffer);
+
Some(ErrorReported)
}
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 1d17bae..62bff34 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -2417,9 +2417,12 @@
"add_reborrow_constraint({:?}, {:?}, {:?})",
location, borrow_region, borrowed_place
);
- for (i, elem) in borrowed_place.projection.iter().enumerate().rev() {
+
+ let mut cursor = &*borrowed_place.projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
+
debug!("add_reborrow_constraint - iteration {:?}", elem);
- let proj_base = &borrowed_place.projection[..i];
match elem {
ProjectionElem::Deref => {
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index aa261f8..2b0237c 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -1296,8 +1296,9 @@
// Insert a Shallow borrow of the prefixes of any fake borrows.
for place in fake_borrows
{
- for (i, elem) in place.projection.iter().enumerate().rev() {
- let proj_base = &place.projection[..i];
+ let mut cursor = &*place.projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
if let ProjectionElem::Deref = elem {
// Insert a shallow borrow after a deref. For other
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 57ddaa4..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};
@@ -134,9 +135,8 @@
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
cid: GlobalId<'tcx>,
body: &'mir mir::Body<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
- debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
+ debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
let tcx = ecx.tcx.tcx;
let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
assert!(!layout.is_unsized());
@@ -162,7 +162,6 @@
ecx,
cid.instance.def_id(),
ret,
- param_env,
)?;
debug!("eval_body_using_ecx done: {:?}", *ret);
@@ -604,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)
})
@@ -658,7 +674,7 @@
let res = ecx.load_mir(cid.instance.def, cid.promoted);
res.and_then(
- |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env)
+ |body| eval_body_using_ecx(&mut ecx, cid, body)
).and_then(|place| {
Ok(RawConst {
alloc_id: place.ptr.assert_ptr().alloc_id,
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/intern.rs b/src/librustc_mir/interpret/intern.rs
index 4cbbc0f..95647ce 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -3,7 +3,7 @@
//! After a const evaluation has computed a value, before we destroy the const evaluator's session
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.
-use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
+use rustc::ty::{Ty, self};
use rustc::mir::interpret::{InterpResult, ErrorHandled};
use rustc::hir;
use rustc::hir::def_id::DefId;
@@ -11,32 +11,29 @@
use rustc_data_structures::fx::FxHashSet;
use syntax::ast::Mutability;
-use syntax_pos::Span;
use super::{
- ValueVisitor, MemoryKind, Pointer, AllocId, MPlaceTy, Scalar,
+ ValueVisitor, MemoryKind, AllocId, MPlaceTy, Scalar,
};
use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
struct InternVisitor<'rt, 'mir, 'tcx> {
- /// previously encountered safe references
- ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
+ /// The ectx from which we intern.
ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
- param_env: ParamEnv<'tcx>,
+ /// Previously encountered safe references.
+ ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
+ /// A list of all encountered allocations. After type-based interning, we traverse this list to
+ /// also intern allocations that are only referenced by a raw pointer or inside a union.
+ leftover_allocations: &'rt mut FxHashSet<AllocId>,
/// The root node of the value that we're looking at. This field is never mutated and only used
/// for sanity assertions that will ICE when `const_qualif` screws up.
mode: InternMode,
/// This field stores the mutability of the value *currently* being checked.
- /// It is set to mutable when an `UnsafeCell` is encountered
- /// When recursing across a reference, we don't recurse but store the
- /// value to be checked in `ref_tracking` together with the mutability at which we are checking
- /// the value.
- /// When encountering an immutable reference, we treat everything as immutable that is behind
- /// it.
+ /// When encountering a mutable reference, we determine the pointee mutability
+ /// taking into account the mutability of the context: `& &mut i32` is entirely immutable,
+ /// despite the nested mutable reference!
+ /// The field gets updated when an `UnsafeCell` is encountered.
mutability: Mutability,
- /// A list of all encountered relocations. After type-based interning, we traverse this list to
- /// also intern allocations that are only referenced by a raw pointer or inside a union.
- leftover_relocations: &'rt mut FxHashSet<AllocId>,
}
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
@@ -45,9 +42,10 @@
/// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mut`
/// that will actually be treated as mutable.
Static,
- /// UnsafeCell is OK in the value of a constant, but not behind references in a constant
+ /// UnsafeCell is OK in the value of a constant: `const FOO = Cell::new(0)` creates
+ /// a new cell every time it is used.
ConstBase,
- /// `UnsafeCell` ICEs
+ /// `UnsafeCell` ICEs.
Const,
}
@@ -55,48 +53,100 @@
/// into the memory of other constants or statics
struct IsStaticOrFn;
+/// Intern an allocation without looking at its children.
+/// `mode` is the mode of the environment where we found this pointer.
+/// `mutablity` is the mutability of the place to be interned; even if that says
+/// `immutable` things might become mutable if `ty` is not frozen.
+/// `ty` can be `None` if there is no potential interior mutability
+/// to account for (e.g. for vtables).
+fn intern_shallow<'rt, 'mir, 'tcx>(
+ ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
+ leftover_allocations: &'rt mut FxHashSet<AllocId>,
+ mode: InternMode,
+ alloc_id: AllocId,
+ mutability: Mutability,
+ ty: Option<Ty<'tcx>>,
+) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
+ trace!(
+ "InternVisitor::intern {:?} with {:?}",
+ alloc_id, mutability,
+ );
+ // remove allocation
+ let tcx = ecx.tcx;
+ let memory = ecx.memory_mut();
+ let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) {
+ Some(entry) => entry,
+ None => {
+ // Pointer not found in local memory map. It is either a pointer to the global
+ // map, or dangling.
+ // If the pointer is dangling (neither in local nor global memory), we leave it
+ // to validation to error. The `delay_span_bug` ensures that we don't forget such
+ // a check in validation.
+ if tcx.alloc_map.lock().get(alloc_id).is_none() {
+ tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
+ }
+ // treat dangling pointers like other statics
+ // just to stop trying to recurse into them
+ return Ok(Some(IsStaticOrFn));
+ },
+ };
+ // This match is just a canary for future changes to `MemoryKind`, which most likely need
+ // changes in this function.
+ match kind {
+ MemoryKind::Stack | MemoryKind::Vtable => {},
+ }
+ // Set allocation mutability as appropriate. This is used by LLVM to put things into
+ // read-only memory, and also by Miri when evluating other constants/statics that
+ // access this one.
+ if mode == InternMode::Static {
+ // When `ty` is `None`, we assume no interior mutability.
+ let frozen = ty.map_or(true, |ty| ty.is_freeze(
+ ecx.tcx.tcx,
+ ecx.param_env,
+ ecx.tcx.span,
+ ));
+ // For statics, allocation mutability is the combination of the place mutability and
+ // the type mutability.
+ // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
+ if mutability == Mutability::Immutable && frozen {
+ alloc.mutability = Mutability::Immutable;
+ } else {
+ // Just making sure we are not "upgrading" an immutable allocation to mutable.
+ assert_eq!(alloc.mutability, Mutability::Mutable);
+ }
+ } else {
+ // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`.
+ // But we still intern that as immutable as the memory cannot be changed once the
+ // initial value was computed.
+ // Constants are never mutable.
+ assert_eq!(
+ mutability, Mutability::Immutable,
+ "Something went very wrong: mutability requested for a constant"
+ );
+ alloc.mutability = Mutability::Immutable;
+ };
+ // link the alloc id to the actual allocation
+ let alloc = tcx.intern_const_alloc(alloc);
+ leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
+ tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
+ Ok(None)
+}
+
impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> {
- /// Intern an allocation without looking at its children
fn intern_shallow(
&mut self,
- ptr: Pointer,
+ alloc_id: AllocId,
mutability: Mutability,
+ ty: Option<Ty<'tcx>>,
) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
- trace!(
- "InternVisitor::intern {:?} with {:?}",
- ptr, mutability,
- );
- // remove allocation
- let tcx = self.ecx.tcx;
- let memory = self.ecx.memory_mut();
- let (kind, mut alloc) = match memory.alloc_map.remove(&ptr.alloc_id) {
- Some(entry) => entry,
- None => {
- // if the pointer is dangling (neither in local nor global memory), we leave it
- // to validation to error. The `delay_span_bug` ensures that we don't forget such
- // a check in validation.
- if tcx.alloc_map.lock().get(ptr.alloc_id).is_none() {
- tcx.sess.delay_span_bug(self.ecx.tcx.span, "tried to intern dangling pointer");
- }
- // treat dangling pointers like other statics
- // just to stop trying to recurse into them
- return Ok(Some(IsStaticOrFn));
- },
- };
- // This match is just a canary for future changes to `MemoryKind`, which most likely need
- // changes in this function.
- match kind {
- MemoryKind::Stack | MemoryKind::Vtable => {},
- }
- // Ensure llvm knows to only put this into immutable memory if the value is immutable either
- // by being behind a reference or by being part of a static or const without interior
- // mutability
- alloc.mutability = mutability;
- // link the alloc id to the actual allocation
- let alloc = tcx.intern_const_alloc(alloc);
- self.leftover_relocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
- tcx.alloc_map.lock().set_alloc_id_memory(ptr.alloc_id, alloc);
- Ok(None)
+ intern_shallow(
+ self.ecx,
+ self.leftover_allocations,
+ self.mode,
+ alloc_id,
+ mutability,
+ ty,
+ )
}
}
@@ -119,14 +169,16 @@
) -> InterpResult<'tcx> {
if let Some(def) = mplace.layout.ty.ty_adt_def() {
if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() {
- // We are crossing over an `UnsafeCell`, we can mutate again
+ // We are crossing over an `UnsafeCell`, we can mutate again. This means that
+ // References we encounter inside here are interned as pointing to mutable
+ // allocations.
let old = std::mem::replace(&mut self.mutability, Mutability::Mutable);
assert_ne!(
self.mode, InternMode::Const,
"UnsafeCells are not allowed behind references in constants. This should have \
been prevented statically by const qualification. If this were allowed one \
- would be able to change a constant at one use site and other use sites may \
- arbitrarily decide to change, too.",
+ would be able to change a constant at one use site and other use sites could \
+ observe that mutation.",
);
let walked = self.walk_aggregate(mplace, fields);
self.mutability = old;
@@ -145,12 +197,13 @@
// Handle trait object vtables
if let Ok(meta) = value.to_meta() {
if let ty::Dynamic(..) =
- self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty
+ self.ecx.tcx.struct_tail_erasing_lifetimes(
+ referenced_ty, self.ecx.param_env).sty
{
if let Ok(vtable) = meta.unwrap().to_ptr() {
// explitly choose `Immutable` here, since vtables are immutable, even
// if the reference of the fat pointer is mutable
- self.intern_shallow(vtable, Mutability::Immutable)?;
+ self.intern_shallow(vtable.alloc_id, Mutability::Immutable, None)?;
}
}
}
@@ -177,7 +230,7 @@
(InternMode::Const, hir::Mutability::MutMutable) => {
match referenced_ty.sty {
ty::Array(_, n)
- if n.eval_usize(self.ecx.tcx.tcx, self.param_env) == 0 => {}
+ if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
ty::Slice(_)
if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {}
_ => bug!("const qualif failed to prevent mutable references"),
@@ -195,21 +248,13 @@
(Mutability::Mutable, hir::Mutability::MutMutable) => Mutability::Mutable,
_ => Mutability::Immutable,
};
- // Compute the mutability of the allocation
- let intern_mutability = intern_mutability(
- self.ecx.tcx.tcx,
- self.param_env,
- mplace.layout.ty,
- self.ecx.tcx.span,
- mutability,
- );
// Recursing behind references changes the intern mode for constants in order to
// cause assertions to trigger if we encounter any `UnsafeCell`s.
let mode = match self.mode {
InternMode::ConstBase => InternMode::Const,
other => other,
};
- match self.intern_shallow(ptr, intern_mutability)? {
+ match self.intern_shallow(ptr.alloc_id, mutability, Some(mplace.layout.ty))? {
// No need to recurse, these are interned already and statics may have
// cycles, so we don't want to recurse there
Some(IsStaticOrFn) => {},
@@ -224,69 +269,45 @@
}
}
-/// Figure out the mutability of the allocation.
-/// Mutable if it has interior mutability *anywhere* in the type.
-fn intern_mutability<'tcx>(
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- ty: Ty<'tcx>,
- span: Span,
- mutability: Mutability,
-) -> Mutability {
- let has_interior_mutability = !ty.is_freeze(tcx, param_env, span);
- if has_interior_mutability {
- Mutability::Mutable
- } else {
- mutability
- }
-}
-
pub fn intern_const_alloc_recursive(
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
def_id: DefId,
ret: MPlaceTy<'tcx>,
- // FIXME(oli-obk): can we scrap the param env? I think we can, the final value of a const eval
- // must always be monomorphic, right?
- param_env: ty::ParamEnv<'tcx>,
) -> InterpResult<'tcx> {
let tcx = ecx.tcx;
// this `mutability` is the mutability of the place, ignoring the type
- let (mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
+ let (base_mutability, base_intern_mode) = match tcx.static_mutability(def_id) {
Some(hir::Mutability::MutImmutable) => (Mutability::Immutable, InternMode::Static),
- None => (Mutability::Immutable, InternMode::ConstBase),
// `static mut` doesn't care about interior mutability, it's mutable anyway
Some(hir::Mutability::MutMutable) => (Mutability::Mutable, InternMode::Static),
+ // consts, promoteds. FIXME: what about array lengths, array initializers?
+ None => (Mutability::Immutable, InternMode::ConstBase),
};
- // type based interning
- let mut ref_tracking = RefTracking::new((ret, mutability, base_intern_mode));
- let leftover_relocations = &mut FxHashSet::default();
-
- // This mutability is the combination of the place mutability and the type mutability. If either
- // is mutable, `alloc_mutability` is mutable. This exists because the entire allocation needs
- // to be mutable if it contains an `UnsafeCell` anywhere. The other `mutability` exists so that
- // the visitor does not treat everything outside the `UnsafeCell` as mutable.
- let alloc_mutability = intern_mutability(
- tcx.tcx, param_env, ret.layout.ty, tcx.span, mutability,
- );
+ // Type based interning.
+ // `ref_tracking` tracks typed references we have seen and still need to crawl for
+ // more typed information inside them.
+ // `leftover_allocations` collects *all* allocations we see, because some might not
+ // be available in a typed way. They get interned at the end.
+ let mut ref_tracking = RefTracking::new((ret, base_mutability, base_intern_mode));
+ let leftover_allocations = &mut FxHashSet::default();
// start with the outermost allocation
- InternVisitor {
- ref_tracking: &mut ref_tracking,
+ intern_shallow(
ecx,
- mode: base_intern_mode,
- leftover_relocations,
- param_env,
- mutability,
- }.intern_shallow(ret.ptr.to_ptr()?, alloc_mutability)?;
+ leftover_allocations,
+ base_intern_mode,
+ ret.ptr.to_ptr()?.alloc_id,
+ base_mutability,
+ Some(ret.layout.ty)
+ )?;
while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() {
let interned = InternVisitor {
ref_tracking: &mut ref_tracking,
ecx,
mode,
- leftover_relocations,
- param_env,
+ leftover_allocations,
mutability,
}.visit_value(mplace);
if let Err(error) = interned {
@@ -309,15 +330,23 @@
// Intern the rest of the allocations as mutable. These might be inside unions, padding, raw
// pointers, ... So we can't intern them according to their type rules
- let mut todo: Vec<_> = leftover_relocations.iter().cloned().collect();
+ let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect();
while let Some(alloc_id) = todo.pop() {
- if let Some((_, alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
- // We can't call the `intern` method here, as its logic is tailored to safe references.
- // So we hand-roll the interning logic here again
+ if let Some((_, mut alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) {
+ // We can't call the `intern_shallow` method here, as its logic is tailored to safe
+ // references and a `leftover_allocations` set (where we only have a todo-list here).
+ // So we hand-roll the interning logic here again.
+ if base_intern_mode != InternMode::Static {
+ // If it's not a static, it *must* be immutable.
+ // We cannot have mutable memory inside a constant.
+ // FIXME: ideally we would assert that they already are immutable, to double-
+ // check our static checks.
+ alloc.mutability = Mutability::Immutable;
+ }
let alloc = tcx.intern_const_alloc(alloc);
tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc);
for &(_, ((), reloc)) in alloc.relocations().iter() {
- if leftover_relocations.insert(reloc) {
+ if leftover_allocations.insert(reloc) {
todo.push(reloc);
}
}
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..034ad5b 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -59,5 +59,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/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index f8af9b9..39aa5c7 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -407,8 +407,9 @@
place: &Place<'tcx>,
is_mut_use: bool,
) {
- for (i, elem) in place.projection.iter().enumerate().rev() {
- let proj_base = &place.projection[..i];
+ let mut cursor = &*place.projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
match elem {
ProjectionElem::Field(..) => {
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index b4c97f9..a75c1af 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -38,8 +38,9 @@
where
L: HasLocalDecls<'tcx>,
{
- for (i, elem) in place.projection.iter().enumerate().rev() {
- let proj_base = &place.projection[..i];
+ let mut cursor = &*place.projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
match elem {
// encountered a Deref, which is ABI-aligned
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
index de1676f..a81786e 100644
--- a/src/librustc_msan/build.rs
+++ b/src/librustc_msan/build.rs
@@ -4,6 +4,7 @@
use cmake::Config;
fn main() {
+ println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
return;
}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f97fcb0..74f68e5 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -40,7 +40,7 @@
use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
-use syntax::symbol::{Symbol, kw, sym};
+use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};
use syntax::attr;
@@ -241,7 +241,7 @@
fn names_to_string(segments: &[Segment]) -> String {
names_to_string(&segments.iter()
- .map(|seg| seg.ident)
+ .map(|seg| seg.ident.name)
.collect::<Vec<_>>())
}
}
@@ -951,7 +951,7 @@
struct_constructors: DefIdMap<(Res, ty::Visibility)>,
/// Features enabled for this crate.
- active_features: FxHashSet<Symbol>,
+ active_features: FxHashSet<Name>,
/// Stores enum visibilities to properly build a reduced graph
/// when visiting the correspondent variants.
@@ -1018,8 +1018,8 @@
fn resolve_str_path(
&mut self,
span: Span,
- crate_root: Option<Symbol>,
- components: &[Symbol],
+ crate_root: Option<Name>,
+ components: &[Name],
ns: Namespace,
) -> (ast::Path, Res) {
let root = if crate_root.is_some() {
@@ -2555,7 +2555,7 @@
fn add_suggestion_for_rename_of_use(
&self,
err: &mut DiagnosticBuilder<'_>,
- name: Symbol,
+ name: Name,
directive: &ImportDirective<'_>,
binding_span: Span,
) {
@@ -2770,22 +2770,22 @@
}
}
-fn names_to_string(idents: &[Ident]) -> String {
+fn names_to_string(names: &[Name]) -> String {
let mut result = String::new();
- for (i, ident) in idents.iter()
- .filter(|ident| ident.name != kw::PathRoot)
+ for (i, name) in names.iter()
+ .filter(|name| **name != kw::PathRoot)
.enumerate() {
if i > 0 {
result.push_str("::");
}
- result.push_str(&ident.as_str());
+ result.push_str(&name.as_str());
}
result
}
fn path_names_to_string(path: &Path) -> String {
names_to_string(&path.segments.iter()
- .map(|seg| seg.ident)
+ .map(|seg| seg.ident.name)
.collect::<Vec<_>>())
}
@@ -2793,15 +2793,14 @@
fn module_to_string(module: Module<'_>) -> Option<String> {
let mut names = Vec::new();
- fn collect_mod(names: &mut Vec<Ident>, module: Module<'_>) {
+ fn collect_mod(names: &mut Vec<Name>, module: Module<'_>) {
if let ModuleKind::Def(.., name) = module.kind {
if let Some(parent) = module.parent {
- names.push(Ident::with_dummy_span(name));
+ names.push(name);
collect_mod(names, parent);
}
} else {
- // danger, shouldn't be ident?
- names.push(Ident::from_str("<opaque>"));
+ names.push(Name::intern("<opaque>"));
collect_mod(names, module.parent.unwrap());
}
}
@@ -2810,9 +2809,8 @@
if names.is_empty() {
return None;
}
- Some(names_to_string(&names.into_iter()
- .rev()
- .collect::<Vec<_>>()))
+ names.reverse();
+ Some(names_to_string(&names))
}
#[derive(Copy, Clone, Debug)]
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 9096d14..3900a3d 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -323,7 +323,7 @@
self.check_stability_and_deprecation(&ext, path);
Ok(if ext.macro_kind() != kind {
- let expected = if kind == MacroKind::Attr { "attribute" } else { kind.descr() };
+ let expected = kind.descr_expected();
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
self.session.struct_span_err(path.span, &msg)
.span_label(path.span, format!("not {} {}", kind.article(), expected))
@@ -774,9 +774,8 @@
}
Err(..) => {
assert!(initial_binding.is_none());
- let bang = if kind == MacroKind::Bang { "!" } else { "" };
- let msg =
- format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
+ let expected = kind.descr_expected();
+ let msg = format!("cannot find {} `{}` in this scope", expected, ident);
let mut err = self.session.struct_span_err(ident.span, &msg);
self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident);
err.emit();
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index eb509f1..e77e829 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1433,15 +1433,17 @@
let global = !names.is_empty() && names[0].name == kw::PathRoot;
if let Some(pos) = pos {
let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
- names_to_string(names)
+ names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>())
} else {
let names = if global { &names[1..] } else { names };
if names.is_empty() {
import_directive_subclass_to_string(subclass)
} else {
- format!("{}::{}",
- names_to_string(names),
- import_directive_subclass_to_string(subclass))
+ format!(
+ "{}::{}",
+ names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
+ import_directive_subclass_to_string(subclass),
+ )
}
}
}
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 12c5ce1..55f6b91 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -130,6 +130,10 @@
self.save_ctxt.span_from_span(span)
}
+ fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
+ self.save_ctxt.lookup_def_id(ref_id)
+ }
+
pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
let source_file = self.tcx.sess.local_crate_source_file.as_ref();
let crate_root = source_file.map(|source_file| {
@@ -223,13 +227,6 @@
}
}
- fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
- match self.save_ctxt.get_path_res(ref_id) {
- Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => None,
- def => Some(def.def_id()),
- }
- }
-
fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) {
for arg in formals {
self.visit_pat(&arg.pat);
@@ -283,36 +280,32 @@
) {
debug!("process_method: {}:{}", id, ident);
- if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) {
- let sig_str = crate::make_signature(&sig.decl, &generics);
- if body.is_some() {
- self.nest_tables(
- id,
- |v| v.process_formals(&sig.decl.inputs, &method_data.qualname),
- );
+ let hir_id = self.tcx.hir().node_to_hir_id(id);
+ self.nest_tables(id, |v| {
+ if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
+ v.process_formals(&sig.decl.inputs, &method_data.qualname);
+ v.process_generic_params(&generics, &method_data.qualname, id);
+
+ method_data.value = crate::make_signature(&sig.decl, &generics);
+ method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt);
+
+ v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
}
- self.process_generic_params(&generics, &method_data.qualname, id);
+ // walk arg and return types
+ for arg in &sig.decl.inputs {
+ v.visit_ty(&arg.ty);
+ }
- method_data.value = sig_str;
- method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt);
- let hir_id = self.tcx.hir().node_to_hir_id(id);
- self.dumper.dump_def(&access_from_vis!(self.save_ctxt, vis, hir_id), method_data);
- }
+ if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
+ v.visit_ty(ret_ty);
+ }
- // walk arg and return types
- for arg in &sig.decl.inputs {
- self.visit_ty(&arg.ty);
- }
-
- if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
- self.visit_ty(ret_ty);
- }
-
- // walk the fn body
- if let Some(body) = body {
- self.nest_tables(id, |v| v.visit_block(body));
- }
+ // walk the fn body
+ if let Some(body) = body {
+ v.visit_block(body);
+ }
+ });
}
fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
@@ -377,26 +370,31 @@
ty_params: &'l ast::Generics,
body: &'l ast::Block,
) {
- if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
- down_cast_data!(fn_data, DefData, item.span);
- self.nest_tables(
- item.id,
- |v| v.process_formals(&decl.inputs, &fn_data.qualname),
- );
- self.process_generic_params(ty_params, &fn_data.qualname, item.id);
- let hir_id = self.tcx.hir().node_to_hir_id(item.id);
- self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), fn_data);
- }
+ let hir_id = self.tcx.hir().node_to_hir_id(item.id);
+ self.nest_tables(item.id, |v| {
+ if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
+ down_cast_data!(fn_data, DefData, item.span);
+ v.process_formals(&decl.inputs, &fn_data.qualname);
+ v.process_generic_params(ty_params, &fn_data.qualname, item.id);
- for arg in &decl.inputs {
- self.visit_ty(&arg.ty);
- }
+ v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data);
+ }
- if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
- self.visit_ty(&ret_ty);
- }
+ for arg in &decl.inputs {
+ v.visit_ty(&arg.ty)
+ }
- self.nest_tables(item.id, |v| v.visit_block(&body));
+ if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
+ if let ast::TyKind::ImplTrait(..) = ret_ty.node {
+ // FIXME: Opaque type desugaring prevents us from easily
+ // processing trait bounds. See `visit_ty` for more details.
+ } else {
+ v.visit_ty(&ret_ty);
+ }
+ }
+
+ v.visit_block(&body);
+ });
}
fn process_static_or_const_item(
@@ -1113,11 +1111,7 @@
// FIXME: uses of the assoc type should ideally point to this
// 'def' and the name here should be a ref to the def in the
// trait.
- for bound in bounds.iter() {
- if let ast::GenericBound::Trait(trait_ref, _) = bound {
- self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
- }
- }
+ self.process_bounds(&bounds);
}
ast::ImplItemKind::Macro(_) => {}
}
@@ -1364,10 +1358,10 @@
self.visit_ty(&ty);
self.process_generic_params(ty_params, &qualname, item.id);
}
- OpaqueTy(ref _bounds, ref ty_params) => {
+ OpaqueTy(ref bounds, ref ty_params) => {
let qualname = format!("::{}",
self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));
- // FIXME do something with _bounds
+
let value = String::new();
if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span);
@@ -1393,6 +1387,7 @@
);
}
+ self.process_bounds(bounds);
self.process_generic_params(ty_params, &qualname, item.id);
}
Mac(_) => (),
@@ -1449,6 +1444,18 @@
self.visit_ty(element);
self.nest_tables(length.id, |v| v.visit_expr(&length.value));
}
+ ast::TyKind::ImplTrait(id, ref bounds) => {
+ // FIXME: As of writing, the opaque type lowering introduces
+ // another DefPath scope/segment (used to declare the resulting
+ // opaque type item).
+ // However, the synthetic scope does *not* have associated
+ // typeck tables, which means we can't nest it and we fire an
+ // assertion when resolving the qualified type paths in trait
+ // bounds...
+ // This will panic if called on return type `impl Trait`, which
+ // we guard against in `process_fn`.
+ self.nest_tables(id, |v| v.process_bounds(bounds));
+ }
_ => visit::walk_ty(self, t),
}
}
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4bc098d..055ccf6 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -312,7 +312,7 @@
let impl_id = self.next_impl_id();
let span = self.span_from_span(sub_span);
- let type_data = self.lookup_ref_id(typ.id);
+ let type_data = self.lookup_def_id(typ.id);
type_data.map(|type_data| {
Data::RelationData(Relation {
kind: RelationKind::Impl {
@@ -322,7 +322,7 @@
from: id_from_def_id(type_data),
to: trait_ref
.as_ref()
- .and_then(|t| self.lookup_ref_id(t.ref_id))
+ .and_then(|t| self.lookup_def_id(t.ref_id))
.map(id_from_def_id)
.unwrap_or_else(|| null_id()),
},
@@ -495,7 +495,7 @@
}
pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
- self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
+ self.lookup_def_id(trait_ref.ref_id).and_then(|def_id| {
let span = trait_ref.path.span;
if generated_code(span) {
return None;
@@ -870,7 +870,7 @@
})
}
- fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
+ fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
match self.get_path_res(ref_id) {
Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None,
def => Some(def.def_id()),
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
index 6df9691..f9333e1 100644
--- a/src/librustc_tsan/build.rs
+++ b/src/librustc_tsan/build.rs
@@ -4,6 +4,7 @@
use cmake::Config;
fn main() {
+ println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS");
if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) {
return;
}
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 20442ab..af1d240 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -25,17 +25,11 @@
unwind = { path = "../libunwind" }
hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] }
-[dependencies.backtrace]
+[dependencies.backtrace_rs]
+package = "backtrace"
version = "0.3.37"
-default-features = false # don't use coresymbolication on OSX
-features = [
- "rustc-dep-of-std", # enable build support for integrating into libstd
- "dbghelp", # backtrace/symbolize on MSVC
- "libbacktrace", # symbolize on most platforms
- "libunwind", # backtrace on most platforms
- "dladdr", # symbolize on platforms w/o libbacktrace
-]
-optional = true
+default-features = false # without the libstd `backtrace` feature, stub out everything
+features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd
[dev-dependencies]
rand = "0.7"
@@ -65,6 +59,13 @@
[features]
default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
+backtrace = [
+ "backtrace_rs/dbghelp", # backtrace/symbolize on MSVC
+ "backtrace_rs/libbacktrace", # symbolize on most platforms
+ "backtrace_rs/libunwind", # backtrace on most platforms
+ "backtrace_rs/dladdr", # symbolize on platforms w/o libbacktrace
+]
+
panic-unwind = ["panic_unwind"]
profiler = ["profiler_builtins"]
compiler-builtins-c = ["alloc/compiler-builtins-c"]
diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs
index 5d46ef7..61c42a5 100644
--- a/src/libstd/backtrace.rs
+++ b/src/libstd/backtrace.rs
@@ -97,6 +97,7 @@
use crate::sync::Mutex;
use crate::sys_common::backtrace::{output_filename, lock};
use crate::vec::Vec;
+use backtrace_rs as backtrace;
use backtrace::BytesOrWideString;
/// A captured OS thread stack backtrace.
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index b14e02a..b5265fe 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1956,7 +1956,8 @@
/// # Platform-specific behavior
///
/// This function currently corresponds to the `opendir` function on Unix
-/// and the `FindFirstFile` function on Windows.
+/// and the `FindFirstFile` function on Windows. Advancing the iterator
+/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows.
/// Note that, this [may change in the future][changes].
///
/// [changes]: ../io/index.html#platform-specific-behavior
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/libstd/panicking.rs b/src/libstd/panicking.rs
index db4089c..28fb402 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -17,8 +17,7 @@
use crate::raw;
use crate::sys::stdio::panic_output;
use crate::sys_common::rwlock::RWLock;
-use crate::sys_common::thread_info;
-use crate::sys_common::util;
+use crate::sys_common::{thread_info, util, backtrace};
use crate::thread;
#[cfg(not(test))]
@@ -157,20 +156,18 @@
}
fn default_hook(info: &PanicInfo<'_>) {
- #[cfg(feature = "backtrace")]
- use crate::sys_common::{backtrace as backtrace_mod};
-
// If this is a double panic, make sure that we print a backtrace
// for this panic. Otherwise only print it if logging is enabled.
- #[cfg(feature = "backtrace")]
- let log_backtrace = {
+ let log_backtrace = if cfg!(feature = "backtrace") {
let panics = update_panic_count(0);
if panics >= 2 {
- Some(backtrace::PrintFmt::Full)
+ Some(backtrace_rs::PrintFmt::Full)
} else {
- backtrace_mod::log_enabled()
+ backtrace::log_enabled()
}
+ } else {
+ None
};
// The current implementation always returns `Some`.
@@ -190,14 +187,13 @@
let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
name, msg, location);
- #[cfg(feature = "backtrace")]
- {
+ if cfg!(feature = "backtrace") {
use crate::sync::atomic::{AtomicBool, Ordering};
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
if let Some(format) = log_backtrace {
- let _ = backtrace_mod::print(err, format);
+ let _ = backtrace::print(err, format);
} else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \
environment variable to display a backtrace.");
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index c50025a..b8d57cf 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -422,7 +422,7 @@
/// // Execute `ls` in the current directory of the program.
/// list_dir.status().expect("process failed to execute");
///
-/// println!("");
+/// println!();
///
/// // Change `ls` to execute in the root directory.
/// list_dir.current_dir("/");
diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs
index 1a78abf..01711d4 100644
--- a/src/libstd/sys_common/backtrace.rs
+++ b/src/libstd/sys_common/backtrace.rs
@@ -7,10 +7,9 @@
use crate::borrow::Cow;
use crate::io::prelude::*;
use crate::path::{self, Path, PathBuf};
-use crate::sync::atomic::{self, Ordering};
use crate::sys::mutex::Mutex;
-use backtrace::{BacktraceFmt, BytesOrWideString, PrintFmt};
+use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt};
/// Max number of frames to print.
const MAX_NB_FRAMES: usize = 100;
@@ -74,14 +73,14 @@
bt_fmt.add_context()?;
let mut idx = 0;
let mut res = Ok(());
- backtrace::trace_unsynchronized(|frame| {
+ backtrace_rs::trace_unsynchronized(|frame| {
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
return false;
}
let mut hit = false;
let mut stop = false;
- backtrace::resolve_frame_unsynchronized(frame, |symbol| {
+ backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
hit = true;
if print_fmt == PrintFmt::Short {
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
@@ -130,6 +129,8 @@
// For now logging is turned off by default, and this function checks to see
// whether the magical environment variable is present to see if it's turned on.
pub fn log_enabled() -> Option<PrintFmt> {
+ use crate::sync::atomic::{self, Ordering};
+
// Setting environment variables for Fuchsia components isn't a standard
// or easily supported workflow. For now, always display backtraces.
if cfg!(target_os = "fuchsia") {
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 9190a3b..cba3eca 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -41,7 +41,6 @@
pub mod alloc;
pub mod at_exit_imp;
-#[cfg(feature = "backtrace")]
pub mod backtrace;
pub mod condvar;
pub mod io;
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 7759a98..384c055 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -977,13 +977,6 @@
span.with_call_site_ctxt(self.current_expansion.id)
}
- /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
- /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
- /// or with `with_call_site_ctxt` (where necessary).
- pub fn with_legacy_ctxt(&self, span: Span) -> Span {
- span.with_legacy_ctxt(self.current_expansion.id)
- }
-
/// Returns span for the macro which originally caused the current expansion to happen.
///
/// Stops backtracing at include! boundary.
@@ -1081,8 +1074,8 @@
pub fn set_trace_macros(&mut self, x: bool) {
self.ecfg.trace_mac = x
}
- pub fn ident_of(&self, st: &str) -> ast::Ident {
- ast::Ident::from_str(st)
+ pub fn ident_of(&self, st: &str, sp: Span) -> ast::Ident {
+ ast::Ident::from_str_and_span(st, sp)
}
pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> {
let def_site = self.with_def_site_ctxt(DUMMY_SP);
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 06a5531..f1d0e0b 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -363,7 +363,7 @@
self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
}
pub fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
- let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
+ let ident = Ident::new(sym::integer(idx), sp);
self.expr(sp, ast::ExprKind::Field(expr, ident))
}
pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
@@ -525,7 +525,7 @@
let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
let err_path = self.path_global(sp, err);
- let binding_variable = self.ident_of("__try_var");
+ let binding_variable = self.ident_of("__try_var", sp);
let binding_pat = self.pat_ident(sp, binding_variable);
let binding_expr = self.expr_ident(sp, binding_variable);
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 46ffa52..b27e9c5 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -877,9 +877,9 @@
// Now `last` holds the complete set of NT tokens that could
// end the sequence before SUFFIX. Check that every one works with `suffix`.
'each_last: for token in &last.tokens {
- if let TokenTree::MetaVarDecl(_, ref name, ref frag_spec) = *token {
+ if let TokenTree::MetaVarDecl(_, name, frag_spec) = *token {
for next_token in &suffix_first.tokens {
- match is_in_follow(next_token, &frag_spec.as_str()) {
+ match is_in_follow(next_token, frag_spec.name) {
IsInFollow::Invalid(msg, help) => {
sess.span_diagnostic
.struct_span_err(next_token.span(), &msg)
@@ -948,7 +948,7 @@
fn token_can_be_followed_by_any(tok: "ed::TokenTree) -> bool {
if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok {
- frag_can_be_followed_by_any(&frag_spec.as_str())
+ frag_can_be_followed_by_any(frag_spec.name)
} else {
// (Non NT's can always be followed by anthing in matchers.)
true
@@ -963,15 +963,15 @@
/// specifier which consumes at most one token tree can be followed by
/// a fragment specifier (indeed, these fragments can be followed by
/// ANYTHING without fear of future compatibility hazards).
-fn frag_can_be_followed_by_any(frag: &str) -> bool {
+fn frag_can_be_followed_by_any(frag: Symbol) -> bool {
match frag {
- "item" | // always terminated by `}` or `;`
- "block" | // exactly one token tree
- "ident" | // exactly one token tree
- "literal" | // exactly one token tree
- "meta" | // exactly one token tree
- "lifetime" | // exactly one token tree
- "tt" => // exactly one token tree
+ sym::item | // always terminated by `}` or `;`
+ sym::block | // exactly one token tree
+ sym::ident | // exactly one token tree
+ sym::literal | // exactly one token tree
+ sym::meta | // exactly one token tree
+ sym::lifetime | // exactly one token tree
+ sym::tt => // exactly one token tree
true,
_ =>
@@ -993,7 +993,7 @@
/// break macros that were relying on that binary operator as a
/// separator.
// when changing this do not forget to update doc/book/macros.md!
-fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow {
+fn is_in_follow(tok: "ed::TokenTree, frag: Symbol) -> IsInFollow {
use quoted::TokenTree;
if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok {
@@ -1002,17 +1002,17 @@
IsInFollow::Yes
} else {
match frag {
- "item" => {
+ sym::item => {
// since items *must* be followed by either a `;` or a `}`, we can
// accept anything after them
IsInFollow::Yes
}
- "block" => {
+ sym::block => {
// anything can follow block, the braces provide an easy boundary to
// maintain
IsInFollow::Yes
}
- "stmt" | "expr" => {
+ sym::stmt | sym::expr => {
const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
match tok {
TokenTree::Token(token) => match token.kind {
@@ -1022,7 +1022,7 @@
_ => IsInFollow::No(TOKENS),
}
}
- "pat" => {
+ sym::pat => {
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
match tok {
TokenTree::Token(token) => match token.kind {
@@ -1033,7 +1033,7 @@
_ => IsInFollow::No(TOKENS),
}
}
- "path" | "ty" => {
+ sym::path | sym::ty => {
const TOKENS: &[&str] = &[
"`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`",
"`where`",
@@ -1061,20 +1061,20 @@
_ => IsInFollow::No(TOKENS),
}
}
- "ident" | "lifetime" => {
+ sym::ident | sym::lifetime => {
// being a single token, idents and lifetimes are harmless
IsInFollow::Yes
}
- "literal" => {
+ sym::literal => {
// literals may be of a single token, or two tokens (negative numbers)
IsInFollow::Yes
}
- "meta" | "tt" => {
+ sym::meta | sym::tt => {
// being either a single token or a delimited sequence, tt is
// harmless
IsInFollow::Yes
}
- "vis" => {
+ sym::vis => {
// Explicitly disallow `priv`, on the off chance it comes back.
const TOKENS: &[&str] = &["`,`", "an ident", "a type"];
match tok {
@@ -1099,7 +1099,7 @@
_ => IsInFollow::No(TOKENS),
}
}
- "" => IsInFollow::Yes, // kw::Invalid
+ kw::Invalid => IsInFollow::Yes,
_ => IsInFollow::Invalid(
format!("invalid fragment specifier `{}`", frag),
VALID_FRAGMENT_NAMES_MSG,
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index baae615..cf19664 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -1256,7 +1256,7 @@
for part in idents {
fixed_name.push_str(&format!("_{}", part.name));
}
- ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp);
+ ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp);
self.struct_span_err(fixed_name_sp, error_msg)
.span_label(fixed_name_sp, "dash-separated idents are not valid")
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 328b307..75d727b 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -62,7 +62,7 @@
MacEager::expr(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::InlineAsm(P(inline_asm)),
- span: cx.with_legacy_ctxt(sp),
+ span: cx.with_def_site_ctxt(sp),
attrs: ThinVec::new(),
}))
}
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index 001996e..cbfe14f 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -23,7 +23,9 @@
}
};
- let sp = cx.with_legacy_ctxt(sp);
+ // `core::panic` and `std::panic` are different macros, so we use call-site
+ // context to pick up whichever is currently in scope.
+ let sp = cx.with_call_site_ctxt(sp);
let panic_call = Mac {
path: Path::from_ident(Ident::new(sym::panic, sp)),
tts: custom_message.unwrap_or_else(|| {
diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs
index 0342e44..3c33baf 100644
--- a/src/libsyntax_ext/cfg.rs
+++ b/src/libsyntax_ext/cfg.rs
@@ -16,7 +16,7 @@
sp: Span,
tts: TokenStream,
) -> Box<dyn base::MacResult + 'static> {
- let sp = cx.with_legacy_ctxt(sp);
+ let sp = cx.with_def_site_ctxt(sp);
match parse_cfg(cx, sp, tts) {
Ok(cfg) => {
diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs
index fc56dff..16f0160 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -59,6 +59,6 @@
} else if has_errors {
return DummyResult::any(sp);
}
- let sp = cx.with_legacy_ctxt(sp);
+ let sp = cx.with_def_site_ctxt(sp);
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
}
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 6391b62..f344706 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -39,7 +39,7 @@
}
}
- let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_legacy_ctxt(sp));
+ let ident = ast::Ident::new(Symbol::intern(&res_str), cx.with_call_site_ctxt(sp));
struct ConcatIdentsResult { ident: ast::Ident }
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index debdc30..13d63aa 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -109,7 +109,7 @@
GtOp => "gt",
GeOp => "ge",
};
- cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt])
+ cx.expr_method_call(span, lft, cx.ident_of(op_str, span), vec![rgt])
}
pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 781645a..088b61b 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -62,7 +62,7 @@
// We want to make sure we have the ctxt set so that we can use unstable methods
let span = cx.with_def_site_ctxt(span);
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
- let builder = Ident::from_str_and_span("debug_trait_builder", span);
+ let builder = cx.ident_of("debug_trait_builder", span);
let builder_expr = cx.expr_ident(span, builder.clone());
let fmt = substr.nonself_args[0].clone();
@@ -72,7 +72,7 @@
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
// tuple struct/"normal" variant
let expr =
- cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
+ cx.expr_method_call(span, fmt, cx.ident_of("debug_tuple", span), vec![name]);
stmts.push(cx.stmt_let(span, true, builder, expr));
for field in fields {
@@ -93,7 +93,7 @@
ast::VariantData::Struct(..) => {
// normal struct/struct variant
let expr =
- cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
+ cx.expr_method_call(span, fmt, cx.ident_of("debug_struct", span), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
@@ -113,7 +113,7 @@
}
}
- let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);
+ let expr = cx.expr_method_call(span, builder_expr, cx.ident_of("finish", span), vec![]);
stmts.push(cx.stmt_expr(expr));
let block = cx.block(span, stmts);
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index d3d604b..cde72ab 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -66,10 +66,14 @@
krate: &str)
-> P<Expr> {
let decoder = substr.nonself_args[0].clone();
- let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")];
+ let recurse = vec![
+ cx.ident_of(krate, trait_span),
+ cx.ident_of("Decodable", trait_span),
+ cx.ident_of("decode", trait_span),
+ ];
let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
// throw an underscore in front to suppress unused variable warnings
- let blkarg = cx.ident_of("_d");
+ let blkarg = cx.ident_of("_d", trait_span);
let blkdecoder = cx.expr_ident(trait_span, blkarg);
return match *substr.fields {
@@ -78,7 +82,7 @@
Unnamed(ref fields, _) => fields.len(),
Named(ref fields) => fields.len(),
};
- let read_struct_field = cx.ident_of("read_struct_field");
+ let read_struct_field = cx.ident_of("read_struct_field", trait_span);
let path = cx.path_ident(trait_span, substr.type_ident);
let result =
@@ -94,17 +98,17 @@
let result = cx.expr_ok(trait_span, result);
cx.expr_method_call(trait_span,
decoder,
- cx.ident_of("read_struct"),
+ cx.ident_of("read_struct", trait_span),
vec![cx.expr_str(trait_span, substr.type_ident.name),
cx.expr_usize(trait_span, nfields),
cx.lambda1(trait_span, result, blkarg)])
}
StaticEnum(_, ref fields) => {
- let variant = cx.ident_of("i");
+ let variant = cx.ident_of("i", trait_span);
let mut arms = Vec::with_capacity(fields.len() + 1);
let mut variants = Vec::with_capacity(fields.len());
- let rvariant_arg = cx.ident_of("read_enum_variant_arg");
+ let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span);
for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
variants.push(cx.expr_str(v_span, ident.name));
@@ -132,11 +136,11 @@
let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
let result = cx.expr_method_call(trait_span,
blkdecoder,
- cx.ident_of("read_enum_variant"),
+ cx.ident_of("read_enum_variant", trait_span),
vec![variant_vec, lambda]);
cx.expr_method_call(trait_span,
decoder,
- cx.ident_of("read_enum"),
+ cx.ident_of("read_enum", trait_span),
vec![cx.expr_str(trait_span, substr.type_ident.name),
cx.lambda1(trait_span, result, blkarg)])
}
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 8b18fb2..655d3bb 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -153,16 +153,16 @@
-> P<Expr> {
let encoder = substr.nonself_args[0].clone();
// throw an underscore in front to suppress unused variable warnings
- let blkarg = cx.ident_of("_e");
+ let blkarg = cx.ident_of("_e", trait_span);
let blkencoder = cx.expr_ident(trait_span, blkarg);
let fn_path = cx.expr_path(cx.path_global(trait_span,
- vec![cx.ident_of(krate),
- cx.ident_of("Encodable"),
- cx.ident_of("encode")]));
+ vec![cx.ident_of(krate, trait_span),
+ cx.ident_of("Encodable", trait_span),
+ cx.ident_of("encode", trait_span)]));
return match *substr.fields {
Struct(_, ref fields) => {
- let emit_struct_field = cx.ident_of("emit_struct_field");
+ let emit_struct_field = cx.ident_of("emit_struct_field", trait_span);
let mut stmts = Vec::new();
for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
let name = match name {
@@ -201,7 +201,7 @@
cx.expr_method_call(trait_span,
encoder,
- cx.ident_of("emit_struct"),
+ cx.ident_of("emit_struct", trait_span),
vec![cx.expr_str(trait_span, substr.type_ident.name),
cx.expr_usize(trait_span, fields.len()),
blk])
@@ -214,7 +214,7 @@
// actually exist.
let me = cx.stmt_let(trait_span, false, blkarg, encoder);
let encoder = cx.expr_ident(trait_span, blkarg);
- let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
+ let emit_variant_arg = cx.ident_of("emit_enum_variant_arg", trait_span);
let mut stmts = Vec::new();
if !fields.is_empty() {
let last = fields.len() - 1;
@@ -244,7 +244,7 @@
let name = cx.expr_str(trait_span, variant.ident.name);
let call = cx.expr_method_call(trait_span,
blkencoder,
- cx.ident_of("emit_enum_variant"),
+ cx.ident_of("emit_enum_variant", trait_span),
vec![name,
cx.expr_usize(trait_span, idx),
cx.expr_usize(trait_span, fields.len()),
@@ -252,7 +252,7 @@
let blk = cx.lambda1(trait_span, call, blkarg);
let ret = cx.expr_method_call(trait_span,
encoder,
- cx.ident_of("emit_enum"),
+ cx.ident_of("emit_enum", trait_span),
vec![cx.expr_str(trait_span ,substr.type_ident.name),
blk]);
cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index c53fa7d..aceee62 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -237,7 +237,7 @@
/// Whether there is a self argument (outer Option) i.e., whether
/// this is a static function, and whether it is a pointer (inner
/// Option)
- pub explicit_self: Option<Option<PtrTy<'a>>>,
+ pub explicit_self: Option<Option<PtrTy>>,
/// Arguments other than the self argument
pub args: Vec<(Ty<'a>, &'a str)>,
@@ -843,7 +843,7 @@
-> P<Expr> {
let substructure = Substructure {
type_ident,
- method_ident: cx.ident_of(self.name),
+ method_ident: cx.ident_of(self.name, trait_.span),
self_args,
nonself_args,
fields,
@@ -890,7 +890,7 @@
for (ty, name) in self.args.iter() {
let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
- let ident = ast::Ident::from_str_and_span(name, trait_.span);
+ let ident = cx.ident_of(name, trait_.span);
arg_tys.push((ident, ast_ty));
let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -938,7 +938,7 @@
let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
- let method_ident = cx.ident_of(self.name);
+ let method_ident = cx.ident_of(self.name, trait_.span);
let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type));
let body_block = cx.block_expr(body);
@@ -1201,7 +1201,7 @@
).collect::<Vec<String>>();
let self_arg_idents = self_arg_names.iter()
- .map(|name| cx.ident_of(&name[..]))
+ .map(|name| cx.ident_of(name, sp))
.collect::<Vec<ast::Ident>>();
// The `vi_idents` will be bound, solely in the catch-all, to
@@ -1210,7 +1210,7 @@
let vi_idents = self_arg_names.iter()
.map(|name| {
let vi_suffix = format!("{}_vi", &name[..]);
- ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span)
+ cx.ident_of(&vi_suffix[..], trait_.span)
})
.collect::<Vec<ast::Ident>>();
@@ -1389,7 +1389,7 @@
let target_ty = cx.ty_ident(
sp,
- ast::Ident::from_str_and_span(target_type_name, sp),
+ cx.ident_of(target_type_name, sp),
);
let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
@@ -1591,7 +1591,7 @@
let mut ident_exprs = Vec::new();
for (i, struct_field) in struct_def.fields().iter().enumerate() {
let sp = struct_field.span.with_ctxt(self.span.ctxt());
- let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
+ let ident = cx.ident_of(&format!("{}_{}", prefix, i), self.span);
paths.push(ident.with_span_pos(sp));
let val = cx.expr_path(cx.path_ident(sp, ident));
let val = if use_temporaries {
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index cb1c7b2..b341a07 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -13,9 +13,9 @@
/// The types of pointers
#[derive(Clone)]
-pub enum PtrTy<'a> {
+pub enum PtrTy {
/// &'lifetime mut
- Borrowed(Option<&'a str>, ast::Mutability),
+ Borrowed(Option<Ident>, ast::Mutability),
/// *mut
#[allow(dead_code)]
Raw(ast::Mutability),
@@ -26,7 +26,7 @@
#[derive(Clone)]
pub struct Path<'a> {
path: Vec<&'a str>,
- lifetime: Option<&'a str>,
+ lifetime: Option<Ident>,
params: Vec<Box<Ty<'a>>>,
kind: PathKind,
}
@@ -46,7 +46,7 @@
Path::new_(vec![path], None, Vec::new(), PathKind::Local)
}
pub fn new_<'r>(path: Vec<&'r str>,
- lifetime: Option<&'r str>,
+ lifetime: Option<Ident>,
params: Vec<Box<Ty<'r>>>,
kind: PathKind)
-> Path<'r> {
@@ -72,7 +72,7 @@
self_ty: Ident,
self_generics: &Generics)
-> ast::Path {
- let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect();
+ let mut idents = self.path.iter().map(|s| cx.ident_of(*s, span)).collect();
let lt = mk_lifetimes(cx, span, &self.lifetime);
let tys: Vec<P<ast::Ty>> =
self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
@@ -99,7 +99,7 @@
pub enum Ty<'a> {
Self_,
/// &/Box/ Ty
- Ptr(Box<Ty<'a>>, PtrTy<'a>),
+ Ptr(Box<Ty<'a>>, PtrTy),
/// mod::mod::Type<[lifetime], [Params...]>, including a plain type
/// parameter, and things like `i32`
Literal(Path<'a>),
@@ -107,14 +107,14 @@
Tuple(Vec<Ty<'a>>),
}
-pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
+pub fn borrowed_ptrty() -> PtrTy {
Borrowed(None, ast::Mutability::Immutable)
}
pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
Ptr(ty, borrowed_ptrty())
}
-pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
+pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
Some(Some(borrowed_ptrty()))
}
@@ -126,13 +126,11 @@
Tuple(Vec::new())
}
-fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
- lt.map(|s|
- cx.lifetime(span, Ident::from_str(s))
- )
+fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Option<ast::Lifetime> {
+ lt.map(|ident| cx.lifetime(span, ident))
}
-fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
+fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Lifetime> {
mk_lifetime(cx, span, lt).into_iter().collect()
}
@@ -209,7 +207,7 @@
cx.trait_bound(path)
})
.collect();
- cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None)
+ cx.typaram(span, cx.ident_of(name, span), attrs.to_owned(), bounds, None)
}
fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
@@ -265,7 +263,7 @@
pub fn get_explicit_self(cx: &ExtCtxt<'_>,
span: Span,
- self_ptr: &Option<PtrTy<'_>>)
+ self_ptr: &Option<PtrTy>)
-> (P<Expr>, ast::ExplicitSelf) {
// this constructs a fresh `self` path
let self_path = cx.expr_self(span);
@@ -276,7 +274,7 @@
respan(span,
match *ptr {
Borrowed(ref lt, mutbl) => {
- let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s)));
+ let lt = lt.map(|s| cx.lifetime(span, s));
SelfKind::Region(lt, mutbl)
}
Raw(_) => {
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 179b7fe..70e1fbe 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -20,16 +20,16 @@
Some(v) => v,
};
- let sp = cx.with_legacy_ctxt(sp);
+ let sp = cx.with_def_site_ctxt(sp);
let e = match env::var(&*var.as_str()) {
Err(..) => {
- let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime));
+ let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp));
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&[sym::option, sym::Option, sym::None]),
vec![GenericArg::Type(cx.ty_rptr(sp,
cx.ty_ident(sp,
- Ident::with_dummy_span(sym::str)),
+ Ident::new(sym::str, sp)),
Some(lt),
ast::Mutability::Immutable))],
vec![]))
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 5bfbdc9..46c7cbb 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -486,7 +486,7 @@
let sp = self.macsp;
let count = |c, arg| {
let mut path = Context::rtpath(self.ecx, "Count");
- path.push(self.ecx.ident_of(c));
+ path.push(self.ecx.ident_of(c, sp));
match arg {
Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
@@ -534,7 +534,7 @@
let pos = {
let pos = |c, arg| {
let mut path = Context::rtpath(self.ecx, "Position");
- path.push(self.ecx.ident_of(c));
+ path.push(self.ecx.ident_of(c, sp));
match arg {
Some(i) => {
let arg = self.ecx.expr_usize(sp, i);
@@ -603,7 +603,7 @@
let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill));
let align = |name| {
let mut p = Context::rtpath(self.ecx, "Alignment");
- p.push(self.ecx.ident_of(name));
+ p.push(self.ecx.ident_of(name, sp));
self.ecx.path_global(sp, p)
};
let align = match arg.format.align {
@@ -621,11 +621,11 @@
sp,
path,
vec![
- self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
- self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
- self.ecx.field_imm(sp, self.ecx.ident_of("flags"), flags),
- self.ecx.field_imm(sp, self.ecx.ident_of("precision"), prec),
- self.ecx.field_imm(sp, self.ecx.ident_of("width"), width),
+ self.ecx.field_imm(sp, self.ecx.ident_of("fill", sp), fill),
+ self.ecx.field_imm(sp, self.ecx.ident_of("align", sp), align),
+ self.ecx.field_imm(sp, self.ecx.ident_of("flags", sp), flags),
+ self.ecx.field_imm(sp, self.ecx.ident_of("precision", sp), prec),
+ self.ecx.field_imm(sp, self.ecx.ident_of("width", sp), width),
],
);
@@ -634,8 +634,8 @@
sp,
path,
vec![
- self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
- self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
+ self.ecx.field_imm(sp, self.ecx.ident_of("position", sp), pos),
+ self.ecx.field_imm(sp, self.ecx.ident_of("format", sp), fmt),
],
))
}
@@ -653,7 +653,7 @@
let mut heads = Vec::with_capacity(self.args.len());
let names_pos: Vec<_> = (0..self.args.len())
- .map(|i| ast::Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
+ .map(|i| self.ecx.ident_of(&format!("arg{}", i), self.macsp))
.collect();
// First, build up the static array which will become our precompiled
diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs
index f4af169..19a87e6 100644
--- a/src/libsyntax_ext/global_allocator.rs
+++ b/src/libsyntax_ext/global_allocator.rs
@@ -28,7 +28,7 @@
};
// Generate a bunch of new items using the AllocFnFactory
- let span = ecx.with_legacy_ctxt(item.span);
+ let span = ecx.with_def_site_ctxt(item.span);
let f = AllocFnFactory {
span,
kind: AllocatorKind::Global,
@@ -43,7 +43,7 @@
let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
let const_body = ecx.expr_block(ecx.block(span, stmts));
let const_item =
- ecx.item_const(span, Ident::with_dummy_span(kw::Underscore), const_ty, const_body);
+ ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
// Return the original item and the new methods.
vec![Annotatable::Item(item), Annotatable::Item(const_item)]
@@ -61,7 +61,7 @@
let mut abi_args = Vec::new();
let mut i = 0;
let ref mut mk = || {
- let name = Ident::from_str(&format!("arg{}", i));
+ let name = self.cx.ident_of(&format!("arg{}", i), self.span);
i += 1;
name
};
@@ -83,7 +83,7 @@
);
let item = self.cx.item(
self.span,
- Ident::from_str(&self.kind.fn_name(method.name)),
+ self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
self.attrs(),
kind,
);
@@ -119,7 +119,7 @@
) -> P<Expr> {
match *ty {
AllocatorTy::Layout => {
- let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+ let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
let ty_usize = self.cx.ty_path(usize);
let size = ident();
let align = ident();
@@ -177,12 +177,12 @@
}
fn usize(&self) -> P<Ty> {
- let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize));
+ let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
self.cx.ty_path(usize)
}
fn ptr_u8(&self) -> P<Ty> {
- let u8 = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::u8));
+ let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
let ty_u8 = self.cx.ty_path(u8);
self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
}
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index 6140f0d..c56b3f3 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -30,7 +30,7 @@
id: ast::DUMMY_NODE_ID,
node: ast::ItemKind::GlobalAsm(P(global_asm)),
vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
- span: cx.with_legacy_ctxt(sp),
+ span: cx.with_def_site_ctxt(sp),
tokens: None,
})])
}
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 31d32d2..a5dcfb9 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -340,12 +340,12 @@
Vec::new(),
ast::ItemKind::ExternCrate(None));
- let bridge = Ident::from_str_and_span("bridge", span);
- let client = Ident::from_str_and_span("client", span);
- let proc_macro_ty = Ident::from_str_and_span("ProcMacro", span);
- let custom_derive = Ident::from_str_and_span("custom_derive", span);
- let attr = Ident::from_str_and_span("attr", span);
- let bang = Ident::from_str_and_span("bang", span);
+ let bridge = cx.ident_of("bridge", span);
+ let client = cx.ident_of("client", span);
+ let proc_macro_ty = cx.ident_of("ProcMacro", span);
+ let custom_derive = cx.ident_of("custom_derive", span);
+ let attr = cx.ident_of("attr", span);
+ let bang = cx.ident_of("bang", span);
let decls = {
let local_path = |sp: Span, name| {
@@ -378,7 +378,7 @@
let decls_static = cx.item_static(
span,
- Ident::from_str_and_span("_DECLS", span),
+ cx.ident_of("_DECLS", span),
cx.ty_rptr(span,
cx.ty(span, ast::TyKind::Slice(
cx.ty_path(cx.path(span,
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index be5aca7..0910c00 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -98,20 +98,20 @@
// creates test::$name
let test_path = |name| {
- cx.path(sp, vec![test_id, cx.ident_of(name)])
+ cx.path(sp, vec![test_id, cx.ident_of(name, sp)])
};
// creates test::ShouldPanic::$name
let should_panic_path = |name| {
- cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic"), cx.ident_of(name)])
+ cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)])
};
// creates $name: $expr
- let field = |name, expr| cx.field_imm(sp, cx.ident_of(name), expr);
+ let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr);
let test_fn = if is_bench {
// A simple ident for a lambda
- let b = ast::Ident::from_str_and_span("b", attr_sp);
+ let b = cx.ident_of("b", attr_sp);
cx.expr_call(sp, cx.expr_path(test_path("StaticBenchFn")), vec![
// |b| self::test::assert_test_result(
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
index b93c11f..56de0c9 100644
--- a/src/libsyntax_ext/test_harness.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -250,7 +250,7 @@
// test::test_main_static(...)
let mut test_runner = cx.test_runner.clone().unwrap_or(
- ecx.path(sp, vec![test_id, Ident::from_str_and_span("test_main_static", sp)]));
+ ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)]));
test_runner.span = sp;
@@ -288,7 +288,7 @@
// Honor the reexport_test_harness_main attribute
let main_id = match cx.reexport_test_harness_main {
Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
- None => Ident::from_str_and_span("main", sp),
+ None => Ident::new(sym::main, sp),
};
let main = P(ast::Item {
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 8142d44..e28d932 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -709,6 +709,13 @@
}
}
+ pub fn descr_expected(self) -> &'static str {
+ match self {
+ MacroKind::Attr => "attribute",
+ _ => self.descr(),
+ }
+ }
+
pub fn article(self) -> &'static str {
match self {
MacroKind::Attr => "an",
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9a296f1..ca177eb 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -526,13 +526,6 @@
self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
}
- /// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
- /// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
- /// or with `with_call_site_ctxt` (where necessary).
- pub fn with_legacy_ctxt(&self, expn_id: ExpnId) -> Span {
- self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent)
- }
-
/// Produces a span with the same location as `self` and context produced by a macro with the
/// given ID and transparency, assuming that macro was defined directly and not produced by
/// some other macro (which is the case for built-in and procedural macros).
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index ab32d44..597ae83 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -765,7 +765,7 @@
Ident::with_dummy_span(string.as_symbol())
}
- /// Maps a string to an identifier with an empty span.
+ /// Maps a string to an identifier with a dummy span.
pub fn from_str(string: &str) -> Ident {
Ident::with_dummy_span(Symbol::intern(string))
}
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/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs
index fef6253..8c86d2c 100644
--- a/src/test/debuginfo/function-arg-initialization.rs
+++ b/src/test/debuginfo/function-arg-initialization.rs
@@ -242,12 +242,12 @@
fn binding(a: i64, b: u64, c: f64) {
let x = 0; // #break
- println!("")
+ println!()
}
fn assignment(mut a: u64, b: u64, c: f64) {
a = b; // #break
- println!("")
+ println!()
}
fn function_call(x: u64, y: u64, z: f64) {
diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs
new file mode 100644
index 0000000..9bd8406
--- /dev/null
+++ b/src/test/ui/allocator/hygiene.rs
@@ -0,0 +1,31 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+#![allow(nonstandard_style)]
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+#[allow(dead_code)]
+struct u8;
+#[allow(dead_code)]
+struct usize;
+#[allow(dead_code)]
+static arg0: () = ();
+
+#[global_allocator]
+pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+fn main() {
+ let n = GLOBAL.0.load(Ordering::SeqCst);
+ let s = Box::new(0);
+ helper::work_with(&s);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+ drop(s);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
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/attributes/obsolete-attr.rs b/src/test/ui/attributes/obsolete-attr.rs
index cf6dd33..42f90ed 100644
--- a/src/test/ui/attributes/obsolete-attr.rs
+++ b/src/test/ui/attributes/obsolete-attr.rs
@@ -1,9 +1,9 @@
// Obsolete attributes fall back to unstable custom attributes.
#[ab_isize="stdcall"] extern {}
-//~^ ERROR cannot find attribute macro `ab_isize` in this scope
+//~^ ERROR cannot find attribute `ab_isize` in this scope
#[fixed_stack_segment] fn f() {}
-//~^ ERROR cannot find attribute macro `fixed_stack_segment` in this scope
+//~^ ERROR cannot find attribute `fixed_stack_segment` in this scope
fn main() {}
diff --git a/src/test/ui/attributes/obsolete-attr.stderr b/src/test/ui/attributes/obsolete-attr.stderr
index 9c6909f..2d7c257 100644
--- a/src/test/ui/attributes/obsolete-attr.stderr
+++ b/src/test/ui/attributes/obsolete-attr.stderr
@@ -1,10 +1,10 @@
-error: cannot find attribute macro `fixed_stack_segment` in this scope
+error: cannot find attribute `fixed_stack_segment` in this scope
--> $DIR/obsolete-attr.rs:6:3
|
LL | #[fixed_stack_segment] fn f() {}
| ^^^^^^^^^^^^^^^^^^^
-error: cannot find attribute macro `ab_isize` in this scope
+error: cannot find attribute `ab_isize` in this scope
--> $DIR/obsolete-attr.rs:3:3
|
LL | #[ab_isize="stdcall"] extern {}
diff --git a/src/test/ui/attributes/unknown-attr.rs b/src/test/ui/attributes/unknown-attr.rs
index 544a6e2..70fef04 100644
--- a/src/test/ui/attributes/unknown-attr.rs
+++ b/src/test/ui/attributes/unknown-attr.rs
@@ -3,10 +3,10 @@
#![feature(custom_inner_attributes)]
#![mutable_doc]
-//~^ ERROR cannot find attribute macro `mutable_doc` in this scope
+//~^ ERROR cannot find attribute `mutable_doc` in this scope
#[dance] mod a {}
-//~^ ERROR cannot find attribute macro `dance` in this scope
+//~^ ERROR cannot find attribute `dance` in this scope
#[dance] fn main() {}
-//~^ ERROR cannot find attribute macro `dance` in this scope
+//~^ ERROR cannot find attribute `dance` in this scope
diff --git a/src/test/ui/attributes/unknown-attr.stderr b/src/test/ui/attributes/unknown-attr.stderr
index 4d46387..85c227d 100644
--- a/src/test/ui/attributes/unknown-attr.stderr
+++ b/src/test/ui/attributes/unknown-attr.stderr
@@ -1,16 +1,16 @@
-error: cannot find attribute macro `mutable_doc` in this scope
+error: cannot find attribute `mutable_doc` in this scope
--> $DIR/unknown-attr.rs:5:4
|
LL | #![mutable_doc]
| ^^^^^^^^^^^
-error: cannot find attribute macro `dance` in this scope
+error: cannot find attribute `dance` in this scope
--> $DIR/unknown-attr.rs:8:3
|
LL | #[dance] mod a {}
| ^^^^^
-error: cannot find attribute macro `dance` in this scope
+error: cannot find attribute `dance` in this scope
--> $DIR/unknown-attr.rs:11:3
|
LL | #[dance] fn main() {}
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
index 4947d6e..ab8398e 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
@@ -37,11 +37,11 @@
--> $DIR/variadic-ffi-4.rs:20:5
|
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | ------- ------- has type `core::ffi::VaListImpl<'1>`
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
- | has type `&mut core::ffi::VaListImpl<'2>`
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
- | ^^^^ assignment requires that `'1` must outlive `'2`
+ | ^^^^ assignment requires that `'2` must outlive `'1`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:25:5
@@ -57,11 +57,11 @@
--> $DIR/variadic-ffi-4.rs:25:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
- | --- ------- has type `core::ffi::VaListImpl<'1>`
+ | --- ------- has type `core::ffi::VaListImpl<'2>`
| |
- | has type `&mut core::ffi::VaListImpl<'2>`
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
- | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+ | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
error[E0384]: cannot assign to immutable argument `ap0`
--> $DIR/variadic-ffi-4.rs:25:5
@@ -99,11 +99,11 @@
--> $DIR/variadic-ffi-4.rs:33:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | ------- ------- has type `core::ffi::VaListImpl<'1>`
+ | ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
- | has type `&mut core::ffi::VaListImpl<'2>`
+ | has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
- | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+ | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
error: aborting due to 11 previous errors
diff --git a/src/test/ui/coherence/conflicting-impl-with-err.rs b/src/test/ui/coherence/conflicting-impl-with-err.rs
new file mode 100644
index 0000000..3e0234b
--- /dev/null
+++ b/src/test/ui/coherence/conflicting-impl-with-err.rs
@@ -0,0 +1,16 @@
+struct ErrorKind;
+struct Error(ErrorKind);
+
+impl From<nope::Thing> for Error { //~ ERROR failed to resolve
+ fn from(_: nope::Thing) -> Self { //~ ERROR failed to resolve
+ unimplemented!()
+ }
+}
+
+impl From<ErrorKind> for Error {
+ fn from(_: ErrorKind) -> Self {
+ unimplemented!()
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/conflicting-impl-with-err.stderr b/src/test/ui/coherence/conflicting-impl-with-err.stderr
new file mode 100644
index 0000000..a8a5730
--- /dev/null
+++ b/src/test/ui/coherence/conflicting-impl-with-err.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: use of undeclared type or module `nope`
+ --> $DIR/conflicting-impl-with-err.rs:4:11
+ |
+LL | impl From<nope::Thing> for Error {
+ | ^^^^ use of undeclared type or module `nope`
+
+error[E0433]: failed to resolve: use of undeclared type or module `nope`
+ --> $DIR/conflicting-impl-with-err.rs:5:16
+ |
+LL | fn from(_: nope::Thing) -> Self {
+ | ^^^^ use of undeclared type or module `nope`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/collections-const-new.rs b/src/test/ui/collections-const-new.rs
index e01b0df..a93f9a1 100644
--- a/src/test/ui/collections-const-new.rs
+++ b/src/test/ui/collections-const-new.rs
@@ -1,15 +1,11 @@
-// run-pass
+// check-pass
-#![allow(dead_code)]
// Test several functions can be used for constants
// 1. Vec::new()
// 2. String::new()
-#![feature(const_vec_new)]
-#![feature(const_string_new)]
-
const MY_VEC: Vec<usize> = Vec::new();
const MY_STRING: String = String::new();
-pub fn main() {}
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs
new file mode 100644
index 0000000..9fa726f
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.rs
@@ -0,0 +1,3 @@
+// compile-flags: --cfg a{
+// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr
new file mode 100644
index 0000000..7d2087b
--- /dev/null
+++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-6.stderr
@@ -0,0 +1,2 @@
+error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
index 22dbac7..45b757e 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs
@@ -1,7 +1,7 @@
macro_rules! foo {
() => {
#[cfg_attr(all(), unknown)]
- //~^ ERROR cannot find attribute macro `unknown` in this scope
+ //~^ ERROR cannot find attribute `unknown` in this scope
fn foo() {}
}
}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
index c7c52a2..ef434ec 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27
|
LL | #[cfg_attr(all(), unknown)]
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.rs b/src/test/ui/conditional-compilation/cfg-generic-params.rs
index faf0195..53aa355 100644
--- a/src/test/ui/conditional-compilation/cfg-generic-params.rs
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.rs
@@ -17,22 +17,22 @@
fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK
fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK
fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK
type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
-//~^ ERROR cannot find attribute macro `unknown` in this scope
+//~^ ERROR cannot find attribute `unknown` in this scope
fn main() {
f_lt::<'static>();
diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.stderr b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
index f6e5732..d9e29c8 100644
--- a/src/test/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/src/test/ui/conditional-compilation/cfg-generic-params.stderr
@@ -16,31 +16,31 @@
LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
| ^
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:34:43
|
LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
| ^^^^^^^
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:30:40
|
LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
| ^^^^^^^
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:26:34
|
LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
| ^^^^^^^
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:22:29
|
LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {}
| ^^^^^^^
-error: cannot find attribute macro `unknown` in this scope
+error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:19:29
|
LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {}
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/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
index 5fb9253..8b17f68 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
@@ -14,8 +14,9 @@
impl Foo<u32> for () {
const X: u32 = 42;
}
+
impl Foo<Vec<u32>> for String {
- const X: Vec<u32> = Vec::new(); //~ ERROR not yet stable as a const fn
+ const X: Vec<u32> = Vec::new();
}
impl Bar<u32, ()> for () {}
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
index c56ebf6..5bc7b70 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
@@ -4,13 +4,5 @@
LL | const F: u32 = (U::X, 42).1;
| ^^^^^^^^^^ constants cannot evaluate destructors
-error: `std::vec::Vec::<T>::new` is not yet stable as a const fn
- --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:18:25
- |
-LL | const X: Vec<u32> = Vec::new();
- | ^^^^^^^^^^
- |
- = help: add `#![feature(const_vec_new)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs
new file mode 100644
index 0000000..b476e04
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+
+#![feature(const_raw_ptr_deref)]
+#![deny(const_err)]
+
+use std::cell::UnsafeCell;
+
+// make sure we do not just intern this as mutable
+const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
+
+const MUTATING_BEHIND_RAW: () = {
+ // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
+ unsafe {
+ *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
+ //~^ ERROR any use of this value will cause an error
+ //~^^ tried to modify constant memory
+ }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
new file mode 100644
index 0000000..507d4823
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -0,0 +1,27 @@
+warning: skipping const checks
+ --> $DIR/mutable_const.rs:14:9
+ |
+LL | *MUTABLE_BEHIND_RAW = 99
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: any use of this value will cause an error
+ --> $DIR/mutable_const.rs:14:9
+ |
+LL | / const MUTATING_BEHIND_RAW: () = {
+LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
+LL | | unsafe {
+LL | | *MUTABLE_BEHIND_RAW = 99
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
+... |
+LL | | }
+LL | | };
+ | |__-
+ |
+note: lint level defined here
+ --> $DIR/mutable_const.rs:4:9
+ |
+LL | #![deny(const_err)]
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
index 82569e2..28cf353 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
@@ -6,7 +6,7 @@
thread 'rustc' panicked at 'assertion failed: `(left != right)`
left: `Const`,
- right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:LL:CC
+ right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites could observe that mutation.', src/librustc_mir/interpret/intern.rs:LL:CC
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: internal compiler error: unexpected panic
diff --git a/src/test/ui/custom_attribute.rs b/src/test/ui/custom_attribute.rs
index 13c873c..4957184 100644
--- a/src/test/ui/custom_attribute.rs
+++ b/src/test/ui/custom_attribute.rs
@@ -1,9 +1,9 @@
#![feature(stmt_expr_attributes)]
-#[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+#[foo] //~ ERROR cannot find attribute `foo` in this scope
fn main() {
- #[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+ #[foo] //~ ERROR cannot find attribute `foo` in this scope
let x = ();
- #[foo] //~ ERROR cannot find attribute macro `foo` in this scope
+ #[foo] //~ ERROR cannot find attribute `foo` in this scope
x
}
diff --git a/src/test/ui/custom_attribute.stderr b/src/test/ui/custom_attribute.stderr
index b4f9f3f..4023892 100644
--- a/src/test/ui/custom_attribute.stderr
+++ b/src/test/ui/custom_attribute.stderr
@@ -1,16 +1,16 @@
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
--> $DIR/custom_attribute.rs:3:3
|
LL | #[foo]
| ^^^
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
--> $DIR/custom_attribute.rs:5:7
|
LL | #[foo]
| ^^^
-error: cannot find attribute macro `foo` in this scope
+error: cannot find attribute `foo` in this scope
--> $DIR/custom_attribute.rs:7:7
|
LL | #[foo]
diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs
index a4f4c26..fb13fd7 100644
--- a/src/test/ui/drop/dropck_legal_cycles.rs
+++ b/src/test/ui/drop/dropck_legal_cycles.rs
@@ -143,7 +143,7 @@
v[0].descend_into_self(&mut c);
assert!(!c.saw_prev_marked); // <-- different from below, b/c acyclic above
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 1: { v[0] -> v[1], v[1] -> v[0] };
// does not exercise `v` itself
@@ -158,7 +158,7 @@
v[0].descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 2: { v[0] -> v, v[1] -> v }
let v: V = Named::new("v");
@@ -171,7 +171,7 @@
v.descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 3: { hk0 -> hv0, hv0 -> hk0, hk1 -> hv1, hv1 -> hk1 };
// does not exercise `h` itself
@@ -193,7 +193,7 @@
assert!(c.saw_prev_marked);
}
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 4: { h -> (hmk0,hmv0,hmk1,hmv1), {hmk0,hmv0,hmk1,hmv1} -> h }
@@ -216,7 +216,7 @@
// break;
}
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 5: { vd[0] -> vd[1], vd[1] -> vd[0] };
// does not exercise vd itself
@@ -232,7 +232,7 @@
vd[0].descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 6: { vd -> (vd0, vd1), {vd0, vd1} -> vd }
let mut vd: VecDeque<VD> = VecDeque::new();
@@ -247,7 +247,7 @@
vd[0].descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 7: { vm -> (vm0, vm1), {vm0, vm1} -> vm }
let mut vm: HashMap<usize, VM> = HashMap::new();
@@ -262,7 +262,7 @@
vm[&0].descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 8: { ll -> (ll0, ll1), {ll0, ll1} -> ll }
let mut ll: LinkedList<LL> = LinkedList::new();
@@ -282,7 +282,7 @@
// break;
}
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 9: { bh -> (bh0, bh1), {bh0, bh1} -> bh }
let mut bh: BinaryHeap<BH> = BinaryHeap::new();
@@ -302,7 +302,7 @@
// break;
}
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 10: { btm -> (btk0, btv1), {bt0, bt1} -> btm }
let mut btm: BTreeMap<BTM, BTM> = BTreeMap::new();
@@ -323,7 +323,7 @@
// break;
}
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 10: { bts -> (bts0, bts1), {bts0, bts1} -> btm }
let mut bts: BTreeSet<BTS> = BTreeSet::new();
@@ -343,7 +343,7 @@
// break;
}
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 11: { rc0 -> (rc1, rc2), rc1 -> (), rc2 -> rc0 }
let (rc0, rc1, rc2): (RCRC, RCRC, RCRC);
@@ -361,7 +361,7 @@
rc0.descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// We want to take the previous Rc case and generalize it to Arc.
//
@@ -395,7 +395,7 @@
arc0.descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 13: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, rwlocks
let (arc0, arc1, arc2): (ARCRW, ARCRW, ARCRW);
@@ -413,7 +413,7 @@
arc0.descend_into_self(&mut c);
assert!(c.saw_prev_marked);
- if PRINT { println!(""); }
+ if PRINT { println!(); }
// Cycle 14: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, mutexs
let (arc0, arc1, arc2): (ARCM, ARCM, ARCM);
diff --git a/src/test/ui/empty/empty-macro-use.stderr b/src/test/ui/empty/empty-macro-use.stderr
index 1630041..8e3e068 100644
--- a/src/test/ui/empty/empty-macro-use.stderr
+++ b/src/test/ui/empty/empty-macro-use.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
--> $DIR/empty-macro-use.rs:7:5
|
LL | macro_two!();
diff --git a/src/test/ui/ext-nonexistent.stderr b/src/test/ui/ext-nonexistent.stderr
index 3fbbb49..f3aa83f 100644
--- a/src/test/ui/ext-nonexistent.stderr
+++ b/src/test/ui/ext-nonexistent.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `iamnotanextensionthatexists!` in this scope
+error: cannot find macro `iamnotanextensionthatexists` in this scope
--> $DIR/ext-nonexistent.rs:2:13
|
LL | fn main() { iamnotanextensionthatexists!(""); }
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
index d34936b..936cab2 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.rs
@@ -1,18 +1,18 @@
// Check that literals in attributes parse just fine.
-#[fake_attr] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(100)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr("hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(name = "hello")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute macro `fake_attr` in th
-#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute macro `fake_attr` in this scop
-#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute macro `fake_attr` in
-#[fake_attr(true)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_attr(b"hi")] //~ ERROR cannot find attribute macro `fake_attr` in this scope
-#[fake_doc(r"doc")] //~ ERROR cannot find attribute macro `fake_doc` in this scope
+#[fake_attr] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(100)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr("hello")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(name = "hello")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute `fake_attr` in th
+#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute `fake_attr` in this scop
+#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute `fake_attr` in
+#[fake_attr(true)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_attr(b"hi")] //~ ERROR cannot find attribute `fake_attr` in this scope
+#[fake_doc(r"doc")] //~ ERROR cannot find attribute `fake_doc` in this scope
struct Q {}
fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
index efdc2d1..b7c45ec 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute.stderr
@@ -1,76 +1,76 @@
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:3:3
|
LL | #[fake_attr]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:4:3
|
LL | #[fake_attr(100)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:5:3
|
LL | #[fake_attr(1, 2, 3)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:6:3
|
LL | #[fake_attr("hello")]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:7:3
|
LL | #[fake_attr(name = "hello")]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:8:3
|
LL | #[fake_attr(1, "hi", key = 12, true, false)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:9:3
|
LL | #[fake_attr(key = "hello", val = 10)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:10:3
|
LL | #[fake_attr(key("hello"), val(10))]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:11:3
|
LL | #[fake_attr(enabled = true, disabled = false)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:12:3
|
LL | #[fake_attr(true)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:13:3
|
LL | #[fake_attr(pi = 3.14159)]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_attr` in this scope
+error: cannot find attribute `fake_attr` in this scope
--> $DIR/feature-gate-custom_attribute.rs:14:3
|
LL | #[fake_attr(b"hi")]
| ^^^^^^^^^
-error: cannot find attribute macro `fake_doc` in this scope
+error: cannot find attribute `fake_doc` in this scope
--> $DIR/feature-gate-custom_attribute.rs:15:3
|
LL | #[fake_doc(r"doc")]
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
index 51b5bf5..e4c8014 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.rs
@@ -4,54 +4,54 @@
// gate-test-custom_attribute
struct StLt<#[lt_struct] 'a>(&'a u32);
-//~^ ERROR cannot find attribute macro `lt_struct` in this scope
+//~^ ERROR cannot find attribute `lt_struct` in this scope
struct StTy<#[ty_struct] I>(I);
-//~^ ERROR cannot find attribute macro `ty_struct` in this scope
+//~^ ERROR cannot find attribute `ty_struct` in this scope
enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
-//~^ ERROR cannot find attribute macro `lt_enum` in this scope
+//~^ ERROR cannot find attribute `lt_enum` in this scope
enum EnTy<#[ty_enum] J> { A(J), B }
-//~^ ERROR cannot find attribute macro `ty_enum` in this scope
+//~^ ERROR cannot find attribute `ty_enum` in this scope
trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-//~^ ERROR cannot find attribute macro `lt_trait` in this scope
+//~^ ERROR cannot find attribute `lt_trait` in this scope
trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
-//~^ ERROR cannot find attribute macro `ty_trait` in this scope
+//~^ ERROR cannot find attribute `ty_trait` in this scope
type TyLt<#[lt_type] 'd> = &'d u32;
-//~^ ERROR cannot find attribute macro `lt_type` in this scope
+//~^ ERROR cannot find attribute `lt_type` in this scope
type TyTy<#[ty_type] L> = (L, );
-//~^ ERROR cannot find attribute macro `ty_type` in this scope
+//~^ ERROR cannot find attribute `ty_type` in this scope
impl<#[lt_inherent] 'e> StLt<'e> { }
-//~^ ERROR cannot find attribute macro `lt_inherent` in this scope
+//~^ ERROR cannot find attribute `lt_inherent` in this scope
impl<#[ty_inherent] M> StTy<M> { }
-//~^ ERROR cannot find attribute macro `ty_inherent` in this scope
+//~^ ERROR cannot find attribute `ty_inherent` in this scope
impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
- //~^ ERROR cannot find attribute macro `lt_impl_for` in this scope
+ //~^ ERROR cannot find attribute `lt_impl_for` in this scope
fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
}
impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
- //~^ ERROR cannot find attribute macro `ty_impl_for` in this scope
+ //~^ ERROR cannot find attribute `ty_impl_for` in this scope
fn foo(&self, _: N) { }
}
fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-//~^ ERROR cannot find attribute macro `lt_fn` in this scope
+//~^ ERROR cannot find attribute `lt_fn` in this scope
fn f_ty<#[ty_fn] O>(_: O) { }
-//~^ ERROR cannot find attribute macro `ty_fn` in this scope
+//~^ ERROR cannot find attribute `ty_fn` in this scope
impl<I> StTy<I> {
fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
- //~^ ERROR cannot find attribute macro `lt_meth` in this scope
+ //~^ ERROR cannot find attribute `lt_meth` in this scope
fn m_ty<#[ty_meth] P>(_: P) { }
- //~^ ERROR cannot find attribute macro `ty_meth` in this scope
+ //~^ ERROR cannot find attribute `ty_meth` in this scope
}
fn hof_lt<Q>(_: Q)
where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
- //~^ ERROR cannot find attribute macro `lt_hof` in this scope
+ //~^ ERROR cannot find attribute `lt_hof` in this scope
{
}
diff --git a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
index 9250616..bc89cad 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_attribute2.stderr
@@ -1,100 +1,100 @@
-error: cannot find attribute macro `lt_hof` in this scope
+error: cannot find attribute `lt_hof` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:53:21
|
LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
| ^^^^^^
-error: cannot find attribute macro `ty_meth` in this scope
+error: cannot find attribute `ty_meth` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:48:15
|
LL | fn m_ty<#[ty_meth] P>(_: P) { }
| ^^^^^^^
-error: cannot find attribute macro `lt_meth` in this scope
+error: cannot find attribute `lt_meth` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:46:15
|
LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
| ^^^^^^^
-error: cannot find attribute macro `ty_fn` in this scope
+error: cannot find attribute `ty_fn` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:42:11
|
LL | fn f_ty<#[ty_fn] O>(_: O) { }
| ^^^^^
-error: cannot find attribute macro `lt_fn` in this scope
+error: cannot find attribute `lt_fn` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:40:11
|
LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
| ^^^^^
-error: cannot find attribute macro `ty_impl_for` in this scope
+error: cannot find attribute `ty_impl_for` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:35:8
|
LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
| ^^^^^^^^^^^
-error: cannot find attribute macro `lt_impl_for` in this scope
+error: cannot find attribute `lt_impl_for` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:31:8
|
LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
| ^^^^^^^^^^^
-error: cannot find attribute macro `ty_inherent` in this scope
+error: cannot find attribute `ty_inherent` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:28:8
|
LL | impl<#[ty_inherent] M> StTy<M> { }
| ^^^^^^^^^^^
-error: cannot find attribute macro `lt_inherent` in this scope
+error: cannot find attribute `lt_inherent` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:26:8
|
LL | impl<#[lt_inherent] 'e> StLt<'e> { }
| ^^^^^^^^^^^
-error: cannot find attribute macro `ty_type` in this scope
+error: cannot find attribute `ty_type` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:23:13
|
LL | type TyTy<#[ty_type] L> = (L, );
| ^^^^^^^
-error: cannot find attribute macro `lt_type` in this scope
+error: cannot find attribute `lt_type` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:21:13
|
LL | type TyLt<#[lt_type] 'd> = &'d u32;
| ^^^^^^^
-error: cannot find attribute macro `ty_trait` in this scope
+error: cannot find attribute `ty_trait` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:18:14
|
LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
| ^^^^^^^^
-error: cannot find attribute macro `lt_trait` in this scope
+error: cannot find attribute `lt_trait` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:16:14
|
LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
| ^^^^^^^^
-error: cannot find attribute macro `ty_enum` in this scope
+error: cannot find attribute `ty_enum` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:13:13
|
LL | enum EnTy<#[ty_enum] J> { A(J), B }
| ^^^^^^^
-error: cannot find attribute macro `lt_enum` in this scope
+error: cannot find attribute `lt_enum` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:11:13
|
LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
| ^^^^^^^
-error: cannot find attribute macro `ty_struct` in this scope
+error: cannot find attribute `ty_struct` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:8:15
|
LL | struct StTy<#[ty_struct] I>(I);
| ^^^^^^^^^
-error: cannot find attribute macro `lt_struct` in this scope
+error: cannot find attribute `lt_struct` in this scope
--> $DIR/feature-gate-custom_attribute2.rs:6:15
|
LL | struct StLt<#[lt_struct] 'a>(&'a u32);
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
index 4044fd2..c985298 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
@@ -19,5 +19,5 @@
//~^ ERROR the `#[rustc_dummy]` attribute is just used for rustc unit tests
#[rustc_unknown]
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
-//~| ERROR cannot find attribute macro `rustc_unknown` in this scope
+//~| ERROR cannot find attribute `rustc_unknown` in this scope
fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
index c106302..d6fdab2 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
@@ -37,7 +37,7 @@
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
-error: cannot find attribute macro `rustc_unknown` in this scope
+error: cannot find attribute `rustc_unknown` in this scope
--> $DIR/feature-gate-rustc-attrs.rs:20:3
|
LL | #[rustc_unknown]
diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs
index 43b1a04..0fbc796 100644
--- a/src/test/ui/for/for-c-in-str.rs
+++ b/src/test/ui/for/for-c-in-str.rs
@@ -6,6 +6,6 @@
//~| NOTE `&str` is not an iterator
//~| HELP the trait `std::iter::Iterator` is not implemented for `&str`
//~| NOTE required by `std::iter::IntoIterator::into_iter`
- println!("");
+ println!();
}
}
diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr
index 92f92e2..dab4d34 100644
--- a/src/test/ui/generator/auto-trait-regions.stderr
+++ b/src/test/ui/generator/auto-trait-regions.stderr
@@ -1,20 +1,26 @@
error: implementation of `Foo` is not general enough
--> $DIR/auto-trait-regions.rs:30:5
|
+LL | auto trait Foo {}
+ | ----------------- trait `Foo` defined here
+...
LL | assert_foo(gen);
- | ^^^^^^^^^^
+ | ^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`
- = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
+ = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`...
+ = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough
--> $DIR/auto-trait-regions.rs:48:5
|
+LL | auto trait Foo {}
+ | ----------------- trait `Foo` defined here
+...
LL | assert_foo(gen);
- | ^^^^^^^^^^
+ | ^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`
- = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+ = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/hrtb/due-to-where-clause.rs b/src/test/ui/hrtb/due-to-where-clause.rs
new file mode 100644
index 0000000..04e2ddd
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.rs
@@ -0,0 +1,16 @@
+// ignore-compare-mode-nll
+// ^ This code works in nll mode.
+
+fn main() {
+ test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
+}
+
+trait Foo<'a> {}
+
+struct FooS<'a> {
+ data: &'a mut u32,
+}
+
+impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {}
+
+fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr
new file mode 100644
index 0000000..e698584
--- /dev/null
+++ b/src/test/ui/hrtb/due-to-where-clause.stderr
@@ -0,0 +1,17 @@
+error: implementation of `Foo` is not general enough
+ --> $DIR/due-to-where-clause.rs:5:5
+ |
+LL | test::<FooS>(&mut 42);
+ | ^^^^^^^^^^^^ doesn't satisfy where-clause
+...
+LL | trait Foo<'a> {}
+ | ---------------- trait `Foo` defined here
+...
+LL | fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {}
+ | ------------------------------------------------------------- due to a where-clause on `test`...
+ |
+ = note: ...`FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
+ = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
index 77a5491..003f326 100644
--- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
+++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr
@@ -1,11 +1,14 @@
error: implementation of `Deserialize` is not general enough
--> $DIR/hrtb-cache-issue-54302.rs:19:5
|
+LL | trait Deserialize<'de> {}
+ | ------------------------- trait `Deserialize` defined here
+...
LL | assert_deserialize_owned::<&'static str>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
|
- = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
- = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+ = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+ = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
error: aborting due to previous error
diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr
index e7deca7..c0e3fd3 100644
--- a/src/test/ui/hrtb/issue-30786.migrate.stderr
+++ b/src/test/ui/hrtb/issue-30786.migrate.stderr
@@ -1,11 +1,17 @@
error: implementation of `Stream` is not general enough
--> $DIR/issue-30786.rs:108:22
|
-LL | let map = source.map(|x: &_| x);
- | ^^^
+LL | / pub trait Stream {
+LL | | type Item;
+LL | | fn next(self) -> Option<Self::Item>;
+LL | | }
+ | |_- trait `Stream` defined here
+...
+LL | let map = source.map(|x: &_| x);
+ | ^^^ implementation of `Stream` is not general enough
|
- = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`
- = note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
+ = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`...
+ = note: ...but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
error: aborting due to previous error
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
index 8614d86..1cfd93e 100644
--- a/src/test/ui/hrtb/issue-30786.nll.stderr
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -1,11 +1,11 @@
error: higher-ranked subtype error
- --> $DIR/issue-30786.rs:112:18
+ --> $DIR/issue-30786.rs:113:18
|
LL | let filter = map.filter(|x: &_| true);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
- --> $DIR/issue-30786.rs:114:17
+ --> $DIR/issue-30786.rs:115:17
|
LL | let count = filter.count(); // Assert that we still have a valid stream.
| ^^^^^^^^^^^^^^
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
index b9920a1..c42297c 100644
--- a/src/test/ui/hrtb/issue-30786.rs
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -16,7 +16,7 @@
//[nll]compile-flags: -Z borrowck=mir
-pub trait Stream {
+pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
type Item;
fn next(self) -> Option<Self::Item>;
}
@@ -109,6 +109,7 @@
//[migrate]~^ ERROR implementation of `Stream` is not general enough
//[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map
//[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1
+ //[migrate]~| NOTE implementation of `Stream` is not general enough
let filter = map.filter(|x: &_| true);
//[nll]~^ ERROR higher-ranked subtype error
let count = filter.count(); // Assert that we still have a valid stream.
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
index 3ad7435..83ca281 100644
--- a/src/test/ui/hygiene/no_implicit_prelude-2018.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
@@ -4,7 +4,7 @@
mod bar {
fn f() {
::std::print!(""); // OK
- print!(); //~ ERROR cannot find macro `print!` in this scope
+ print!(); //~ ERROR cannot find macro `print` in this scope
}
}
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
index 0fdb18d..f31b752 100644
--- a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `print!` in this scope
+error: cannot find macro `print` in this scope
--> $DIR/no_implicit_prelude-2018.rs:7:9
|
LL | print!();
diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
index 890c830..204e7b2 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
@@ -13,7 +13,7 @@
}
fn f() {
::foo::m!();
- assert_eq!(0, 0); //~ ERROR cannot find macro `panic!` in this scope
+ assert_eq!(0, 0); //~ ERROR cannot find macro `panic` in this scope
}
}
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index 8fa55d0..bc0ce74 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `panic!` in this scope
+error: cannot find macro `panic` in this scope
--> $DIR/no_implicit_prelude.rs:16:9
|
LL | assert_eq!(0, 0);
diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs
index 70b712c..b6f3bb8 100644
--- a/src/test/ui/issues/issue-11692-1.rs
+++ b/src/test/ui/issues/issue-11692-1.rs
@@ -1,3 +1,3 @@
fn main() {
- print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope
+ print!(testo!()); //~ ERROR cannot find macro `testo` in this scope
}
diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr
index bfd1647..3864634 100644
--- a/src/test/ui/issues/issue-11692-1.stderr
+++ b/src/test/ui/issues/issue-11692-1.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `testo!` in this scope
+error: cannot find macro `testo` in this scope
--> $DIR/issue-11692-1.rs:2:12
|
LL | print!(testo!());
diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs
index 61be284..5957ed3 100644
--- a/src/test/ui/issues/issue-11692-2.rs
+++ b/src/test/ui/issues/issue-11692-2.rs
@@ -1,3 +1,3 @@
fn main() {
- concat!(test!()); //~ ERROR cannot find macro `test!` in this scope
+ concat!(test!()); //~ ERROR cannot find macro `test` in this scope
}
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
index 740c355..f021943 100644
--- a/src/test/ui/issues/issue-11692-2.stderr
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `test!` in this scope
+error: cannot find macro `test` in this scope
--> $DIR/issue-11692-2.rs:2:13
|
LL | concat!(test!());
diff --git a/src/test/ui/issues/issue-19734.rs b/src/test/ui/issues/issue-19734.rs
index b730e19..fe4a327 100644
--- a/src/test/ui/issues/issue-19734.rs
+++ b/src/test/ui/issues/issue-19734.rs
@@ -4,5 +4,5 @@
impl Type {
undef!();
- //~^ ERROR cannot find macro `undef!` in this scope
+ //~^ ERROR cannot find macro `undef` in this scope
}
diff --git a/src/test/ui/issues/issue-19734.stderr b/src/test/ui/issues/issue-19734.stderr
index fc1a7d0..8175797 100644
--- a/src/test/ui/issues/issue-19734.stderr
+++ b/src/test/ui/issues/issue-19734.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `undef!` in this scope
+error: cannot find macro `undef` in this scope
--> $DIR/issue-19734.rs:6:5
|
LL | undef!();
diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs
index fad7bf5..f52e092 100644
--- a/src/test/ui/issues/issue-32655.rs
+++ b/src/test/ui/issues/issue-32655.rs
@@ -1,6 +1,6 @@
macro_rules! foo (
() => (
- #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
+ #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope
struct T;
);
);
@@ -12,7 +12,7 @@
foo!();
bar!(
- #[derive_Clone] //~ ERROR cannot find attribute macro `derive_Clone` in this scope
+ #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope
struct S;
);
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
index e13bed0..ca085b2 100644
--- a/src/test/ui/issues/issue-32655.stderr
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `derive_Clone` in this scope
+error: cannot find attribute `derive_Clone` in this scope
--> $DIR/issue-32655.rs:3:11
|
LL | #[derive_Clone]
@@ -7,7 +7,7 @@
LL | foo!();
| ------- in this macro invocation
-error: cannot find attribute macro `derive_Clone` in this scope
+error: cannot find attribute `derive_Clone` in this scope
--> $DIR/issue-32655.rs:15:7
|
LL | #[derive_Clone]
diff --git a/src/test/ui/issues/issue-40845.rs b/src/test/ui/issues/issue-40845.rs
index c9102f4..a4ede6a 100644
--- a/src/test/ui/issues/issue-40845.rs
+++ b/src/test/ui/issues/issue-40845.rs
@@ -1,6 +1,6 @@
-trait T { m!(); } //~ ERROR cannot find macro `m!` in this scope
+trait T { m!(); } //~ ERROR cannot find macro `m` in this scope
struct S;
-impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope
+impl S { m!(); } //~ ERROR cannot find macro `m` in this scope
fn main() {}
diff --git a/src/test/ui/issues/issue-40845.stderr b/src/test/ui/issues/issue-40845.stderr
index a8be38e..2744330 100644
--- a/src/test/ui/issues/issue-40845.stderr
+++ b/src/test/ui/issues/issue-40845.stderr
@@ -1,10 +1,10 @@
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
--> $DIR/issue-40845.rs:4:10
|
LL | impl S { m!(); }
| ^
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
--> $DIR/issue-40845.rs:1:11
|
LL | trait T { m!(); }
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-49074.rs b/src/test/ui/issues/issue-49074.rs
index 38074d5..752bb34 100644
--- a/src/test/ui/issues/issue-49074.rs
+++ b/src/test/ui/issues/issue-49074.rs
@@ -1,7 +1,7 @@
// Check that unknown attribute error is shown even if there are unresolved macros.
#[marco_use] // typo
-//~^ ERROR cannot find attribute macro `marco_use` in this scope
+//~^ ERROR cannot find attribute `marco_use` in this scope
mod foo {
macro_rules! bar {
() => ();
@@ -9,5 +9,5 @@
}
fn main() {
- bar!(); //~ ERROR cannot find macro `bar!` in this scope
+ bar!(); //~ ERROR cannot find macro `bar` in this scope
}
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
index e0d3bb3..bbfeb4e 100644
--- a/src/test/ui/issues/issue-49074.stderr
+++ b/src/test/ui/issues/issue-49074.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `bar!` in this scope
+error: cannot find macro `bar` in this scope
--> $DIR/issue-49074.rs:12:4
|
LL | bar!();
@@ -6,7 +6,7 @@
|
= help: have you added the `#[macro_use]` on the module/import?
-error: cannot find attribute macro `marco_use` in this scope
+error: cannot find attribute `marco_use` in this scope
--> $DIR/issue-49074.rs:3:3
|
LL | #[marco_use] // typo
diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr
index 9863761..3ed2779 100644
--- a/src/test/ui/issues/issue-54302-cases.stderr
+++ b/src/test/ui/issues/issue-54302-cases.stderr
@@ -1,38 +1,58 @@
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:63:5
|
-LL | <u32 as RefFoo<u32>>::ref_foo(a)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | | fn foo(self) -> &'x T;
+LL | | }
+ | |_- trait `Foo` defined here
+...
+LL | <u32 as RefFoo<u32>>::ref_foo(a)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
- = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
+ = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
+ = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:69:5
|
-LL | <i32 as RefFoo<i32>>::ref_foo(a)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | | fn foo(self) -> &'x T;
+LL | | }
+ | |_- trait `Foo` defined here
+...
+LL | <i32 as RefFoo<i32>>::ref_foo(a)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`
- = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
+ = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`...
+ = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:75:5
|
-LL | <u64 as RefFoo<u64>>::ref_foo(a)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | | fn foo(self) -> &'x T;
+LL | | }
+ | |_- trait `Foo` defined here
+...
+LL | <u64 as RefFoo<u64>>::ref_foo(a)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`
- = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
+ = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`...
+ = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:81:5
|
-LL | <i64 as RefFoo<i64>>::ref_foo(a)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / trait Foo<'x, T> {
+LL | | fn foo(self) -> &'x T;
+LL | | }
+ | |_- trait `Foo` defined here
+...
+LL | <i64 as RefFoo<i64>>::ref_foo(a)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`
- = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
+ = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`...
+ = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
error: aborting due to 4 previous errors
diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr
index c6d0805..1b3f57b 100644
--- a/src/test/ui/issues/issue-54302.stderr
+++ b/src/test/ui/issues/issue-54302.stderr
@@ -1,11 +1,14 @@
error: implementation of `Deserialize` is not general enough
--> $DIR/issue-54302.rs:13:5
|
+LL | trait Deserialize<'de> {}
+ | ------------------------- trait `Deserialize` defined here
+...
LL | assert_deserialize_owned::<&'static str>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
|
- = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
- = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
+ = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`...
+ = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr
index f25e18e..f44c842 100644
--- a/src/test/ui/issues/issue-55731.stderr
+++ b/src/test/ui/issues/issue-55731.stderr
@@ -1,11 +1,16 @@
error: implementation of `DistributedIteratorMulti` is not general enough
--> $DIR/issue-55731.rs:48:5
|
-LL | multi(Map {
- | ^^^^^
+LL | / trait DistributedIteratorMulti<Source> {
+LL | | type Item;
+LL | | }
+ | |_- trait `DistributedIteratorMulti` defined here
+...
+LL | multi(Map {
+ | ^^^^^ implementation of `DistributedIteratorMulti` is not general enough
|
- = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
- = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
+ = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`...
+ = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
error: aborting due to previous error
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/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
index 779e2eb..2ed4d6d 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
@@ -12,11 +12,11 @@
--> $DIR/ex3-both-anon-regions-3.rs:2:5
|
LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
- | - - let's call the lifetime of this reference `'1`
+ | - - let's call the lifetime of this reference `'3`
| |
- | let's call the lifetime of this reference `'2`
+ | let's call the lifetime of this reference `'4`
LL | z.push((x,y));
- | ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
+ | ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
index 1d8cce5..7dcbdd0 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
@@ -1,4 +1,4 @@
-#![feature(box_patterns)]
+#![feature(box_patterns, stmt_expr_attributes)]
#![feature(or_patterns)]
//~^ WARN the feature `or_patterns` is incomplete
@@ -17,6 +17,10 @@
let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
}
+fn _no_lint_attr() {
+ let _x = #[allow(dead_code)] (1 + 2);
+}
+
// Don't lint in these cases (#64106).
fn or_patterns_no_lint() {
match Box::new(0) {
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
index 7d5e286..675dd4f 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr
@@ -49,109 +49,109 @@
| ^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:41:12
+ --> $DIR/issue-54538-unused-parens-lint.rs:45:12
|
LL | if let (0 | 1) = 0 {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:42:13
+ --> $DIR/issue-54538-unused-parens-lint.rs:46:13
|
LL | if let ((0 | 1),) = (0,) {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:43:13
+ --> $DIR/issue-54538-unused-parens-lint.rs:47:13
|
LL | if let [(0 | 1)] = [0] {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:44:16
+ --> $DIR/issue-54538-unused-parens-lint.rs:48:16
|
LL | if let 0 | (1 | 2) = 0 {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:46:15
+ --> $DIR/issue-54538-unused-parens-lint.rs:50:15
|
LL | if let TS((0 | 1)) = TS(0) {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:48:20
+ --> $DIR/issue-54538-unused-parens-lint.rs:52:20
|
LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:58:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:62:9
|
LL | (_) => {}
| ^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:59:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:63:9
|
LL | (y) => {}
| ^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:60:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:64:9
|
LL | (ref r) => {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:61:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:65:9
|
LL | (e @ 1...2) => {}
| ^^^^^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:67:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:71:9
|
LL | (e @ &(1...2)) => {}
| ^^^^^^^^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:68:10
+ --> $DIR/issue-54538-unused-parens-lint.rs:72:10
|
LL | &(_) => {}
| ^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:79:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:83:9
|
LL | (_) => {}
| ^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:80:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:84:9
|
LL | (y) => {}
| ^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:81:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:85:9
|
LL | (ref r) => {}
| ^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:82:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:86:9
|
LL | (e @ 1..=2) => {}
| ^^^^^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:88:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:92:9
|
LL | (e @ &(1..=2)) => {}
| ^^^^^^^^^^^^^^ help: remove these parentheses
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:89:10
+ --> $DIR/issue-54538-unused-parens-lint.rs:93:10
|
LL | &(_) => {}
| ^^^ help: remove these parentheses
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/macros/macro-expansion-tests.stderr b/src/test/ui/macros/macro-expansion-tests.stderr
index 4ad9ade..8b3f7ca 100644
--- a/src/test/ui/macros/macro-expansion-tests.stderr
+++ b/src/test/ui/macros/macro-expansion-tests.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
--> $DIR/macro-expansion-tests.rs:7:21
|
LL | fn g() -> i32 { m!() }
@@ -6,7 +6,7 @@
|
= help: have you added the `#[macro_use]` on the module/import?
-error: cannot find macro `m!` in this scope
+error: cannot find macro `m` in this scope
--> $DIR/macro-expansion-tests.rs:15:21
|
LL | fn g() -> i32 { m!() }
diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr
index 967f4f3..ce2e198 100644
--- a/src/test/ui/macros/macro-name-typo.stderr
+++ b/src/test/ui/macros/macro-name-typo.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `printlx!` in this scope
+error: cannot find macro `printlx` in this scope
--> $DIR/macro-name-typo.rs:2:5
|
LL | printlx!("oh noes!");
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.rs b/src/test/ui/macros/macro-path-prelude-fail-3.rs
index 597053d..68eb350 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.rs
@@ -1,3 +1,3 @@
fn main() {
- inline!(); //~ ERROR cannot find macro `inline!` in this scope
+ inline!(); //~ ERROR cannot find macro `inline` in this scope
}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index 96b8a24..ec00760 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `inline!` in this scope
+error: cannot find macro `inline` in this scope
--> $DIR/macro-path-prelude-fail-3.rs:2:5
|
LL | inline!();
diff --git a/src/test/ui/macros/macro-reexport-removed.rs b/src/test/ui/macros/macro-reexport-removed.rs
index b69a1fa..874c94d 100644
--- a/src/test/ui/macros/macro-reexport-removed.rs
+++ b/src/test/ui/macros/macro-reexport-removed.rs
@@ -2,7 +2,7 @@
#![feature(macro_reexport)] //~ ERROR feature has been removed
-#[macro_reexport(macro_one)] //~ ERROR cannot find attribute macro `macro_reexport` in this scope
+#[macro_reexport(macro_one)] //~ ERROR cannot find attribute `macro_reexport` in this scope
extern crate two_macros;
fn main() {}
diff --git a/src/test/ui/macros/macro-reexport-removed.stderr b/src/test/ui/macros/macro-reexport-removed.stderr
index 25778fb..4bec708 100644
--- a/src/test/ui/macros/macro-reexport-removed.stderr
+++ b/src/test/ui/macros/macro-reexport-removed.stderr
@@ -10,7 +10,7 @@
LL | #![feature(macro_reexport)]
| ^^^^^^^^^^^^^^
-error: cannot find attribute macro `macro_reexport` in this scope
+error: cannot find attribute `macro_reexport` in this scope
--> $DIR/macro-reexport-removed.rs:5:3
|
LL | #[macro_reexport(macro_one)]
diff --git a/src/test/ui/macros/macro-use-wrong-name.stderr b/src/test/ui/macros/macro-use-wrong-name.stderr
index 28f727d..8b4e90a 100644
--- a/src/test/ui/macros/macro-use-wrong-name.stderr
+++ b/src/test/ui/macros/macro-use-wrong-name.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
--> $DIR/macro-use-wrong-name.rs:7:5
|
LL | macro_two!();
diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr
index 9239b2a..01c8ebe 100644
--- a/src/test/ui/macros/macro_undefined.stderr
+++ b/src/test/ui/macros/macro_undefined.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `k!` in this scope
+error: cannot find macro `k` in this scope
--> $DIR/macro_undefined.rs:11:5
|
LL | k!();
diff --git a/src/test/ui/missing/missing-macro-use.rs b/src/test/ui/missing/missing-macro-use.rs
index dff4c94..d494c44 100644
--- a/src/test/ui/missing/missing-macro-use.rs
+++ b/src/test/ui/missing/missing-macro-use.rs
@@ -4,5 +4,5 @@
pub fn main() {
macro_two!();
- //~^ ERROR cannot find macro `macro_two!` in this scope
+ //~^ ERROR cannot find macro `macro_two` in this scope
}
diff --git a/src/test/ui/missing/missing-macro-use.stderr b/src/test/ui/missing/missing-macro-use.stderr
index 01a7beb..711e249 100644
--- a/src/test/ui/missing/missing-macro-use.stderr
+++ b/src/test/ui/missing/missing-macro-use.stderr
@@ -1,4 +1,4 @@
-error: cannot find macro `macro_two!` in this scope
+error: cannot find macro `macro_two` in this scope
--> $DIR/missing-macro-use.rs:6:5
|
LL | macro_two!();
diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs
index 4e6f9b0..3f8d6f0 100644
--- a/src/test/ui/proc-macro/derive-still-gated.rs
+++ b/src/test/ui/proc-macro/derive-still-gated.rs
@@ -3,7 +3,7 @@
#[macro_use]
extern crate test_macros;
-#[derive_Empty] //~ ERROR cannot find attribute macro `derive_Empty` in this scope
+#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope
struct A;
fn main() {}
diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr
index 4df1715..99289fd 100644
--- a/src/test/ui/proc-macro/derive-still-gated.stderr
+++ b/src/test/ui/proc-macro/derive-still-gated.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `derive_Empty` in this scope
+error: cannot find attribute `derive_Empty` in this scope
--> $DIR/derive-still-gated.rs:6:3
|
LL | #[derive_Empty]
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
index 8a26df9..b17c056 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -25,17 +25,17 @@
my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
}
fn check_bang2() {
- my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope
+ my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope
crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
//~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
}
fn check_bang3() {
- MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope
+ MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope
crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected macro, found derive macro `crate::MyTrait`
}
-#[my_macro] //~ ERROR cannot find attribute macro `my_macro` in this scope
+#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope
#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected attribute, found macro `crate::my_macro`
fn check_attr1() {}
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index 0c863e9..c011a70 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -88,19 +88,19 @@
LL | #[derive(crate::my_macro)]
| ^^^^^^^^^^^^^^^ not a derive macro
-error: cannot find macro `my_macro_attr!` in this scope
+error: cannot find macro `my_macro_attr` in this scope
--> $DIR/macro-namespace-reserved-2.rs:28:5
|
LL | my_macro_attr!();
| ^^^^^^^^^^^^^
-error: cannot find macro `MyTrait!` in this scope
+error: cannot find macro `MyTrait` in this scope
--> $DIR/macro-namespace-reserved-2.rs:33:5
|
LL | MyTrait!();
| ^^^^^^^
-error: cannot find attribute macro `my_macro` in this scope
+error: cannot find attribute `my_macro` in this scope
--> $DIR/macro-namespace-reserved-2.rs:38:3
|
LL | #[my_macro]
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs
index 0421522..6401522 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.rs
+++ b/src/test/ui/proc-macro/proc-macro-attributes.rs
@@ -4,7 +4,7 @@
extern crate derive_b;
#[B] //~ ERROR `B` is ambiguous
-#[C] //~ ERROR cannot find attribute macro `C` in this scope
+#[C] //~ ERROR cannot find attribute `C` in this scope
#[B(D)] //~ ERROR `B` is ambiguous
#[B(E = "foo")] //~ ERROR `B` is ambiguous
#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
index b068c6b..3ac93a7 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.stderr
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -1,4 +1,4 @@
-error: cannot find attribute macro `C` in this scope
+error: cannot find attribute `C` in this scope
--> $DIR/proc-macro-attributes.rs:7:3
|
LL | #[C]
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
index 088f39c..d2282af 100644
--- a/src/test/ui/proc-macro/resolve-error.rs
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -24,11 +24,11 @@
struct Foo;
// Interpreted as an unstable custom attribute
-#[attr_proc_macra] //~ ERROR cannot find attribute macro `attr_proc_macra` in this scope
+#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope
struct Bar;
// Interpreted as an unstable custom attribute
-#[FooWithLongNan] //~ ERROR cannot find attribute macro `FooWithLongNan` in this scope
+#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope
struct Asdf;
#[derive(Dlone)]
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
index 2a5f2b8..3dca5ce 100644
--- a/src/test/ui/proc-macro/resolve-error.stderr
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -1,22 +1,22 @@
-error: cannot find macro `bang_proc_macrp!` in this scope
+error: cannot find macro `bang_proc_macrp` in this scope
--> $DIR/resolve-error.rs:56:5
|
LL | bang_proc_macrp!();
| ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
-error: cannot find macro `Dlona!` in this scope
+error: cannot find macro `Dlona` in this scope
--> $DIR/resolve-error.rs:53:5
|
LL | Dlona!();
| ^^^^^
-error: cannot find macro `attr_proc_macra!` in this scope
+error: cannot find macro `attr_proc_macra` in this scope
--> $DIR/resolve-error.rs:50:5
|
LL | attr_proc_macra!();
| ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
-error: cannot find macro `FooWithLongNama!` in this scope
+error: cannot find macro `FooWithLongNama` in this scope
--> $DIR/resolve-error.rs:47:5
|
LL | FooWithLongNama!();
@@ -40,13 +40,13 @@
LL | #[derive(Dlone)]
| ^^^^^ help: a derive macro with a similar name exists: `Clone`
-error: cannot find attribute macro `FooWithLongNan` in this scope
+error: cannot find attribute `FooWithLongNan` in this scope
--> $DIR/resolve-error.rs:31:3
|
LL | #[FooWithLongNan]
| ^^^^^^^^^^^^^^
-error: cannot find attribute macro `attr_proc_macra` in this scope
+error: cannot find attribute `attr_proc_macra` in this scope
--> $DIR/resolve-error.rs:27:3
|
LL | #[attr_proc_macra]
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.rs b/src/test/ui/reserved/reserved-attr-on-macro.rs
index fddb991..2630db0 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.rs
+++ b/src/test/ui/reserved/reserved-attr-on-macro.rs
@@ -1,5 +1,5 @@
#[rustc_attribute_should_be_reserved]
-//~^ ERROR cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+//~^ ERROR cannot find attribute `rustc_attribute_should_be_reserved` in this scope
//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
macro_rules! foo {
diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr
index 856162b..6859605 100644
--- a/src/test/ui/reserved/reserved-attr-on-macro.stderr
+++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr
@@ -15,7 +15,7 @@
|
= note: import resolution is stuck, try simplifying macro imports
-error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope
+error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope
--> $DIR/reserved-attr-on-macro.rs:1:3
|
LL | #[rustc_attribute_should_be_reserved]
diff --git a/src/test/ui/resolve/visibility-indeterminate.rs b/src/test/ui/resolve/visibility-indeterminate.rs
index 198ea75..0e1142d 100644
--- a/src/test/ui/resolve/visibility-indeterminate.rs
+++ b/src/test/ui/resolve/visibility-indeterminate.rs
@@ -1,6 +1,6 @@
// edition:2018
-foo!(); //~ ERROR cannot find macro `foo!` in this scope
+foo!(); //~ ERROR cannot find macro `foo` in this scope
pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility
diff --git a/src/test/ui/resolve/visibility-indeterminate.stderr b/src/test/ui/resolve/visibility-indeterminate.stderr
index 17927a5..b967829 100644
--- a/src/test/ui/resolve/visibility-indeterminate.stderr
+++ b/src/test/ui/resolve/visibility-indeterminate.stderr
@@ -4,7 +4,7 @@
LL | pub(in ::bar) struct Baz {}
| ^^^^^
-error: cannot find macro `foo!` in this scope
+error: cannot find macro `foo` in this scope
--> $DIR/visibility-indeterminate.rs:3:1
|
LL | foo!();
diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs
new file mode 100644
index 0000000..92e8588
--- /dev/null
+++ b/src/test/ui/save-analysis/issue-63663.rs
@@ -0,0 +1,28 @@
+// check-pass
+// compile-flags: -Zsave-analysis
+
+pub trait Trait {
+ type Assoc;
+}
+
+pub struct A;
+
+trait Generic<T> {}
+impl<T> Generic<T> for () {}
+
+// Don't ICE when resolving type paths in return type `impl Trait`
+fn assoc_in_opaque_type_bounds<U: Trait>() -> impl Generic<U::Assoc> {}
+
+// Check that this doesn't ICE when processing associated const in formal
+// argument and return type of functions defined inside function/method scope.
+pub fn func() {
+ fn _inner1<U: Trait>(_: U::Assoc) {}
+ fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() }
+
+ impl A {
+ fn _inner1<U: Trait>(self, _: U::Assoc) {}
+ fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs
index 844f13c..dfb7d65 100644
--- a/src/test/ui/self/self_type_keyword.rs
+++ b/src/test/ui/self/self_type_keyword.rs
@@ -19,7 +19,7 @@
ref mut Self => (),
//~^ ERROR expected identifier, found keyword `Self`
Self!() => (),
- //~^ ERROR cannot find macro `Self!` in this scope
+ //~^ ERROR cannot find macro `Self` in this scope
Foo { Self } => (),
//~^ ERROR expected identifier, found keyword `Self`
}
diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr
index bb63119..11b3b01 100644
--- a/src/test/ui/self/self_type_keyword.stderr
+++ b/src/test/ui/self/self_type_keyword.stderr
@@ -54,7 +54,7 @@
LL | struct Bar<'Self>;
| ^^^^^
-error: cannot find macro `Self!` in this scope
+error: cannot find macro `Self` in this scope
--> $DIR/self_type_keyword.rs:21:9
|
LL | Self!() => (),
diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs
index 74f63f2..7c8231b 100644
--- a/src/test/ui/suggestions/attribute-typos.rs
+++ b/src/test/ui/suggestions/attribute-typos.rs
@@ -1,11 +1,11 @@
-#[deprcated] //~ ERROR cannot find attribute macro `deprcated` in this scope
+#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope
fn foo() {}
-#[tests] //~ ERROR cannot find attribute macro `tests` in this scope
+#[tests] //~ ERROR cannot find attribute `tests` in this scope
fn bar() {}
#[rustc_err]
-//~^ ERROR cannot find attribute macro `rustc_err` in this scope
+//~^ ERROR cannot find attribute `rustc_err` in this scope
//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
fn main() {}
diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr
index 6b2f591..e403293 100644
--- a/src/test/ui/suggestions/attribute-typos.stderr
+++ b/src/test/ui/suggestions/attribute-typos.stderr
@@ -7,19 +7,19 @@
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
-error: cannot find attribute macro `rustc_err` in this scope
+error: cannot find attribute `rustc_err` in this scope
--> $DIR/attribute-typos.rs:7:3
|
LL | #[rustc_err]
| ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
-error: cannot find attribute macro `tests` in this scope
+error: cannot find attribute `tests` in this scope
--> $DIR/attribute-typos.rs:4:3
|
LL | #[tests]
| ^^^^^ help: an attribute macro with a similar name exists: `test`
-error: cannot find attribute macro `deprcated` in this scope
+error: cannot find attribute `deprcated` in this scope
--> $DIR/attribute-typos.rs:1:3
|
LL | #[deprcated]
diff --git a/src/test/ui/syntax-extension-minor.rs b/src/test/ui/syntax-extension-minor.rs
index 0206a76..2d6710a 100644
--- a/src/test/ui/syntax-extension-minor.rs
+++ b/src/test/ui/syntax-extension-minor.rs
@@ -1,3 +1,5 @@
+// run-pass
+
#![feature(concat_idents)]
pub fn main() {
@@ -5,10 +7,8 @@
let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions
let asdf_fdsa = "<.<".to_string();
- // this now fails (correctly, I claim) because hygiene prevents
- // the assembled identifier from being a reference to the binding.
+ // concat_idents should have call-site hygiene.
assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
- //~^ ERROR cannot find value `asdf_fdsa` in this scope
assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction");
}
diff --git a/src/test/ui/syntax-extension-minor.stderr b/src/test/ui/syntax-extension-minor.stderr
deleted file mode 100644
index 2d8056d..0000000
--- a/src/test/ui/syntax-extension-minor.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `asdf_fdsa` in this scope
- --> $DIR/syntax-extension-minor.rs:10:13
- |
-LL | assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
index c07da43..d5698be 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.rs
@@ -5,13 +5,13 @@
struct S;
// Interpreted as an unstable custom attribute
-#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+#[rustfmt] //~ ERROR cannot find attribute `rustfmt` in this scope
fn check() {}
#[rustfmt::skip] // OK
fn main() {
rustfmt; //~ ERROR expected value, found tool module `rustfmt`
- rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+ rustfmt!(); //~ ERROR cannot find macro `rustfmt` in this scope
rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip`
}
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
index 33581a1..6bef793 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -4,13 +4,13 @@
LL | #[derive(rustfmt)]
| ^^^^^^^
-error: cannot find attribute macro `rustfmt` in this scope
+error: cannot find attribute `rustfmt` in this scope
--> $DIR/tool-attributes-misplaced-1.rs:8:3
|
LL | #[rustfmt]
| ^^^^^^^
-error: cannot find macro `rustfmt!` in this scope
+error: cannot find macro `rustfmt` in this scope
--> $DIR/tool-attributes-misplaced-1.rs:14:5
|
LL | rustfmt!();
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9ffa939..eab23f3 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -1,3 +1,9 @@
+//! Build a dist manifest, hash and sign everything.
+//! This gets called by `promote-release`
+//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
+//! via `x.py dist hash-and-sign`; the cmdline arguments are set up
+//! by rustbuild (in `src/bootstrap/dist.rs`).
+
use toml;
use serde::Serialize;
@@ -270,6 +276,7 @@
// Do not ask for a passphrase while manually testing
let mut passphrase = String::new();
if should_sign {
+ // `x.py` passes the passphrase via stdin.
t!(io::stdin().read_to_string(&mut passphrase));
}
@@ -362,6 +369,7 @@
}
}
+ /// 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()) {
let filename = file.file_name().unwrap().to_str().unwrap();
@@ -532,19 +540,20 @@
.as_ref()
.cloned()
.map(|version| (version, true))
- .unwrap_or_default();
+ .unwrap_or_default(); // `is_present` defaults to `false` here.
- // miri needs to build std with xargo, which doesn't allow stable/beta:
- // <https://github.com/japaric/xargo/pull/204#issuecomment-374888868>
+ // Miri is nightly-only; never ship it for other trains.
if pkgname == "miri-preview" && self.rust_release != "nightly" {
- is_present = false; // ignore it
+ is_present = false; // Pretend the component is entirely missing.
}
let targets = targets.iter().map(|name| {
if is_present {
+ // The component generally exists, but it might still be missing for this target.
let filename = self.filename(pkgname, name);
let digest = match self.digests.remove(&filename) {
Some(digest) => digest,
+ // This component does not exist for this target -- skip it.
None => return (name.to_string(), Target::unavailable()),
};
let xz_filename = filename.replace(".tar.gz", ".tar.xz");
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 467b777..7c51de5 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -253,7 +253,7 @@
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", opts.usage(&message));
- println!("");
+ println!();
panic!()
}
@@ -265,7 +265,7 @@
if matches.opt_present("h") || matches.opt_present("help") {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", opts.usage(&message));
- println!("");
+ println!();
panic!()
}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index aff5546..baed27d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2593,7 +2593,7 @@
" actual: {}",
codegen_units_to_str(&actual_item.codegen_units)
);
- println!("");
+ println!();
}
}
@@ -3526,7 +3526,7 @@
}
}
}
- println!("");
+ println!();
}
}
}
diff --git a/src/tools/miri b/src/tools/miri
index dd94c7c..d881387 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit dd94c7c5a32be2ee0adeeaf9d46f26f14925797c
+Subproject commit d88138723780d11ca2c09560111223dc20b9d5f3
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 2e2505b..7cf3cc7 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -7,6 +7,8 @@
## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts
## when a new commit lands on `master` (i.e., after it passed all checks on `auto`).
+from __future__ import print_function
+
import sys
import re
import os
@@ -20,21 +22,26 @@
import urllib.request as urllib2
# List of people to ping when the status of a tool or a book changed.
+# These should be collaborators of the rust-lang/rust repository (with at least
+# read privileges on it). CI will fail otherwise.
MAINTAINERS = {
- 'miri': '@oli-obk @RalfJung @eddyb',
- 'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk @phansch @flip1995 @yaahc',
- 'rls': '@Xanewok',
- 'rustfmt': '@topecongiro',
- 'book': '@carols10cents @steveklabnik',
- 'nomicon': '@frewsxcv @Gankro',
- 'reference': '@steveklabnik @Havvy @matthewjasper @ehuss',
- 'rust-by-example': '@steveklabnik @marioidival @projektir',
- 'embedded-book': (
- '@adamgreig @andre-richter @jamesmunns @korken89 '
- '@ryankurte @thejpster @therealprof'
- ),
- 'edition-guide': '@ehuss @Centril @steveklabnik',
- 'rustc-guide': '@mark-i-m @spastorino @amanjeev'
+ 'miri': {'oli-obk', 'RalfJung', 'eddyb'},
+ 'clippy-driver': {
+ 'Manishearth', 'llogiq', 'mcarton', 'oli-obk', 'phansch', 'flip1995',
+ 'yaahc',
+ },
+ 'rls': {'Xanewok'},
+ 'rustfmt': {'topecongiro'},
+ 'book': {'carols10cents', 'steveklabnik'},
+ 'nomicon': {'frewsxcv', 'Gankra'},
+ 'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'},
+ 'rust-by-example': {'steveklabnik', 'marioidival'},
+ 'embedded-book': {
+ 'adamgreig', 'andre-richter', 'jamesmunns', 'korken89',
+ 'ryankurte', 'thejpster', 'therealprof',
+ },
+ 'edition-guide': {'ehuss', 'Centril', 'steveklabnik'},
+ 'rustc-guide': {'mark-i-m', 'spastorino', 'amanjeev'},
}
REPOS = {
@@ -52,6 +59,50 @@
}
+def validate_maintainers(repo, github_token):
+ '''Ensure all maintainers are assignable on a GitHub repo'''
+ next_link_re = re.compile(r'<([^>]+)>; rel="next"')
+
+ # Load the list of assignable people in the GitHub repo
+ assignable = []
+ url = 'https://api.github.com/repos/%s/collaborators?per_page=100' % repo
+ while url is not None:
+ response = urllib2.urlopen(urllib2.Request(url, headers={
+ 'Authorization': 'token ' + github_token,
+ # Properly load nested teams.
+ 'Accept': 'application/vnd.github.hellcat-preview+json',
+ }))
+ assignable.extend(user['login'] for user in json.load(response))
+ # Load the next page if available
+ url = None
+ link_header = response.headers.get('Link')
+ if link_header:
+ matches = next_link_re.match(link_header)
+ if matches is not None:
+ url = matches.group(1)
+
+ errors = False
+ for tool, maintainers in MAINTAINERS.items():
+ for maintainer in maintainers:
+ if maintainer not in assignable:
+ errors = True
+ print(
+ "error: %s maintainer @%s is not assignable in the %s repo"
+ % (tool, maintainer, repo),
+ )
+
+ if errors:
+ print()
+ print(" To be assignable, a person needs to be explicitly listed as a")
+ print(" collaborator in the repository settings. The simple way to")
+ print(" fix this is to ask someone with 'admin' privileges on the repo")
+ print(" to add the person or whole team as a collaborator with 'read'")
+ print(" privileges. Those privileges don't grant any extra permissions")
+ print(" so it's safe to apply them.")
+ print()
+ print("The build will fail due to this.")
+ exit(1)
+
def read_current_status(current_commit, path):
'''Reads build status of `current_commit` from content of `history/*.tsv`
'''
@@ -73,13 +124,12 @@
def issue(
tool,
status,
- maintainers,
+ assignees,
relevant_pr_number,
relevant_pr_user,
pr_reviewer,
):
# Open an issue about the toolstate failure.
- assignees = [x.strip() for x in maintainers.split('@') if x != '']
if status == 'test-fail':
status_description = 'has failing tests'
else:
@@ -100,7 +150,7 @@
REPOS.get(tool), relevant_pr_user, pr_reviewer
)),
'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
- 'assignees': assignees,
+ 'assignees': list(assignees),
'labels': ['T-compiler', 'I-nominated'],
})
print("Creating issue:\n{}".format(request))
@@ -150,22 +200,32 @@
old = status[os]
new = s.get(tool, old)
status[os] = new
- if new > old: # comparing the strings, but they are ordered appropriately!
+ maintainers = ' '.join('@'+name for name in MAINTAINERS[tool])
+ # 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' \
- .format(tool, os, old, new, MAINTAINERS.get(tool))
+ .format(tool, os, old, new, maintainers)
elif new < old:
# tests or builds are failing and were not failing before
changed = True
title = '💔 {} on {}: {} → {}' \
.format(tool, os, old, new)
message += '{} (cc {}, @rust-lang/infra).\n' \
- .format(title, MAINTAINERS.get(tool))
- # 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
+ .format(title, maintainers)
+ # 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:
@@ -200,6 +260,16 @@
if __name__ == '__main__':
+ repo = os.environ.get('TOOLSTATE_VALIDATE_MAINTAINERS_REPO')
+ if repo:
+ github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
+ if github_token:
+ validate_maintainers(repo, github_token)
+ else:
+ print('skipping toolstate maintainers validation since no GitHub token is present')
+ # When validating maintainers don't run the full script.
+ exit(0)
+
cur_commit = sys.argv[1]
cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
cur_commit_msg = sys.argv[2]
diff --git a/src/tools/rls b/src/tools/rls
index 412fb00..d9aa23a 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 412fb00b37afb6b7f7fa96a35f2315c7e640b916
+Subproject commit d9aa23a43ad29e3a10551a1425ef5d5baef28d70
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index d068e1c..930279c 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -62,7 +62,6 @@
serde = { version = "1.0.82", features = ['derive'] }
serde_json = { version = "1.0.31", features = ["raw_value"] }
smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
-byteorder = { version = "1.2.7", features = ["i128"] }
[target.'cfg(not(windows))'.dependencies]